Merge pull request #480 from thomasvl/objc_beta_drop

Beta quality drop of Objective C Support.
diff --git a/Makefile.am b/Makefile.am
index 28e55cd..3e87c51 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -506,14 +506,10 @@
   objectivec/GPBDictionary.h                                                 \
   objectivec/GPBDictionary.m                                                 \
   objectivec/GPBDictionary_PackagePrivate.h                                  \
-  objectivec/GPBExtensionField.h                                             \
-  objectivec/GPBExtensionField.m                                             \
-  objectivec/GPBExtensionField_PackagePrivate.h                              \
+  objectivec/GPBExtensionInternals.h                                         \
+  objectivec/GPBExtensionInternals.m                                         \
   objectivec/GPBExtensionRegistry.h                                          \
   objectivec/GPBExtensionRegistry.m                                          \
-  objectivec/GPBField.h                                                      \
-  objectivec/GPBField.m                                                      \
-  objectivec/GPBField_PackagePrivate.h                                       \
   objectivec/GPBMessage.h                                                    \
   objectivec/GPBMessage.m                                                    \
   objectivec/GPBMessage_PackagePrivate.h                                     \
@@ -523,7 +519,10 @@
   objectivec/GPBRootObject.h                                                 \
   objectivec/GPBRootObject.m                                                 \
   objectivec/GPBRootObject_PackagePrivate.h                                  \
-  objectivec/GPBTypes.h                                                      \
+  objectivec/GPBRuntimeTypes.h                                               \
+  objectivec/GPBUnknownField.h                                               \
+  objectivec/GPBUnknownField.m                                               \
+  objectivec/GPBUnknownField_PackagePrivate.h                                \
   objectivec/GPBUnknownFieldSet.h                                            \
   objectivec/GPBUnknownFieldSet.m                                            \
   objectivec/GPBUnknownFieldSet_PackagePrivate.h                             \
@@ -547,8 +546,6 @@
   objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
   objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
   objectivec/README.md                                                       \
-  objectivec/Tests/Filter1.txt                                               \
-  objectivec/Tests/Filter2.txt                                               \
   objectivec/Tests/golden_message                                            \
   objectivec/Tests/golden_packed_fields_message                              \
   objectivec/Tests/GPBARCUnittestProtos.m                                    \
@@ -564,7 +561,6 @@
   objectivec/Tests/GPBDictionaryTests+UInt32.m                               \
   objectivec/Tests/GPBDictionaryTests+UInt64.m                               \
   objectivec/Tests/GPBDictionaryTests.pddm                                   \
-  objectivec/Tests/GPBFilteredMessageTests.m                                 \
   objectivec/Tests/GPBMessageTests+Merge.m                                   \
   objectivec/Tests/GPBMessageTests+Runtime.m                                 \
   objectivec/Tests/GPBMessageTests+Serialization.m                           \
@@ -596,8 +592,6 @@
   objectivec/Tests/text_format_map_unittest_data.txt                          \
   objectivec/Tests/text_format_unittest_data.txt                              \
   objectivec/Tests/unittest_cycle.proto                                       \
-  objectivec/Tests/unittest_filter.proto                                      \
-  objectivec/Tests/unittest_name_mangling.proto                               \
   objectivec/Tests/unittest_objc.proto                                        \
   objectivec/Tests/unittest_runtime_proto2.proto                              \
   objectivec/Tests/unittest_runtime_proto3.proto                              \
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
new file mode 100755
index 0000000..f414bd8
--- /dev/null
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+
+# Invoked by the Xcode projects to build the protos needed for the unittests.
+
+set -eu
+
+readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos"
+
+# Helper for bailing.
+die() {
+  echo "Error: $1"
+  exit 2
+}
+
+# What to do.
+case "${ACTION}" in
+  "")
+    # Build, fall thru
+    ;;
+  "clean")
+    rm -rf "${OUTPUT_DIR}"
+    exit 0
+    ;;
+  *)
+    die "Unknown action requested: ${ACTION}"
+    ;;
+esac
+
+# Move to the top of the protobuf directories.
+cd "${SRCROOT}/.."
+
+[[ -x src/protoc ]] || \
+  die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)."
+
+RUN_PROTOC=no
+if [[ ! -d "${OUTPUT_DIR}" ]] ; then
+  RUN_PROTOC=yes
+else
+  # Find the newest input file (protos, compiler, and this script).
+  # (these patterns catch some extra stuff, but better to over sample than
+  # under)
+  readonly NewestInput=$(find \
+     src/google/protobuf/*.proto \
+     objectivec/Tests/*.proto \
+     src/.libs src/*.la src/protoc \
+     objectivec/DevTools/compile_testing_protos.sh \
+        -type f -print0 \
+        | xargs -0 stat -f "%m %N" \
+        | sort -n | tail -n1 | cut -f2- -d" ")
+  # Find the oldest output file.
+  readonly OldestOutput=$(find \
+        "${OUTPUT_DIR}" \
+        -type f -print0 \
+        | xargs -0 stat -f "%m %N" \
+        | sort -n -r | tail -n1 | cut -f2- -d" ")
+  # If the newest input is newer than the oldest output, regenerate.
+  if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then
+    RUN_PROTOC=yes
+  fi
+fi
+
+if [[ "${RUN_PROTOC}" != "yes" ]] ; then
+  # Up to date.
+  exit 0
+fi
+
+# Ensure the output dir exists
+mkdir -p "${OUTPUT_DIR}/google/protobuf"
+
+CORE_PROTO_FILES=(                                         \
+  src/google/protobuf/unittest_custom_options.proto        \
+  src/google/protobuf/unittest_enormous_descriptor.proto   \
+  src/google/protobuf/unittest_embed_optimize_for.proto    \
+  src/google/protobuf/unittest_empty.proto                 \
+  src/google/protobuf/unittest_import.proto                \
+  src/google/protobuf/unittest_import_lite.proto           \
+  src/google/protobuf/unittest_lite.proto                  \
+  src/google/protobuf/unittest_mset.proto                  \
+  src/google/protobuf/unittest_no_generic_services.proto   \
+  src/google/protobuf/unittest_optimize_for.proto          \
+  src/google/protobuf/unittest.proto                       \
+  src/google/protobuf/unittest_import_public.proto         \
+  src/google/protobuf/unittest_import_public_lite.proto    \
+  src/google/protobuf/unittest_drop_unknown_fields.proto   \
+  src/google/protobuf/unittest_preserve_unknown_enum.proto \
+  src/google/protobuf/map_lite_unittest.proto              \
+  src/google/protobuf/map_proto2_unittest.proto            \
+  src/google/protobuf/map_unittest.proto                   \
+)
+
+compile_proto() {
+  src/protoc                                   \
+    --objc_out="${OUTPUT_DIR}/google/protobuf" \
+    --proto_path=src/google/protobuf/          \
+    --proto_path=src                           \
+    $*
+}
+
+for a_proto in "${CORE_PROTO_FILES[@]}" ; do
+  compile_proto "${a_proto}"
+done
+
+OBJC_PROTO_FILES=(                               \
+  objectivec/Tests/unittest_cycle.proto          \
+  objectivec/Tests/unittest_runtime_proto2.proto \
+  objectivec/Tests/unittest_runtime_proto3.proto \
+  objectivec/Tests/unittest_objc.proto           \
+  objectivec/Tests/unittest_objc_startup.proto   \
+)
+
+for a_proto in "${OBJC_PROTO_FILES[@]}" ; do
+  compile_proto --proto_path="objectivec/Tests" "${a_proto}"
+done
diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh
index 57c4f43..2192b76 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -162,7 +162,7 @@
 wrapped_make -j "${NUM_MAKE_JOBS}" check
 
 header "Ensuring the ObjC descriptors are current."
-# Find the newest input file (protos, compiler, and this script).
+# Find the newest input file (protos, compiler, and the generator script).
 # (these patterns catch some extra stuff, but better to over sample than under)
 readonly NewestInput=$(find \
    src/google/protobuf/*.proto \
diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h
index 3fcba7a..b486f27 100644
--- a/objectivec/GPBArray.h
+++ b/objectivec/GPBArray.h
@@ -30,7 +30,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 
 // These classes are used for repeated fields of basic data types. They are used because
 // they perform better than boxing into NSNumbers in NSArrays.
diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h
index e9b27e2..b71ee87 100644
--- a/objectivec/GPBCodedInputStream.h
+++ b/objectivec/GPBCodedInputStream.h
@@ -60,7 +60,7 @@
 - (int64_t)readSInt64;
 - (BOOL)readBool;
 - (NSString *)readString;
-- (NSData *)readData;
+- (NSData *)readBytes;
 
 // Read an embedded message field value from the stream.
 - (void)readMessage:(GPBMessage *)message
diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m
index 79d31fc..71758ba 100644
--- a/objectivec/GPBCodedInputStream.m
+++ b/objectivec/GPBCodedInputStream.m
@@ -38,7 +38,7 @@
 
 static const NSUInteger kDefaultRecursionLimit = 64;
 
-static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) {
+static void CheckSize(GPBCodedInputStreamState *state, size_t size) {
   size_t newSize = state->bufferPos + size;
   if (newSize > state->bufferSize) {
     [NSException raise:NSParseErrorException format:@""];
@@ -50,26 +50,26 @@
   }
 }
 
-static inline int8_t ReadRawByte(GPBCodedInputStreamState *state) {
+static int8_t ReadRawByte(GPBCodedInputStreamState *state) {
   CheckSize(state, sizeof(int8_t));
   return ((int8_t *)state->bytes)[state->bufferPos++];
 }
 
-static inline int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) {
+static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) {
   CheckSize(state, sizeof(int32_t));
   int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos);
   state->bufferPos += sizeof(int32_t);
   return value;
 }
 
-static inline int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
+static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
   CheckSize(state, sizeof(int64_t));
   int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos);
   state->bufferPos += sizeof(int64_t);
   return value;
 }
 
-static inline int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
+static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
   int8_t tmp = ReadRawByte(state);
   if (tmp >= 0) {
     return tmp;
@@ -104,7 +104,7 @@
   return result;
 }
 
-static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
+static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
   int32_t shift = 0;
   int64_t result = 0;
   while (shift < 64) {
@@ -119,7 +119,7 @@
   return 0;
 }
 
-static inline void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
+static void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
   CheckSize(state, size);
   state->bufferPos += size;
 }
@@ -222,7 +222,7 @@
   return result;
 }
 
-NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) {
+NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) {
   int32_t size = ReadRawVarint32(state);
   if (size < 0) return nil;
   CheckSize(state, size);
@@ -232,7 +232,7 @@
   return result;
 }
 
-NSData *GPBCodedInputStreamReadRetainedDataNoCopy(
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
     GPBCodedInputStreamState *state) {
   int32_t size = ReadRawVarint32(state);
   if (size < 0) return nil;
@@ -453,8 +453,8 @@
   GPBCodedInputStreamPopLimit(&state_, oldLimit);
 }
 
-- (NSData *)readData {
-  return [GPBCodedInputStreamReadRetainedData(&state_) autorelease];
+- (NSData *)readBytes {
+  return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease];
 }
 
 - (uint32_t)readUInt32 {
@@ -499,7 +499,7 @@
 
 // Returns true if the passed in bytes are 7 bit ascii.
 // This routine needs to be fast.
-static inline bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) {
+static bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) {
 // In the loops below, it's more efficient to collect rather than do
 // conditional at every step.
 #if __LP64__
@@ -587,7 +587,7 @@
   return true;
 }
 
-static inline void GPBStringInitStringValue(GPBString *string) {
+static void GPBStringInitStringValue(GPBString *string) {
   OSSpinLockLock(&string->lock_);
   GPBStringInitStringValueAlreadyLocked(string);
   OSSpinLockUnlock(&string->lock_);
diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h
index ba6471e..e482b4c 100644
--- a/objectivec/GPBCodedInputStream_PackagePrivate.h
+++ b/objectivec/GPBCodedInputStream_PackagePrivate.h
@@ -114,9 +114,9 @@
 BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state);
 NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state)
     __attribute((ns_returns_retained));
-NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state)
+NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
     __attribute((ns_returns_retained));
-NSData *GPBCodedInputStreamReadRetainedDataNoCopy(
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
     GPBCodedInputStreamState *state) __attribute((ns_returns_retained));
 
 size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h
index 1f1eb38..9a237b6 100644
--- a/objectivec/GPBCodedOutputStream.h
+++ b/objectivec/GPBCodedOutputStream.h
@@ -30,7 +30,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 #import "GPBWireFormat.h"
 
 @class GPBBoolArray;
@@ -84,110 +84,110 @@
 // This block of code is generated, do not edit it directly.
 
 - (void)writeDouble:(int32_t)fieldNumber value:(double)value;
-- (void)writeDoubles:(int32_t)fieldNumber
-              values:(GPBDoubleArray *)values
-                 tag:(uint32_t)tag;
+- (void)writeDoubleArray:(int32_t)fieldNumber
+                  values:(GPBDoubleArray *)values
+                     tag:(uint32_t)tag;
 - (void)writeDoubleNoTag:(double)value;
 
 - (void)writeFloat:(int32_t)fieldNumber value:(float)value;
-- (void)writeFloats:(int32_t)fieldNumber
-             values:(GPBFloatArray *)values
-                tag:(uint32_t)tag;
+- (void)writeFloatArray:(int32_t)fieldNumber
+                 values:(GPBFloatArray *)values
+                    tag:(uint32_t)tag;
 - (void)writeFloatNoTag:(float)value;
 
 - (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value;
-- (void)writeUInt64s:(int32_t)fieldNumber
-              values:(GPBUInt64Array *)values
-                 tag:(uint32_t)tag;
+- (void)writeUInt64Array:(int32_t)fieldNumber
+                  values:(GPBUInt64Array *)values
+                     tag:(uint32_t)tag;
 - (void)writeUInt64NoTag:(uint64_t)value;
 
 - (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value;
-- (void)writeInt64s:(int32_t)fieldNumber
-             values:(GPBInt64Array *)values
-                tag:(uint32_t)tag;
+- (void)writeInt64Array:(int32_t)fieldNumber
+                 values:(GPBInt64Array *)values
+                    tag:(uint32_t)tag;
 - (void)writeInt64NoTag:(int64_t)value;
 
 - (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value;
-- (void)writeInt32s:(int32_t)fieldNumber
-             values:(GPBInt32Array *)values
-                tag:(uint32_t)tag;
+- (void)writeInt32Array:(int32_t)fieldNumber
+                 values:(GPBInt32Array *)values
+                    tag:(uint32_t)tag;
 - (void)writeInt32NoTag:(int32_t)value;
 
 - (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value;
-- (void)writeUInt32s:(int32_t)fieldNumber
-              values:(GPBUInt32Array *)values
-                 tag:(uint32_t)tag;
+- (void)writeUInt32Array:(int32_t)fieldNumber
+                  values:(GPBUInt32Array *)values
+                     tag:(uint32_t)tag;
 - (void)writeUInt32NoTag:(uint32_t)value;
 
 - (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value;
-- (void)writeFixed64s:(int32_t)fieldNumber
-               values:(GPBUInt64Array *)values
-                  tag:(uint32_t)tag;
+- (void)writeFixed64Array:(int32_t)fieldNumber
+                   values:(GPBUInt64Array *)values
+                      tag:(uint32_t)tag;
 - (void)writeFixed64NoTag:(uint64_t)value;
 
 - (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value;
-- (void)writeFixed32s:(int32_t)fieldNumber
-               values:(GPBUInt32Array *)values
-                  tag:(uint32_t)tag;
+- (void)writeFixed32Array:(int32_t)fieldNumber
+                   values:(GPBUInt32Array *)values
+                      tag:(uint32_t)tag;
 - (void)writeFixed32NoTag:(uint32_t)value;
 
 - (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value;
-- (void)writeSInt32s:(int32_t)fieldNumber
-              values:(GPBInt32Array *)values
-                 tag:(uint32_t)tag;
+- (void)writeSInt32Array:(int32_t)fieldNumber
+                  values:(GPBInt32Array *)values
+                     tag:(uint32_t)tag;
 - (void)writeSInt32NoTag:(int32_t)value;
 
 - (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value;
-- (void)writeSInt64s:(int32_t)fieldNumber
-              values:(GPBInt64Array *)values
-                 tag:(uint32_t)tag;
+- (void)writeSInt64Array:(int32_t)fieldNumber
+                  values:(GPBInt64Array *)values
+                     tag:(uint32_t)tag;
 - (void)writeSInt64NoTag:(int64_t)value;
 
 - (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value;
-- (void)writeSFixed64s:(int32_t)fieldNumber
-                values:(GPBInt64Array *)values
-                   tag:(uint32_t)tag;
+- (void)writeSFixed64Array:(int32_t)fieldNumber
+                    values:(GPBInt64Array *)values
+                       tag:(uint32_t)tag;
 - (void)writeSFixed64NoTag:(int64_t)value;
 
 - (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value;
-- (void)writeSFixed32s:(int32_t)fieldNumber
-                values:(GPBInt32Array *)values
-                   tag:(uint32_t)tag;
+- (void)writeSFixed32Array:(int32_t)fieldNumber
+                    values:(GPBInt32Array *)values
+                       tag:(uint32_t)tag;
 - (void)writeSFixed32NoTag:(int32_t)value;
 
 - (void)writeBool:(int32_t)fieldNumber value:(BOOL)value;
-- (void)writeBools:(int32_t)fieldNumber
-            values:(GPBBoolArray *)values
-               tag:(uint32_t)tag;
+- (void)writeBoolArray:(int32_t)fieldNumber
+                values:(GPBBoolArray *)values
+                   tag:(uint32_t)tag;
 - (void)writeBoolNoTag:(BOOL)value;
 
 - (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value;
-- (void)writeEnums:(int32_t)fieldNumber
-            values:(GPBEnumArray *)values
-               tag:(uint32_t)tag;
+- (void)writeEnumArray:(int32_t)fieldNumber
+                values:(GPBEnumArray *)values
+                   tag:(uint32_t)tag;
 - (void)writeEnumNoTag:(int32_t)value;
 
 - (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
-- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values;
 - (void)writeStringNoTag:(NSString *)value;
 
 - (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
-- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values;
 - (void)writeMessageNoTag:(GPBMessage *)value;
 
-- (void)writeData:(int32_t)fieldNumber value:(NSData *)value;
-- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values;
-- (void)writeDataNoTag:(NSData *)value;
+- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value;
+- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeBytesNoTag:(NSData *)value;
 
 - (void)writeGroup:(int32_t)fieldNumber
              value:(GPBMessage *)value;
-- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values;
 - (void)writeGroupNoTag:(int32_t)fieldNumber
                   value:(GPBMessage *)value;
 
 - (void)writeUnknownGroup:(int32_t)fieldNumber
                     value:(GPBUnknownFieldSet *)value;
-- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values;
 - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
                          value:(GPBUnknownFieldSet *)value;
 
@@ -230,7 +230,7 @@
     __attribute__((const));
 size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value)
     __attribute__((const));
-size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value)
+size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value)
     __attribute__((const));
 size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value)
     __attribute__((const));
@@ -243,7 +243,7 @@
 size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value)
     __attribute__((const));
 size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const));
-size_t GPBComputeWireFormatTagSize(int field_number, GPBType type)
+size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType)
     __attribute__((const));
 
 size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const));
@@ -259,7 +259,7 @@
 size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value)
     __attribute__((const));
 size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const));
-size_t GPBComputeDataSizeNoTag(NSData *value) __attribute__((const));
+size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const));
 size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const));
 size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const));
 size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const));
@@ -297,22 +297,22 @@
 // Write methods for types that can be in packed arrays.
 //%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE)
 //%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
-//%- (void)write##NAME##s:(int32_t)fieldNumber
-//%       NAME$S values:(GPB##ARRAY_TYPE##Array *)values
-//%       NAME$S    tag:(uint32_t)tag;
+//%- (void)write##NAME##Array:(int32_t)fieldNumber
+//%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
+//%       NAME$S        tag:(uint32_t)tag;
 //%- (void)write##NAME##NoTag:(TYPE)value;
 //%
 // Write methods for types that aren't in packed arrays.
 //%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
 //%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
-//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values;
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values;
 //%- (void)write##NAME##NoTag:(TYPE)value;
 //%
 // Special write methods for Groups.
 //%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
 //%- (void)write##NAME:(int32_t)fieldNumber
 //%       NAME$S value:(TYPE)value;
-//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values;
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values;
 //%- (void)write##NAME##NoTag:(int32_t)fieldNumber
 //%            NAME$S value:(TYPE)value;
 //%
@@ -335,6 +335,6 @@
 //%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t)
 //%_WRITE_UNPACKABLE_DECLS(String, NSString *)
 //%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage *)
-//%_WRITE_UNPACKABLE_DECLS(Data, NSData *)
+//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData *)
 //%_WRITE_GROUP_DECLS(Group, GPBMessage *)
 //%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet *)
diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m
index 9604c12..eb4900f 100644
--- a/objectivec/GPBCodedOutputStream.m
+++ b/objectivec/GPBCodedOutputStream.m
@@ -372,14 +372,14 @@
   [self writeMessageNoTag:value];
 }
 
-- (void)writeDataNoTag:(NSData *)value {
+- (void)writeBytesNoTag:(NSData *)value {
   GPBWriteRawVarint32(&state_, (int32_t)[value length]);
   [self writeRawData:value];
 }
 
-- (void)writeData:(int32_t)fieldNumber value:(NSData *)value {
+- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value {
   GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
-  [self writeDataNoTag:value];
+  [self writeBytesNoTag:value];
 }
 
 - (void)writeUInt32NoTag:(uint32_t)value {
@@ -436,9 +436,9 @@
 }
 
 //%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME)
-//%- (void)write##NAME##s:(int32_t)fieldNumber
-//%       NAME$S values:(GPB##ARRAY_TYPE##Array *)values
-//%       NAME$S    tag:(uint32_t)tag {
+//%- (void)write##NAME##Array:(int32_t)fieldNumber
+//%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
+//%       NAME$S        tag:(uint32_t)tag {
 //%  if (tag != 0) {
 //%    if (values.count == 0) return;
 //%    __block size_t dataSize = 0;
@@ -461,7 +461,7 @@
 //%}
 //%
 //%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE)
-//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values {
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values {
 //%  for (TYPE *value in values) {
 //%    [self write##NAME:fieldNumber value:value];
 //%  }
@@ -470,9 +470,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeDoubles:(int32_t)fieldNumber
-              values:(GPBDoubleArray *)values
-                 tag:(uint32_t)tag {
+- (void)writeDoubleArray:(int32_t)fieldNumber
+                  values:(GPBDoubleArray *)values
+                     tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -497,9 +497,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeFloats:(int32_t)fieldNumber
-             values:(GPBFloatArray *)values
-                tag:(uint32_t)tag {
+- (void)writeFloatArray:(int32_t)fieldNumber
+                 values:(GPBFloatArray *)values
+                    tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -524,9 +524,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeUInt64s:(int32_t)fieldNumber
-              values:(GPBUInt64Array *)values
-                 tag:(uint32_t)tag {
+- (void)writeUInt64Array:(int32_t)fieldNumber
+                  values:(GPBUInt64Array *)values
+                     tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -551,9 +551,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeInt64s:(int32_t)fieldNumber
-             values:(GPBInt64Array *)values
-                tag:(uint32_t)tag {
+- (void)writeInt64Array:(int32_t)fieldNumber
+                 values:(GPBInt64Array *)values
+                    tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -578,9 +578,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeInt32s:(int32_t)fieldNumber
-             values:(GPBInt32Array *)values
-                tag:(uint32_t)tag {
+- (void)writeInt32Array:(int32_t)fieldNumber
+                 values:(GPBInt32Array *)values
+                    tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -605,9 +605,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeUInt32s:(int32_t)fieldNumber
-              values:(GPBUInt32Array *)values
-                 tag:(uint32_t)tag {
+- (void)writeUInt32Array:(int32_t)fieldNumber
+                  values:(GPBUInt32Array *)values
+                     tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -632,9 +632,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeFixed64s:(int32_t)fieldNumber
-               values:(GPBUInt64Array *)values
-                  tag:(uint32_t)tag {
+- (void)writeFixed64Array:(int32_t)fieldNumber
+                   values:(GPBUInt64Array *)values
+                      tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -659,9 +659,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeFixed32s:(int32_t)fieldNumber
-               values:(GPBUInt32Array *)values
-                  tag:(uint32_t)tag {
+- (void)writeFixed32Array:(int32_t)fieldNumber
+                   values:(GPBUInt32Array *)values
+                      tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -686,9 +686,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeSInt32s:(int32_t)fieldNumber
-              values:(GPBInt32Array *)values
-                 tag:(uint32_t)tag {
+- (void)writeSInt32Array:(int32_t)fieldNumber
+                  values:(GPBInt32Array *)values
+                     tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -713,9 +713,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeSInt64s:(int32_t)fieldNumber
-              values:(GPBInt64Array *)values
-                 tag:(uint32_t)tag {
+- (void)writeSInt64Array:(int32_t)fieldNumber
+                  values:(GPBInt64Array *)values
+                     tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -740,9 +740,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeSFixed64s:(int32_t)fieldNumber
-                values:(GPBInt64Array *)values
-                   tag:(uint32_t)tag {
+- (void)writeSFixed64Array:(int32_t)fieldNumber
+                    values:(GPBInt64Array *)values
+                       tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -767,9 +767,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeSFixed32s:(int32_t)fieldNumber
-                values:(GPBInt32Array *)values
-                   tag:(uint32_t)tag {
+- (void)writeSFixed32Array:(int32_t)fieldNumber
+                    values:(GPBInt32Array *)values
+                       tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -794,9 +794,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, )
 // This block of code is generated, do not edit it directly.
 
-- (void)writeBools:(int32_t)fieldNumber
-            values:(GPBBoolArray *)values
-               tag:(uint32_t)tag {
+- (void)writeBoolArray:(int32_t)fieldNumber
+                values:(GPBBoolArray *)values
+                   tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -821,9 +821,9 @@
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeEnums:(int32_t)fieldNumber
-            values:(GPBEnumArray *)values
-               tag:(uint32_t)tag {
+- (void)writeEnumArray:(int32_t)fieldNumber
+                values:(GPBEnumArray *)values
+                   tag:(uint32_t)tag {
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
@@ -848,7 +848,7 @@
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values {
+- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (NSString *value in values) {
     [self writeString:fieldNumber value:value];
   }
@@ -857,25 +857,25 @@
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values {
+- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBMessage *value in values) {
     [self writeMessage:fieldNumber value:value];
   }
 }
 
-//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Data, NSData)
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values {
+- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (NSData *value in values) {
-    [self writeData:fieldNumber value:value];
+    [self writeBytes:fieldNumber value:value];
   }
 }
 
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values {
+- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBMessage *value in values) {
     [self writeGroup:fieldNumber value:value];
   }
@@ -884,7 +884,7 @@
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet)
 // This block of code is generated, do not edit it directly.
 
-- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values {
+- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBUnknownFieldSet *value in values) {
     [self writeUnknownGroup:fieldNumber value:value];
   }
@@ -906,7 +906,7 @@
   GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
                         GPBWireFormatStartGroup);
   GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
-  [self writeData:GPBWireFormatMessageSetMessage value:value];
+  [self writeBytes:GPBWireFormatMessageSetMessage value:value];
   GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
                         GPBWireFormatEndGroup);
 }
@@ -1062,7 +1062,7 @@
   return GPBComputeRawVarint32SizeForInteger(size) + size;
 }
 
-size_t GPBComputeDataSizeNoTag(NSData *value) {
+size_t GPBComputeBytesSizeNoTag(NSData *value) {
   NSUInteger valueLength = [value length];
   return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength;
 }
@@ -1143,8 +1143,8 @@
   return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value);
 }
 
-size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value) {
-  return GPBComputeTagSize(fieldNumber) + GPBComputeDataSizeNoTag(value);
+size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value);
 }
 
 size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) {
@@ -1183,7 +1183,7 @@
                                             NSData *value) {
   return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
          GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
-         GPBComputeDataSize(GPBWireFormatMessageSetMessage, value);
+         GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value);
 }
 
 size_t GPBComputeTagSize(int32_t fieldNumber) {
@@ -1191,9 +1191,9 @@
       GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
 }
 
-size_t GPBComputeWireFormatTagSize(int field_number, GPBType type) {
+size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) {
   size_t result = GPBComputeTagSize(field_number);
-  if (type == GPBTypeGroup) {
+  if (dataType == GPBDataTypeGroup) {
     // Groups have both a start and an end tag.
     return result * 2;
   } else {
diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h
index 97b46b3..aeac902 100644
--- a/objectivec/GPBDescriptor.h
+++ b/objectivec/GPBDescriptor.h
@@ -30,7 +30,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 
 @class GPBEnumDescriptor;
 @class GPBFieldDescriptor;
@@ -89,14 +89,14 @@
 
 @property(nonatomic, readonly, copy) NSString *name;
 @property(nonatomic, readonly) uint32_t number;
-@property(nonatomic, readonly) GPBType type;
+@property(nonatomic, readonly) GPBDataType dataType;
 @property(nonatomic, readonly) BOOL hasDefaultValue;
-@property(nonatomic, readonly) GPBValue defaultValue;
+@property(nonatomic, readonly) GPBGenericValue defaultValue;
 @property(nonatomic, readonly, getter=isRequired) BOOL required;
 @property(nonatomic, readonly, getter=isOptional) BOOL optional;
 @property(nonatomic, readonly) GPBFieldType fieldType;
 // If it is a map, the value type is in -type.
-@property(nonatomic, readonly) GPBType mapKeyType;
+@property(nonatomic, readonly) GPBDataType mapKeyDataType;
 @property(nonatomic, readonly, getter=isPackable) BOOL packable;
 
 @property(nonatomic, readonly, assign) GPBOneofDescriptor *containingOneof;
@@ -129,12 +129,14 @@
 
 @end
 
-@interface GPBExtensionDescriptor : NSObject
+@interface GPBExtensionDescriptor : NSObject<NSCopying>
 @property(nonatomic, readonly) uint32_t fieldNumber;
-@property(nonatomic, readonly) GPBType type;
+@property(nonatomic, readonly) Class containingMessageClass;
+@property(nonatomic, readonly) GPBDataType dataType;
 @property(nonatomic, readonly, getter=isRepeated) BOOL repeated;
 @property(nonatomic, readonly, getter=isPackable) BOOL packable;
 @property(nonatomic, readonly, assign) Class msgClass;
 @property(nonatomic, readonly) NSString *singletonName;
 @property(nonatomic, readonly, strong) GPBEnumDescriptor *enumDescriptor;
+@property(nonatomic, readonly) id defaultValue;
 @end
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
index b955018..bae9187 100644
--- a/objectivec/GPBDescriptor.m
+++ b/objectivec/GPBDescriptor.m
@@ -369,16 +369,26 @@
   GPBWireFormat format;
   if ((description->flags & GPBFieldMapKeyMask) != 0) {
     // Maps are repeated messages on the wire.
-    format = GPBWireFormatForType(GPBTypeMessage, NO);
+    format = GPBWireFormatForType(GPBDataTypeMessage, NO);
   } else {
-    format = GPBWireFormatForType(description->type,
-                                  description->flags & GPBFieldPacked);
+    format = GPBWireFormatForType(description->dataType,
+                                  ((description->flags & GPBFieldPacked) != 0));
   }
   return GPBWireFormatMakeTag(description->number, format);
 }
 
+uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
+  GPBMessageFieldDescription *description = self->description_;
+  NSCAssert((description->flags & GPBFieldRepeated) != 0,
+            @"Only valid on repeated fields");
+  GPBWireFormat format =
+      GPBWireFormatForType(description->dataType,
+                           ((description->flags & GPBFieldPacked) == 0));
+  return GPBWireFormatMakeTag(description->number, format);
+}
+
 @implementation GPBFieldDescriptor {
-  GPBValue defaultValue_;
+  GPBGenericValue defaultValue_;
   GPBFieldOptions *fieldOptions_;
 
   // Message ivars
@@ -416,12 +426,66 @@
     getSel_ = sel_getUid(description->name);
     setSel_ = SelFromStrings("set", description->name, NULL, YES);
 
+    GPBDataType dataType = description->dataType;
+    BOOL isMessage = GPBDataTypeIsMessage(dataType);
+    BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
+
+    if (isMapOrArray) {
+      // map<>/repeated fields get a *Count property (inplace of a has*) to
+      // support checking if there are any entries without triggering
+      // autocreation.
+      hasOrCountSel_ = SelFromStrings(NULL, description->name, "_Count", NO);
+    } else {
+      // If there is a positive hasIndex, then:
+      //   - All fields types for proto2 messages get has* selectors.
+      //   - Only message fields for proto3 messages get has* selectors.
+      // Note: the positive check is to handle oneOfs, we can't check
+      // containingOneof_ because it isn't set until after initialization.
+      if ((description->hasIndex >= 0) &&
+          (description->hasIndex != GPBNoHasBit) &&
+          ((syntax != GPBFileSyntaxProto3) || isMessage)) {
+        hasOrCountSel_ = SelFromStrings("has", description->name, NULL, NO);
+        setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
+      }
+    }
+
+    // Extra type specific data.
+    if (isMessage) {
+      const char *className = description->dataTypeSpecific.className;
+      msgClass_ = objc_getClass(className);
+      NSAssert(msgClass_, @"Class %s not defined", className);
+    } else if (dataType == GPBDataTypeEnum) {
+      if ((description_->flags & GPBFieldHasEnumDescriptor) != 0) {
+        enumHandling_.enumDescriptor_ =
+            description->dataTypeSpecific.enumDescFunc();
+      } else {
+        enumHandling_.enumVerifier_ =
+            description->dataTypeSpecific.enumVerifier;
+      }
+    }
+
+    // Non map<>/repeated fields can have defaults.
+    if (!isMapOrArray) {
+      defaultValue_ = description->defaultValue;
+      if (dataType == GPBDataTypeBytes) {
+        // Data stored as a length prefixed (network byte order) c-string in
+        // descriptor structure.
+        const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData;
+        if (bytes) {
+          uint32_t length = *((uint32_t *)bytes);
+          length = ntohl(length);
+          bytes += sizeof(length);
+          defaultValue_.valueData =
+              [[NSData alloc] initWithBytes:bytes length:length];
+        }
+      }
+    }
+
+    // FieldOptions stored as a length prefixed (network byte order) c-escaped
+    // string in descriptor records.
     if (description->fieldOptions) {
-      // FieldOptions stored as a length prefixed c-escaped string in descriptor
-      // records.
       uint8_t *optionsBytes = (uint8_t *)description->fieldOptions;
       uint32_t optionsLength = *((uint32_t *)optionsBytes);
-      // The length is stored in network byte order.
       optionsLength = ntohl(optionsLength);
       if (optionsLength > 0) {
         optionsBytes += sizeof(optionsLength);
@@ -434,69 +498,20 @@
                                                   error:NULL] retain];
       }
     }
-
-    GPBType type = description->type;
-    BOOL isMessage = GPBTypeIsMessage(type);
-    if (isMessage) {
-      // No has* for repeated/map or something in a oneof (we can't check
-      // containingOneof_ because it isn't set until after initialization).
-      if ((description->hasIndex >= 0) &&
-          (description->hasIndex != GPBNoHasBit)) {
-        hasSel_ = SelFromStrings("has", description->name, NULL, NO);
-        setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
-      }
-      const char *className = description->typeSpecific.className;
-      msgClass_ = objc_getClass(className);
-      NSAssert1(msgClass_, @"Class %s not defined", className);
-      // The defaultValue_ is fetched directly in -defaultValue to avoid
-      // initialization order issues.
-    } else {
-      if (!GPBFieldIsMapOrArray(self)) {
-        defaultValue_ = description->defaultValue;
-        if (type == GPBTypeData) {
-          // Data stored as a length prefixed c-string in descriptor records.
-          const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData;
-          if (bytes) {
-            uint32_t length = *((uint32_t *)bytes);
-            // The length is stored in network byte order.
-            length = ntohl(length);
-            bytes += sizeof(length);
-            defaultValue_.valueData =
-                [[NSData alloc] initWithBytes:bytes length:length];
-          }
-        }
-        // No has* methods for proto3 or if our hasIndex is < 0 because it
-        // means the field is in a oneof (we can't check containingOneof_
-        // because it isn't set until after initialization).
-        if ((syntax != GPBFileSyntaxProto3) && (description->hasIndex >= 0) &&
-            (description->hasIndex != GPBNoHasBit)) {
-          hasSel_ = SelFromStrings("has", description->name, NULL, NO);
-          setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
-        }
-      }
-      if (GPBTypeIsEnum(type)) {
-        if (description_->flags & GPBFieldHasEnumDescriptor) {
-          enumHandling_.enumDescriptor_ =
-              description->typeSpecific.enumDescFunc();
-        } else {
-          enumHandling_.enumVerifier_ = description->typeSpecific.enumVerifier;
-        }
-      }
-    }
   }
   return self;
 }
 
 - (void)dealloc {
-  if (description_->type == GPBTypeData &&
+  if (description_->dataType == GPBDataTypeBytes &&
       !(description_->flags & GPBFieldRepeated)) {
     [defaultValue_.valueData release];
   }
   [super dealloc];
 }
 
-- (GPBType)type {
-  return description_->type;
+- (GPBDataType)dataType {
+  return description_->dataType;
 }
 
 - (BOOL)hasDefaultValue {
@@ -530,36 +545,36 @@
   }
 }
 
-- (GPBType)mapKeyType {
+- (GPBDataType)mapKeyDataType {
   switch (description_->flags & GPBFieldMapKeyMask) {
     case GPBFieldMapKeyInt32:
-      return GPBTypeInt32;
+      return GPBDataTypeInt32;
     case GPBFieldMapKeyInt64:
-      return GPBTypeInt64;
+      return GPBDataTypeInt64;
     case GPBFieldMapKeyUInt32:
-      return GPBTypeUInt32;
+      return GPBDataTypeUInt32;
     case GPBFieldMapKeyUInt64:
-      return GPBTypeUInt64;
+      return GPBDataTypeUInt64;
     case GPBFieldMapKeySInt32:
-      return GPBTypeSInt32;
+      return GPBDataTypeSInt32;
     case GPBFieldMapKeySInt64:
-      return GPBTypeSInt64;
+      return GPBDataTypeSInt64;
     case GPBFieldMapKeyFixed32:
-      return GPBTypeFixed32;
+      return GPBDataTypeFixed32;
     case GPBFieldMapKeyFixed64:
-      return GPBTypeFixed64;
+      return GPBDataTypeFixed64;
     case GPBFieldMapKeySFixed32:
-      return GPBTypeSFixed32;
+      return GPBDataTypeSFixed32;
     case GPBFieldMapKeySFixed64:
-      return GPBTypeSFixed64;
+      return GPBDataTypeSFixed64;
     case GPBFieldMapKeyBool:
-      return GPBTypeBool;
+      return GPBDataTypeBool;
     case GPBFieldMapKeyString:
-      return GPBTypeString;
+      return GPBDataTypeString;
 
     default:
       NSAssert(0, @"Not a map type");
-      return GPBTypeInt32;  // For lack of anything better.
+      return GPBDataTypeInt32;  // For lack of anything better.
   }
 }
 
@@ -568,8 +583,8 @@
 }
 
 - (BOOL)isValidEnumValue:(int32_t)value {
-  NSAssert(description_->type == GPBTypeEnum,
-           @"Field Must be of type GPBTypeEnum");
+  NSAssert(description_->dataType == GPBDataTypeEnum,
+           @"Field Must be of type GPBDataTypeEnum");
   if (description_->flags & GPBFieldHasEnumDescriptor) {
     return enumHandling_.enumDescriptor_.enumVerifier(value);
   } else {
@@ -585,18 +600,18 @@
   }
 }
 
-- (GPBValue)defaultValue {
+- (GPBGenericValue)defaultValue {
   // Depends on the fact that defaultValue_ is initialized either to "0/nil" or
   // to an actual defaultValue in our initializer.
-  GPBValue value = defaultValue_;
+  GPBGenericValue value = defaultValue_;
 
   if (!(description_->flags & GPBFieldRepeated)) {
     // We special handle data and strings. If they are nil, we replace them
     // with empty string/empty data.
-    GPBType type = description_->type;
-    if (type == GPBTypeData && value.valueData == nil) {
+    GPBDataType type = description_->dataType;
+    if (type == GPBDataTypeBytes && value.valueData == nil) {
       value.valueData = GPBEmptyNSData();
-    } else if (type == GPBTypeString && value.valueString == nil) {
+    } else if (type == GPBDataTypeString && value.valueString == nil) {
       value.valueString = @"";
     }
   }
@@ -635,7 +650,7 @@
   }
 
   // Groups vs. other fields.
-  if (description_->type == GPBTypeGroup) {
+  if (description_->dataType == GPBDataTypeGroup) {
     // Just capitalize the first letter.
     unichar firstChar = [name characterAtIndex:0];
     if (firstChar >= 'a' && firstChar <= 'z') {
@@ -811,16 +826,70 @@
 
 @end
 
-@implementation GPBExtensionDescriptor
+@implementation GPBExtensionDescriptor {
+  GPBGenericValue defaultValue_;
+}
+
+@synthesize containingMessageClass = containingMessageClass_;
 
 - (instancetype)initWithExtensionDescription:
         (GPBExtensionDescription *)description {
   if ((self = [super init])) {
     description_ = description;
+
+#if DEBUG
+    const char *className = description->messageOrGroupClassName;
+    if (className) {
+      NSAssert(objc_lookUpClass(className) != Nil,
+               @"Class %s not defined", className);
+    }
+#endif
+
+    if (description->extendedClass) {
+      Class containingClass = objc_lookUpClass(description->extendedClass);
+      NSAssert(containingClass, @"Class %s not defined",
+               description->extendedClass);
+      containingMessageClass_ = containingClass;
+    }
+
+    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;
+      if (bytes) {
+        uint32_t length = *((uint32_t *)bytes);
+        // The length is stored in network byte order.
+        length = ntohl(length);
+        bytes += sizeof(length);
+        defaultValue_.valueData =
+            [[NSData alloc] initWithBytes:bytes length:length];
+      }
+    } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) {
+      // The default is looked up in -defaultValue instead since extensions
+      // aren't common, we avoid the hit startup hit and it avoid initialization
+      // order issues.
+    } else {
+      defaultValue_ = description->defaultValue;
+    }
   }
   return self;
 }
 
+- (void)dealloc {
+  if ((description_->dataType == GPBDataTypeBytes) &&
+      !GPBExtensionIsRepeated(description_)) {
+    [defaultValue_.valueData release];
+  }
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+#pragma unused(zone)
+  // Immutable.
+  return [self retain];
+}
+
 - (NSString *)singletonName {
   return @(description_->singletonName);
 }
@@ -833,12 +902,24 @@
   return description_->fieldNumber;
 }
 
-- (GPBType)type {
-  return description_->type;
+- (GPBDataType)dataType {
+  return description_->dataType;
+}
+
+- (GPBWireFormat)wireType {
+  return GPBWireFormatForType(description_->dataType,
+                              GPBExtensionIsPacked(description_));
+}
+
+- (GPBWireFormat)alternateWireType {
+  NSAssert(GPBExtensionIsRepeated(description_),
+           @"Only valid on repeated extensions");
+  return GPBWireFormatForType(description_->dataType,
+                              !GPBExtensionIsPacked(description_));
 }
 
 - (BOOL)isRepeated {
-  return (description_->options & GPBExtensionRepeated) != 0;
+  return GPBExtensionIsRepeated(description_);
 }
 
 - (BOOL)isMap {
@@ -846,7 +927,7 @@
 }
 
 - (BOOL)isPackable {
-  return (description_->options & GPBExtensionPacked) != 0;
+  return GPBExtensionIsPacked(description_);
 }
 
 - (Class)msgClass {
@@ -854,11 +935,63 @@
 }
 
 - (GPBEnumDescriptor *)enumDescriptor {
-  if (GPBTypeIsEnum(description_->type)) {
+  if (description_->dataType == GPBDataTypeEnum) {
     GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc();
     return enumDescriptor;
   }
   return nil;
 }
 
+- (id)defaultValue {
+  if (GPBExtensionIsRepeated(description_)) {
+    return nil;
+  }
+
+  switch (description_->dataType) {
+    case GPBDataTypeBool:
+      return @(defaultValue_.valueBool);
+    case GPBDataTypeFloat:
+      return @(defaultValue_.valueFloat);
+    case GPBDataTypeDouble:
+      return @(defaultValue_.valueDouble);
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+    case GPBDataTypeEnum:
+    case GPBDataTypeSFixed32:
+      return @(defaultValue_.valueInt32);
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+    case GPBDataTypeSFixed64:
+      return @(defaultValue_.valueInt64);
+    case GPBDataTypeUInt32:
+    case GPBDataTypeFixed32:
+      return @(defaultValue_.valueUInt32);
+    case GPBDataTypeUInt64:
+    case GPBDataTypeFixed64:
+      return @(defaultValue_.valueUInt64);
+    case GPBDataTypeBytes:
+      // Like message fields, the default is zero length data.
+      return (defaultValue_.valueData ? defaultValue_.valueData
+                                      : GPBEmptyNSData());
+    case GPBDataTypeString:
+      // Like message fields, the default is zero length string.
+      return (defaultValue_.valueString ? defaultValue_.valueString : @"");
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
+      return nil;
+  }
+}
+
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other {
+  int32_t selfNumber = description_->fieldNumber;
+  int32_t otherNumber = other->description_->fieldNumber;
+  if (selfNumber < otherNumber) {
+    return NSOrderedAscending;
+  } else if (selfNumber == otherNumber) {
+    return NSOrderedSame;
+  } else {
+    return NSOrderedDescending;
+  }
+}
+
 @end
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
index b289a48..7987d92 100644
--- a/objectivec/GPBDescriptor_PackagePrivate.h
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -33,6 +33,7 @@
 // subject to change at any time without notice.
 
 #import "GPBDescriptor.h"
+#import "GPBWireFormat.h"
 
 // Describes attributes of the field.
 typedef NS_OPTIONS(uint32_t, GPBFieldFlags) {
@@ -66,8 +67,6 @@
   // set, the name can be derived from the ObjC name.
   GPBFieldTextFormatNameCustom = 1 << 16,
   // Indicates the field has an enum descriptor.
-  // TODO(thomasvl): Output the CPP check to use descFunc or validator based
-  // on final compile.  This will then get added based on that.
   GPBFieldHasEnumDescriptor = 1 << 17,
 };
 
@@ -84,21 +83,21 @@
   int32_t hasIndex;
   // Field flags. Use accessor functions below.
   GPBFieldFlags flags;
-  // Type of the ivar.
-  GPBType type;
+  // Data type of the ivar.
+  GPBDataType dataType;
   // Offset of the variable into it's structure struct.
   size_t offset;
   // FieldOptions protobuf, serialized as string.
   const char *fieldOptions;
 
-  GPBValue defaultValue;  // Default value for the ivar.
+  GPBGenericValue defaultValue;  // Default value for the ivar.
   union {
     const char *className;  // Name for message class.
     // For enums only: If EnumDescriptors are compiled in, it will be that,
     // otherwise it will be the verifier.
     GPBEnumDescriptorFunc enumDescFunc;
     GPBEnumValidationFunc enumVerifier;
-  } typeSpecific;
+  } dataTypeSpecific;
 } GPBMessageFieldDescription;
 
 // Describes a oneof.
@@ -133,10 +132,10 @@
 // An extension
 typedef struct GPBExtensionDescription {
   const char *singletonName;
-  GPBType type;
+  GPBDataType dataType;
   const char *extendedClass;
   int32_t fieldNumber;
-  GPBValue defaultValue;
+  GPBGenericValue defaultValue;
   const char *messageOrGroupClassName;
   GPBExtensionOptions options;
   GPBEnumDescriptorFunc enumDescriptorFunc;
@@ -217,7 +216,7 @@
 
   SEL getSel_;
   SEL setSel_;
-  SEL hasSel_;
+  SEL hasOrCountSel_;  // *Count for map<>/repeated fields, has* otherwise.
   SEL setHasSel_;
 }
 
@@ -254,10 +253,18 @@
  @package
   GPBExtensionDescription *description_;
 }
+@property(nonatomic, readonly) GPBWireFormat wireType;
+
+// For repeated extensions, alternateWireType is the wireType with the opposite
+// value for the packable property.  i.e. - if the extension was marked packed
+// it would be the wire type for unpacked; if the extension was marked unpacked,
+// it would be the wire type for packed.
+@property(nonatomic, readonly) GPBWireFormat alternateWireType;
 
 // description has to be long lived, it is held as a raw pointer.
 - (instancetype)initWithExtensionDescription:
-        (GPBExtensionDescription *)description;
+    (GPBExtensionDescription *)description;
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
 @end
 
 CF_EXTERN_C_BEGIN
@@ -267,8 +274,8 @@
           (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
 }
 
-GPB_INLINE GPBType GPBGetFieldType(GPBFieldDescriptor *field) {
-  return field->description_->type;
+GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
+  return field->description_->dataType;
 }
 
 GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
@@ -281,6 +288,12 @@
 
 uint32_t GPBFieldTag(GPBFieldDescriptor *self);
 
+// For repeated fields, alternateWireType is the wireType with the opposite
+// value for the packable property.  i.e. - if the field was marked packed it
+// would be the wire type for unpacked; if the field was marked unpacked, it
+// would be the wire type for packed.
+uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
+
 GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) {
   return syntax != GPBFileSyntaxProto3;
 }
@@ -289,4 +302,17 @@
   return syntax == GPBFileSyntaxProto3;
 }
 
+GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionRepeated) != 0;
+}
+
+GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionPacked) != 0;
+}
+
+GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionSetWireFormat) != 0;
+}
+
+
 CF_EXTERN_C_END
diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h
index 72873ad..e5bd475 100644
--- a/objectivec/GPBDictionary.h
+++ b/objectivec/GPBDictionary.h
@@ -30,7 +30,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 
 // These classes are used for map fields of basic data types. They are used because
 // they perform better than boxing into NSNumbers in NSDictionaries.
diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m
index 3769c69..df63427 100644
--- a/objectivec/GPBDictionary.m
+++ b/objectivec/GPBDictionary.m
@@ -55,64 +55,64 @@
   return (value != kGPBUnrecognizedEnumeratorValue);
 }
 
-//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2)
-//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
-//%  if (wireType == GPBType##GPBTYPE_NAME1) {
-//%    return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value);
-//%  } else if (wireType == GPBType##GPBTYPE_NAME2) {
-//%    return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value);
+//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2)
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value);
 //%  } else {
-//%    NSCAssert(NO, @"Unexpected type %d", wireType);
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
 //%    return 0;
 //%  }
 //%}
 //%
-//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
-//%  if (wireType == GPBType##GPBTYPE_NAME1) {
-//%    [stream write##GPBTYPE_NAME1##:fieldNum value:value];
-//%  } else if (wireType == GPBType##GPBTYPE_NAME2) {
-//%    [stream write##GPBTYPE_NAME2##:fieldNum value:value];
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    [stream write##GPBDATATYPE_NAME1##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    [stream write##GPBDATATYPE_NAME2##:fieldNum value:value];
 //%  } else {
-//%    NSCAssert(NO, @"Unexpected type %d", wireType);
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
 //%  }
 //%}
 //%
-//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2, GPBTYPE_NAME3)
-//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
-//%  if (wireType == GPBType##GPBTYPE_NAME1) {
-//%    return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value);
-//%  } else if (wireType == GPBType##GPBTYPE_NAME2) {
-//%    return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value);
-//%  } else if (wireType == GPBType##GPBTYPE_NAME3) {
-//%    return GPBCompute##GPBTYPE_NAME3##Size(fieldNum, value);
+//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3)
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) {
+//%    return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value);
 //%  } else {
-//%    NSCAssert(NO, @"Unexpected type %d", wireType);
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
 //%    return 0;
 //%  }
 //%}
 //%
-//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
-//%  if (wireType == GPBType##GPBTYPE_NAME1) {
-//%    [stream write##GPBTYPE_NAME1##:fieldNum value:value];
-//%  } else if (wireType == GPBType##GPBTYPE_NAME2) {
-//%    [stream write##GPBTYPE_NAME2##:fieldNum value:value];
-//%  } else if (wireType == GPBType##GPBTYPE_NAME3) {
-//%    [stream write##GPBTYPE_NAME3##:fieldNum value:value];
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    [stream write##GPBDATATYPE_NAME1##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    [stream write##GPBDATATYPE_NAME2##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) {
+//%    [stream write##GPBDATATYPE_NAME3##:fieldNum value:value];
 //%  } else {
-//%    NSCAssert(NO, @"Unexpected type %d", wireType);
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
 //%  }
 //%}
 //%
 //%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP)
-//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) {
-//%  NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType);
-//%  #pragma unused(wireType)  // For when asserts are off in release.
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
+//%  #pragma unused(dataType)  // For when asserts are off in release.
 //%  return GPBCompute##VALUE_NAME##Size(fieldNum, value);
 //%}
 //%
-//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) {
-//%  NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType);
-//%  #pragma unused(wireType)  // For when asserts are off in release.
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
+//%  #pragma unused(dataType)  // For when asserts are off in release.
 //%  [stream write##VALUE_NAME##:fieldNum value:value];
 //%}
 //%
@@ -126,191 +126,191 @@
 //%SIMPLE_SERIALIZE_SUPPORT(Float, float, )
 //%SIMPLE_SERIALIZE_SUPPORT(Double, double, )
 //%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *)
-//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Data)
+//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes)
 //%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS()
 // This block of code is generated, do not edit it directly.
 
-GPB_INLINE size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeInt32) {
+static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt32) {
     return GPBComputeInt32Size(fieldNum, value);
-  } else if (wireType == GPBTypeSInt32) {
+  } else if (dataType == GPBDataTypeSInt32) {
     return GPBComputeSInt32Size(fieldNum, value);
-  } else if (wireType == GPBTypeSFixed32) {
+  } else if (dataType == GPBDataTypeSFixed32) {
     return GPBComputeSFixed32Size(fieldNum, value);
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
     return 0;
   }
 }
 
-GPB_INLINE void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeInt32) {
+static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt32) {
     [stream writeInt32:fieldNum value:value];
-  } else if (wireType == GPBTypeSInt32) {
+  } else if (dataType == GPBDataTypeSInt32) {
     [stream writeSInt32:fieldNum value:value];
-  } else if (wireType == GPBTypeSFixed32) {
+  } else if (dataType == GPBDataTypeSFixed32) {
     [stream writeSFixed32:fieldNum value:value];
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
   }
 }
 
-GPB_INLINE size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeUInt32) {
+static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt32) {
     return GPBComputeUInt32Size(fieldNum, value);
-  } else if (wireType == GPBTypeFixed32) {
+  } else if (dataType == GPBDataTypeFixed32) {
     return GPBComputeFixed32Size(fieldNum, value);
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
     return 0;
   }
 }
 
-GPB_INLINE void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeUInt32) {
+static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt32) {
     [stream writeUInt32:fieldNum value:value];
-  } else if (wireType == GPBTypeFixed32) {
+  } else if (dataType == GPBDataTypeFixed32) {
     [stream writeFixed32:fieldNum value:value];
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
   }
 }
 
-GPB_INLINE size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeInt64) {
+static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt64) {
     return GPBComputeInt64Size(fieldNum, value);
-  } else if (wireType == GPBTypeSInt64) {
+  } else if (dataType == GPBDataTypeSInt64) {
     return GPBComputeSInt64Size(fieldNum, value);
-  } else if (wireType == GPBTypeSFixed64) {
+  } else if (dataType == GPBDataTypeSFixed64) {
     return GPBComputeSFixed64Size(fieldNum, value);
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
     return 0;
   }
 }
 
-GPB_INLINE void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeInt64) {
+static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt64) {
     [stream writeInt64:fieldNum value:value];
-  } else if (wireType == GPBTypeSInt64) {
+  } else if (dataType == GPBDataTypeSInt64) {
     [stream writeSInt64:fieldNum value:value];
-  } else if (wireType == GPBTypeSFixed64) {
+  } else if (dataType == GPBDataTypeSFixed64) {
     [stream writeSFixed64:fieldNum value:value];
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
   }
 }
 
-GPB_INLINE size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeUInt64) {
+static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt64) {
     return GPBComputeUInt64Size(fieldNum, value);
-  } else if (wireType == GPBTypeFixed64) {
+  } else if (dataType == GPBDataTypeFixed64) {
     return GPBComputeFixed64Size(fieldNum, value);
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
     return 0;
   }
 }
 
-GPB_INLINE void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeUInt64) {
+static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt64) {
     [stream writeUInt64:fieldNum value:value];
-  } else if (wireType == GPBTypeFixed64) {
+  } else if (dataType == GPBDataTypeFixed64) {
     [stream writeFixed64:fieldNum value:value];
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
   }
 }
 
-GPB_INLINE size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeBoolSize(fieldNum, value);
 }
 
-GPB_INLINE void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeBool:fieldNum value:value];
 }
 
-GPB_INLINE size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeEnumSize(fieldNum, value);
 }
 
-GPB_INLINE void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeEnum:fieldNum value:value];
 }
 
-GPB_INLINE size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeFloatSize(fieldNum, value);
 }
 
-GPB_INLINE void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeFloat:fieldNum value:value];
 }
 
-GPB_INLINE size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeDoubleSize(fieldNum, value);
 }
 
-GPB_INLINE void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeDouble:fieldNum value:value];
 }
 
-GPB_INLINE size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeStringSize(fieldNum, value);
 }
 
-GPB_INLINE void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBType wireType) {
-  NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType);
-  #pragma unused(wireType)  // For when asserts are off in release.
+static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeString:fieldNum value:value];
 }
 
-GPB_INLINE size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeMessage) {
+static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeMessage) {
     return GPBComputeMessageSize(fieldNum, value);
-  } else if (wireType == GPBTypeString) {
+  } else if (dataType == GPBDataTypeString) {
     return GPBComputeStringSize(fieldNum, value);
-  } else if (wireType == GPBTypeData) {
-    return GPBComputeDataSize(fieldNum, value);
+  } else if (dataType == GPBDataTypeBytes) {
+    return GPBComputeBytesSize(fieldNum, value);
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
     return 0;
   }
 }
 
-GPB_INLINE void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBType wireType) {
-  if (wireType == GPBTypeMessage) {
+static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeMessage) {
     [stream writeMessage:fieldNum value:value];
-  } else if (wireType == GPBTypeString) {
+  } else if (dataType == GPBDataTypeString) {
     [stream writeString:fieldNum value:value];
-  } else if (wireType == GPBTypeData) {
-    [stream writeData:fieldNum value:value];
+  } else if (dataType == GPBDataTypeBytes) {
+    [stream writeBytes:fieldNum value:value];
   } else {
-    NSCAssert(NO, @"Unexpected type %d", wireType);
+    NSCAssert(NO, @"Unexpected type %d", dataType);
   }
 }
 
 //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS()
 
 size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
-  GPBType mapValueType = GPBGetFieldType(field);
+  GPBDataType mapValueType = GPBGetFieldDataType(field);
   __block size_t result = 0;
   [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
     #pragma unused(stop)
@@ -318,7 +318,7 @@
     msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * dict.count;
   return result;
 }
@@ -326,8 +326,8 @@
 void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream,
                                               NSDictionary *dict,
                                               GPBFieldDescriptor *field) {
-  NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type");
-  GPBType mapValueType = GPBGetFieldType(field);
+  NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
+  GPBDataType mapValueType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
     #pragma unused(stop)
@@ -345,8 +345,8 @@
 }
 
 BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
-  NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type");
-  NSCAssert(GPBGetFieldType(field) == GPBTypeMessage, @"Unexpected value type");
+  NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
+  NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type");
   #pragma unused(field)  // For when asserts are off in release.
   for (GPBMessage *msg in [dict objectEnumerator]) {
     if (!msg.initialized) {
@@ -358,69 +358,69 @@
 
 // Note: if the type is an object, it the retain pass back to the caller.
 static void ReadValue(GPBCodedInputStream *stream,
-                      GPBValue *valueToFill,
-                      GPBType type,
+                      GPBGenericValue *valueToFill,
+                      GPBDataType type,
                       GPBExtensionRegistry *registry,
                       GPBFieldDescriptor *field) {
   switch (type) {
-    case GPBTypeBool:
+    case GPBDataTypeBool:
       valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_);
       break;
-    case GPBTypeFixed32:
+    case GPBDataTypeFixed32:
       valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_);
       break;
-    case GPBTypeSFixed32:
+    case GPBDataTypeSFixed32:
       valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_);
       break;
-    case GPBTypeFloat:
+    case GPBDataTypeFloat:
       valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_);
       break;
-    case GPBTypeFixed64:
+    case GPBDataTypeFixed64:
       valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_);
       break;
-    case GPBTypeSFixed64:
+    case GPBDataTypeSFixed64:
       valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_);
       break;
-    case GPBTypeDouble:
+    case GPBDataTypeDouble:
       valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_);
       break;
-    case GPBTypeInt32:
+    case GPBDataTypeInt32:
       valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_);
       break;
-    case GPBTypeInt64:
+    case GPBDataTypeInt64:
       valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_);
       break;
-    case GPBTypeSInt32:
+    case GPBDataTypeSInt32:
       valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_);
       break;
-    case GPBTypeSInt64:
+    case GPBDataTypeSInt64:
       valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_);
       break;
-    case GPBTypeUInt32:
+    case GPBDataTypeUInt32:
       valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_);
       break;
-    case GPBTypeUInt64:
+    case GPBDataTypeUInt64:
       valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_);
       break;
-    case GPBTypeData:
+    case GPBDataTypeBytes:
       [valueToFill->valueData release];
-      valueToFill->valueData = GPBCodedInputStreamReadRetainedData(&stream->state_);
+      valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_);
       break;
-    case GPBTypeString:
+    case GPBDataTypeString:
       [valueToFill->valueString release];
       valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_);
       break;
-    case GPBTypeMessage: {
+    case GPBDataTypeMessage: {
       GPBMessage *message = [[field.msgClass alloc] init];
       [stream readMessage:message extensionRegistry:registry];
       [valueToFill->valueMessage release];
       valueToFill->valueMessage = message;
       break;
     }
-    case GPBTypeGroup:
+    case GPBDataTypeGroup:
       NSCAssert(NO, @"Can't happen");
       break;
-    case GPBTypeEnum:
+    case GPBDataTypeEnum:
       valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_);
       break;
   }
@@ -431,30 +431,30 @@
                             GPBExtensionRegistry *registry,
                             GPBFieldDescriptor *field,
                             GPBMessage *parentMessage) {
-  GPBType keyType = field.mapKeyType;
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
 
-  GPBValue key;
-  GPBValue value;
+  GPBGenericValue key;
+  GPBGenericValue value;
   // Zero them (but pick up any enum default for proto2).
   key.valueString = value.valueString = nil;
-  if (valueType == GPBTypeEnum) {
+  if (valueDataType == GPBDataTypeEnum) {
     value = field.defaultValue;
   }
 
   GPBCodedInputStreamState *state = &stream->state_;
   uint32_t keyTag =
-      GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyType, NO));
+      GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO));
   uint32_t valueTag =
-      GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueType, NO));
+      GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO));
 
   BOOL hitError = NO;
   while (YES) {
     uint32_t tag = GPBCodedInputStreamReadTag(state);
     if (tag == keyTag) {
-      ReadValue(stream, &key, keyType, registry, field);
+      ReadValue(stream, &key, keyDataType, registry, field);
     } else if (tag == valueTag) {
-      ReadValue(stream, &value, valueType, registry, field);
+      ReadValue(stream, &value, valueDataType, registry, field);
     } else if (tag == 0) {
       // zero signals EOF / limit reached
       break;
@@ -468,18 +468,18 @@
 
   if (!hitError) {
     // Handle the special defaults and/or missing key/value.
-    if ((keyType == GPBTypeString) && (key.valueString == nil)) {
+    if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) {
       key.valueString = [@"" retain];
     }
-    if (GPBTypeIsObject(valueType) && value.valueString == nil) {
-      switch (valueType) {
-        case GPBTypeString:
+    if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) {
+      switch (valueDataType) {
+        case GPBDataTypeString:
           value.valueString = [@"" retain];
           break;
-        case GPBTypeData:
+        case GPBDataTypeBytes:
           value.valueData = [GPBEmptyNSData() retain];
           break;
-        case GPBTypeMessage: {
+        case GPBDataTypeMessage: {
           value.valueMessage = [[field.msgClass alloc] init];
           break;
         }
@@ -489,30 +489,30 @@
       }
     }
 
-    if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) {
+    if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
       // mapDictionary is an NSMutableDictionary
       [mapDictionary setObject:value.valueString forKey:key.valueString];
     } else {
-      if (valueType == GPBTypeEnum) {
+      if (valueDataType == GPBDataTypeEnum) {
         if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) ||
             [field isValidEnumValue:value.valueEnum]) {
-          [mapDictionary setGPBValue:&value forGPBValueKey:&key];
+          [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key];
         } else {
           NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum
                                                                forKey:&key
-                                                              keyType:keyType];
+                                                          keyDataType:keyDataType];
           [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data];
         }
       } else {
-        [mapDictionary setGPBValue:&value forGPBValueKey:&key];
+        [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key];
       }
     }
   }
 
-  if (GPBTypeIsObject(keyType)) {
+  if (GPBDataTypeIsObject(keyDataType)) {
     [key.valueString release];
   }
-  if (GPBTypeIsObject(valueType)) {
+  if (GPBDataTypeIsObject(valueDataType)) {
     [value.valueString release];
   }
 }
@@ -834,26 +834,26 @@
 //%    return 0;
 //%  }
 //%
-//%  GPBType valueType = GPBGetFieldType(field);
-//%  GPBType keyType = field.mapKeyType;
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  GPBDataType keyDataType = field.mapKeyDataType;
 //%  __block size_t result = 0;
 //%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
 //%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
 //%                                                   BOOL *stop) {
 //%    #pragma unused(stop)
-//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
-//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType);
 //%    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
 //%  }];
-//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
 //%  result += tagSize * count;
 //%  return result;
 //%}
 //%
 //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
 //%                         asField:(GPBFieldDescriptor *)field {
-//%  GPBType valueType = GPBGetFieldType(field);
-//%  GPBType keyType = field.mapKeyType;
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  GPBDataType keyDataType = field.mapKeyDataType;
 //%  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
 //%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
 //%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
@@ -862,16 +862,17 @@
 //%    // Write the tag.
 //%    [outputStream writeInt32NoTag:tag];
 //%    // Write the size of the message.
-//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
-//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType);
 //%    [outputStream writeInt32NoTag:(int32_t)msgSize];
 //%    // Write the fields.
-//%    WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
-//%    WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//%    WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType);
 //%  }];
 //%}
 //%
-//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
 //%  [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)];
 //%}
 //%
@@ -1036,37 +1037,37 @@
 //%}
 //%
 //%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-//%  GPBType valueType = GPBGetFieldType(field);
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
 //%  NSUInteger count = 0;
 //%  size_t result = 0;
 //%  for (int i = 0; i < 2; ++i) {
 //%    if (BOOL_DICT_HAS##HELPER(i, )) {
 //%      ++count;
-//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType);
+//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
 //%      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
 //%    }
 //%  }
-//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
 //%  result += tagSize * count;
 //%  return result;
 //%}
 //%
 //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
 //%                         asField:(GPBFieldDescriptor *)field {
-//%  GPBType valueType = GPBGetFieldType(field);
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
 //%  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
 //%  for (int i = 0; i < 2; ++i) {
 //%    if (BOOL_DICT_HAS##HELPER(i, )) {
 //%      // Write the tag.
 //%      [outputStream writeInt32NoTag:tag];
 //%      // Write the size of the message.
-//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType);
+//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
 //%      [outputStream writeInt32NoTag:(int32_t)msgSize];
 //%      // Write the fields.
-//%      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-//%      WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+//%      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
 //%    }
 //%  }
 //%}
@@ -1149,14 +1150,14 @@
 // Empty
 //%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME)
 //%- (NSData *)serializedDataForUnknownValue:(int32_t)value
-//%                                   forKey:(GPBValue *)key
-//%                                  keyType:(GPBType)keyType {
-//%  size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyType);
-//%  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+//%                                   forKey:(GPBGenericValue *)key
+//%                              keyDataType:(GPBDataType)keyDataType {
+//%  size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType);
+//%  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
 //%  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
 //%  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-//%  WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyType);
-//%  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+//%  WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType);
+//%  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
 //%  [outputStream release];
 //%  return data;
 //%}
@@ -1221,7 +1222,8 @@
 //%  return NO;
 //%}
 //%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP)
-//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//%- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
 //%  int idx = (key->valueBool ? 1 : 0);
 //%  _values[idx] = value->value##VALUE_NAME;
 //%  _valueSet[idx] = YES;
@@ -1401,7 +1403,8 @@
 //%  return _values[key ? 1 : 0];
 //%}
 //%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP)
-//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//%- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
 //%  int idx = (key->valueBool ? 1 : 0);
 //%  [_values[idx] release];
 //%  _values[idx] = [value->valueString retain];
@@ -1573,26 +1576,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -1601,16 +1604,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)];
 }
 
@@ -1778,26 +1782,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -1806,16 +1810,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)];
 }
 
@@ -1983,26 +1988,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -2011,16 +2016,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)];
 }
 
@@ -2188,26 +2194,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -2216,16 +2222,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)];
 }
 
@@ -2393,26 +2400,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -2421,16 +2428,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)];
 }
 
@@ -2598,26 +2606,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -2626,16 +2634,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)];
 }
 
@@ -2803,26 +2812,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -2831,16 +2840,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)];
 }
 
@@ -3036,26 +3046,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -3064,28 +3074,29 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)];
 }
 
@@ -3315,26 +3326,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
@@ -3343,16 +3354,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
-    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)];
 }
 
@@ -3520,26 +3532,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -3548,16 +3560,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)];
 }
 
@@ -3725,26 +3738,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -3753,16 +3766,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)];
 }
 
@@ -3930,26 +3944,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -3958,16 +3972,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)];
 }
 
@@ -4135,26 +4150,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -4163,16 +4178,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)];
 }
 
@@ -4340,26 +4356,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -4368,16 +4384,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)];
 }
 
@@ -4545,26 +4562,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -4573,16 +4590,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)];
 }
 
@@ -4750,26 +4768,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -4778,16 +4796,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)];
 }
 
@@ -4983,26 +5002,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -5011,28 +5030,29 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)];
 }
 
@@ -5262,26 +5282,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
@@ -5290,16 +5310,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
-    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:value->valueString forKey:@(key->valueInt32)];
 }
 
@@ -5467,26 +5488,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -5495,16 +5516,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)];
 }
 
@@ -5672,26 +5694,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -5700,16 +5722,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)];
 }
 
@@ -5877,26 +5900,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -5905,16 +5928,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)];
 }
 
@@ -6082,26 +6106,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -6110,16 +6134,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)];
 }
 
@@ -6287,26 +6312,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -6315,16 +6340,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)];
 }
 
@@ -6492,26 +6518,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -6520,16 +6546,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)];
 }
 
@@ -6697,26 +6724,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -6725,16 +6752,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)];
 }
 
@@ -6930,26 +6958,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -6958,28 +6986,29 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)];
 }
 
@@ -7209,26 +7238,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
@@ -7237,16 +7266,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)];
 }
 
@@ -7414,26 +7444,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -7442,16 +7472,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)];
 }
 
@@ -7619,26 +7650,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -7647,16 +7678,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)];
 }
 
@@ -7824,26 +7856,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -7852,16 +7884,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)];
 }
 
@@ -8029,26 +8062,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -8057,16 +8090,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)];
 }
 
@@ -8234,26 +8268,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -8262,16 +8296,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)];
 }
 
@@ -8439,26 +8474,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -8467,16 +8502,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)];
 }
 
@@ -8644,26 +8680,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -8672,16 +8708,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)];
 }
 
@@ -8877,26 +8914,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    NSNumber *aValue,
@@ -8905,28 +8942,29 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)];
 }
 
@@ -9156,26 +9194,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
                                                    id aValue,
@@ -9184,16 +9222,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
-    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:value->valueString forKey:@(key->valueInt64)];
 }
 
@@ -9361,26 +9400,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -9389,16 +9428,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString];
 }
 
@@ -9566,26 +9606,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -9594,16 +9634,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt32) forKey:key->valueString];
 }
 
@@ -9771,26 +9812,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -9799,16 +9840,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString];
 }
 
@@ -9976,26 +10018,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -10004,16 +10046,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueInt64) forKey:key->valueString];
 }
 
@@ -10181,26 +10224,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -10209,16 +10252,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueBool) forKey:key->valueString];
 }
 
@@ -10386,26 +10430,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -10414,16 +10458,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueFloat) forKey:key->valueString];
 }
 
@@ -10591,26 +10636,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -10619,16 +10664,17 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueDouble) forKey:key->valueString];
 }
 
@@ -10824,26 +10870,26 @@
     return 0;
   }
 
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   __block size_t result = 0;
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
                                                    BOOL *stop) {
     #pragma unused(stop)
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
   }];
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
-  GPBType keyType = field.mapKeyType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
                                                    NSNumber *aValue,
@@ -10852,28 +10898,29 @@
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
   }];
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   [_dictionary setObject:@(value->valueEnum) forKey:key->valueString];
 }
 
@@ -11104,7 +11151,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueUInt32;
   _valueSet[idx] = YES;
@@ -11131,37 +11179,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -11344,7 +11392,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueInt32;
   _valueSet[idx] = YES;
@@ -11371,37 +11420,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -11584,7 +11633,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueUInt64;
   _valueSet[idx] = YES;
@@ -11611,37 +11661,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -11824,7 +11874,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueInt64;
   _valueSet[idx] = YES;
@@ -11851,37 +11902,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -12064,7 +12115,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueBool;
   _valueSet[idx] = YES;
@@ -12091,37 +12143,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -12304,7 +12356,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueFloat;
   _valueSet[idx] = YES;
@@ -12331,37 +12384,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -12544,7 +12597,8 @@
   return NO;
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueDouble;
   _valueSet[idx] = YES;
@@ -12571,37 +12625,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -12772,7 +12826,8 @@
   return _values[key ? 1 : 0];
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   [_values[idx] release];
   _values[idx] = [value->valueString retain];
@@ -12820,37 +12875,37 @@
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_values[i] != nil) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_values[i] != nil) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -13115,14 +13170,14 @@
 // This block of code is generated, do not edit it directly.
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType {
-  size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyType);
-  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
   NSMutableData *data = [NSMutableData dataWithLength:msgSize];
   GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
-  WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyType);
-  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+  WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
   [outputStream release];
   return data;
 }
@@ -13130,37 +13185,37 @@
 //%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
   size_t result = 0;
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       ++count;
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
     }
   }
-  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
 }
 
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field {
-  GPBType valueType = GPBGetFieldType(field);
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
   for (int i = 0; i < 2; ++i) {
     if (_valueSet[i]) {
       // Write the tag.
       [outputStream writeInt32NoTag:tag];
       // Write the size of the message.
-      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
       [outputStream writeInt32NoTag:(int32_t)msgSize];
       // Write the fields.
-      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
-      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
     }
   }
 }
@@ -13174,7 +13229,8 @@
   }
 }
 
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueInt32;
   _valueSet[idx] = YES;
diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h
index 9c3c591..7b921e8 100644
--- a/objectivec/GPBDictionary_PackagePrivate.h
+++ b/objectivec/GPBDictionary_PackagePrivate.h
@@ -41,7 +41,8 @@
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field;
-- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key;
 - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
 @end
 
@@ -75,8 +76,8 @@
 //%
 //%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum()
 //%- (NSData *)serializedDataForUnknownValue:(int32_t)value
-//%                                   forKey:(GPBValue *)key
-//%                                  keyType:(GPBType)keyType;
+//%                                   forKey:(GPBGenericValue *)key
+//%                              keyDataType:(GPBDataType)keyDataType;
 //%
 
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32)
@@ -129,8 +130,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 @interface GPBUInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> {
@@ -192,8 +193,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 @interface GPBInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> {
@@ -255,8 +256,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 @interface GPBUInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> {
@@ -318,8 +319,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 @interface GPBInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> {
@@ -381,8 +382,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 @interface GPBBoolObjectDictionary () <GPBDictionaryInternalsProtocol> {
@@ -444,8 +445,8 @@
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
-                                   forKey:(GPBValue *)key
-                                  keyType:(GPBType)keyType;
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
 @end
 
 //%PDDM-EXPAND-END (6 expansions)
diff --git a/objectivec/GPBExtensionField.m b/objectivec/GPBExtensionField.m
deleted file mode 100644
index bbb36d7..0000000
--- a/objectivec/GPBExtensionField.m
+++ /dev/null
@@ -1,525 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 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 "GPBExtensionField_PackagePrivate.h"
-
-#import <objc/runtime.h>
-
-#import "GPBCodedInputStream_PackagePrivate.h"
-#import "GPBCodedOutputStream.h"
-#import "GPBDescriptor_PackagePrivate.h"
-#import "GPBMessage_PackagePrivate.h"
-#import "GPBUtilities_PackagePrivate.h"
-
-GPB_INLINE size_t TypeSize(GPBType type) {
-  switch (type) {
-    case GPBTypeBool:
-      return 1;
-    case GPBTypeFixed32:
-    case GPBTypeSFixed32:
-    case GPBTypeFloat:
-      return 4;
-    case GPBTypeFixed64:
-    case GPBTypeSFixed64:
-    case GPBTypeDouble:
-      return 8;
-    default:
-      return 0;
-  }
-}
-
-GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) {
-  return (description->options & GPBExtensionRepeated) != 0;
-}
-
-GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) {
-  return (description->options & GPBExtensionPacked) != 0;
-}
-
-GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) {
-  return (description->options & GPBExtensionSetWireFormat) != 0;
-}
-
-static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) {
-#define FIELD_CASE(TYPE, ACCESSOR) \
-  case GPBType##TYPE:              \
-    return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
-#define FIELD_CASE2(TYPE) \
-  case GPBType##TYPE:     \
-    return GPBCompute##TYPE##SizeNoTag(object);
-  switch (type) {
-    FIELD_CASE(Bool, boolValue)
-    FIELD_CASE(Float, floatValue)
-    FIELD_CASE(Double, doubleValue)
-    FIELD_CASE(Int32, intValue)
-    FIELD_CASE(SFixed32, intValue)
-    FIELD_CASE(SInt32, intValue)
-    FIELD_CASE(Enum, intValue)
-    FIELD_CASE(Int64, longLongValue)
-    FIELD_CASE(SInt64, longLongValue)
-    FIELD_CASE(SFixed64, longLongValue)
-    FIELD_CASE(UInt32, unsignedIntValue)
-    FIELD_CASE(Fixed32, unsignedIntValue)
-    FIELD_CASE(UInt64, unsignedLongLongValue)
-    FIELD_CASE(Fixed64, unsignedLongLongValue)
-    FIELD_CASE2(Data)
-    FIELD_CASE2(String)
-    FIELD_CASE2(Message)
-    FIELD_CASE2(Group)
-  }
-#undef FIELD_CASE
-#undef FIELD_CASE2
-}
-
-static size_t ComputeSerializedSizeIncludingTagOfObject(
-    GPBExtensionDescription *description, id object) {
-#define FIELD_CASE(TYPE, ACCESSOR)                          \
-  case GPBType##TYPE:                                       \
-    return GPBCompute##TYPE##Size(description->fieldNumber, \
-                                  [(NSNumber *)object ACCESSOR]);
-#define FIELD_CASE2(TYPE) \
-  case GPBType##TYPE:     \
-    return GPBCompute##TYPE##Size(description->fieldNumber, object);
-  switch (description->type) {
-    FIELD_CASE(Bool, boolValue)
-    FIELD_CASE(Float, floatValue)
-    FIELD_CASE(Double, doubleValue)
-    FIELD_CASE(Int32, intValue)
-    FIELD_CASE(SFixed32, intValue)
-    FIELD_CASE(SInt32, intValue)
-    FIELD_CASE(Enum, intValue)
-    FIELD_CASE(Int64, longLongValue)
-    FIELD_CASE(SInt64, longLongValue)
-    FIELD_CASE(SFixed64, longLongValue)
-    FIELD_CASE(UInt32, unsignedIntValue)
-    FIELD_CASE(Fixed32, unsignedIntValue)
-    FIELD_CASE(UInt64, unsignedLongLongValue)
-    FIELD_CASE(Fixed64, unsignedLongLongValue)
-    FIELD_CASE2(Data)
-    FIELD_CASE2(String)
-    FIELD_CASE2(Group)
-    case GPBTypeMessage:
-      if (ExtensionIsWireFormat(description)) {
-        return GPBComputeMessageSetExtensionSize(description->fieldNumber,
-                                                 object);
-      } else {
-        return GPBComputeMessageSize(description->fieldNumber, object);
-      }
-  }
-#undef FIELD_CASE
-#undef FIELD_CASE2
-}
-
-static size_t ComputeSerializedSizeIncludingTagOfArray(
-    GPBExtensionDescription *description, NSArray *values) {
-  if (ExtensionIsPacked(description)) {
-    size_t size = 0;
-    size_t typeSize = TypeSize(description->type);
-    if (typeSize != 0) {
-      size = values.count * typeSize;
-    } else {
-      for (id value in values) {
-        size += ComputePBSerializedSizeNoTagOfObject(description->type, value);
-      }
-    }
-    return size + GPBComputeTagSize(description->fieldNumber) +
-           GPBComputeRawVarint32SizeForInteger(size);
-  } else {
-    size_t size = 0;
-    for (id value in values) {
-      size += ComputeSerializedSizeIncludingTagOfObject(description, value);
-    }
-    return size;
-  }
-}
-
-static void WriteObjectIncludingTagToCodedOutputStream(
-    id object, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
-#define FIELD_CASE(TYPE, ACCESSOR)                      \
-  case GPBType##TYPE:                                   \
-    [output write##TYPE:description->fieldNumber        \
-                  value:[(NSNumber *)object ACCESSOR]]; \
-    return;
-#define FIELD_CASE2(TYPE)                                       \
-  case GPBType##TYPE:                                           \
-    [output write##TYPE:description->fieldNumber value:object]; \
-    return;
-  switch (description->type) {
-    FIELD_CASE(Bool, boolValue)
-    FIELD_CASE(Float, floatValue)
-    FIELD_CASE(Double, doubleValue)
-    FIELD_CASE(Int32, intValue)
-    FIELD_CASE(SFixed32, intValue)
-    FIELD_CASE(SInt32, intValue)
-    FIELD_CASE(Enum, intValue)
-    FIELD_CASE(Int64, longLongValue)
-    FIELD_CASE(SInt64, longLongValue)
-    FIELD_CASE(SFixed64, longLongValue)
-    FIELD_CASE(UInt32, unsignedIntValue)
-    FIELD_CASE(Fixed32, unsignedIntValue)
-    FIELD_CASE(UInt64, unsignedLongLongValue)
-    FIELD_CASE(Fixed64, unsignedLongLongValue)
-    FIELD_CASE2(Data)
-    FIELD_CASE2(String)
-    FIELD_CASE2(Group)
-    case GPBTypeMessage:
-      if (ExtensionIsWireFormat(description)) {
-        [output writeMessageSetExtension:description->fieldNumber value:object];
-      } else {
-        [output writeMessage:description->fieldNumber value:object];
-      }
-      return;
-  }
-#undef FIELD_CASE
-#undef FIELD_CASE2
-}
-
-static void WriteObjectNoTagToCodedOutputStream(
-    id object, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
-#define FIELD_CASE(TYPE, ACCESSOR)                             \
-  case GPBType##TYPE:                                          \
-    [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
-    return;
-#define FIELD_CASE2(TYPE)               \
-  case GPBType##TYPE:                   \
-    [output write##TYPE##NoTag:object]; \
-    return;
-  switch (description->type) {
-    FIELD_CASE(Bool, boolValue)
-    FIELD_CASE(Float, floatValue)
-    FIELD_CASE(Double, doubleValue)
-    FIELD_CASE(Int32, intValue)
-    FIELD_CASE(SFixed32, intValue)
-    FIELD_CASE(SInt32, intValue)
-    FIELD_CASE(Enum, intValue)
-    FIELD_CASE(Int64, longLongValue)
-    FIELD_CASE(SInt64, longLongValue)
-    FIELD_CASE(SFixed64, longLongValue)
-    FIELD_CASE(UInt32, unsignedIntValue)
-    FIELD_CASE(Fixed32, unsignedIntValue)
-    FIELD_CASE(UInt64, unsignedLongLongValue)
-    FIELD_CASE(Fixed64, unsignedLongLongValue)
-    FIELD_CASE2(Data)
-    FIELD_CASE2(String)
-    FIELD_CASE2(Message)
-    case GPBTypeGroup:
-      [output writeGroupNoTag:description->fieldNumber value:object];
-      return;
-  }
-#undef FIELD_CASE
-#undef FIELD_CASE2
-}
-
-static void WriteArrayIncludingTagsToCodedOutputStream(
-    NSArray *values, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
-  if (ExtensionIsPacked(description)) {
-    [output writeTag:description->fieldNumber
-              format:GPBWireFormatLengthDelimited];
-    size_t dataSize = 0;
-    size_t typeSize = TypeSize(description->type);
-    if (typeSize != 0) {
-      dataSize = values.count * typeSize;
-    } else {
-      for (id value in values) {
-        dataSize +=
-            ComputePBSerializedSizeNoTagOfObject(description->type, value);
-      }
-    }
-    [output writeRawVarintSizeTAs32:dataSize];
-    for (id value in values) {
-      WriteObjectNoTagToCodedOutputStream(value, description, output);
-    }
-  } else {
-    for (id value in values) {
-      WriteObjectIncludingTagToCodedOutputStream(value, description, output);
-    }
-  }
-}
-
-@implementation GPBExtensionField {
-  GPBExtensionDescription *description_;
-  GPBExtensionDescriptor *descriptor_;
-  GPBValue defaultValue_;
-}
-
-@synthesize containingType = containingType_;
-@synthesize descriptor = descriptor_;
-
-- (instancetype)init {
-  // Throw an exception if people attempt to not use the designated initializer.
-  self = [super init];
-  if (self != nil) {
-    [self doesNotRecognizeSelector:_cmd];
-    self = nil;
-  }
-  return self;
-}
-
-- (instancetype)initWithDescription:(GPBExtensionDescription *)description {
-  if ((self = [super init])) {
-    description_ = description;
-    if (description->extendedClass) {
-      Class containingClass = objc_lookUpClass(description->extendedClass);
-      NSAssert1(containingClass, @"Class %s not defined",
-                description->extendedClass);
-      containingType_ = [containingClass descriptor];
-    }
-#if DEBUG
-    const char *className = description->messageOrGroupClassName;
-    if (className) {
-      NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined",
-                className);
-    }
-#endif
-    descriptor_ = [[GPBExtensionDescriptor alloc]
-        initWithExtensionDescription:description];
-    GPBType type = description_->type;
-    if (type == GPBTypeData) {
-      // Data stored as a length prefixed c-string in descriptor records.
-      const uint8_t *bytes =
-          (const uint8_t *)description->defaultValue.valueData;
-      if (bytes) {
-        uint32_t length = *((uint32_t *)bytes);
-        // The length is stored in network byte order.
-        length = ntohl(length);
-        bytes += sizeof(length);
-        defaultValue_.valueData =
-            [[NSData alloc] initWithBytes:bytes length:length];
-      }
-    } else if (type == GPBTypeMessage || type == GPBTypeGroup) {
-      // The default is looked up in -defaultValue instead since extensions
-      // aren't
-      // common, we avoid the hit startup hit and it avoid initialization order
-      // issues.
-    } else {
-      defaultValue_ = description->defaultValue;
-    }
-  }
-  return self;
-}
-
-- (void)dealloc {
-  if ((description_->type == GPBTypeData) &&
-      !ExtensionIsRepeated(description_)) {
-    [defaultValue_.valueData release];
-  }
-  [descriptor_ release];
-  [super dealloc];
-}
-
-- (NSString *)description {
-  return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@",
-                                    [self class], self, self.fieldNumber,
-                                    self.containingType];
-}
-
-- (id)copyWithZone:(NSZone *)__unused zone {
-  return [self retain];
-}
-
-#pragma mark Properties
-
-- (int32_t)fieldNumber {
-  return description_->fieldNumber;
-}
-
-- (GPBWireFormat)wireType {
-  return GPBWireFormatForType(description_->type,
-                              ExtensionIsPacked(description_));
-}
-
-- (BOOL)isRepeated {
-  return ExtensionIsRepeated(description_);
-}
-
-- (id)defaultValue {
-  if (ExtensionIsRepeated(description_)) {
-    return nil;
-  }
-
-  switch (description_->type) {
-    case GPBTypeBool:
-      return @(defaultValue_.valueBool);
-    case GPBTypeFloat:
-      return @(defaultValue_.valueFloat);
-    case GPBTypeDouble:
-      return @(defaultValue_.valueDouble);
-    case GPBTypeInt32:
-    case GPBTypeSInt32:
-    case GPBTypeEnum:
-    case GPBTypeSFixed32:
-      return @(defaultValue_.valueInt32);
-    case GPBTypeInt64:
-    case GPBTypeSInt64:
-    case GPBTypeSFixed64:
-      return @(defaultValue_.valueInt64);
-    case GPBTypeUInt32:
-    case GPBTypeFixed32:
-      return @(defaultValue_.valueUInt32);
-    case GPBTypeUInt64:
-    case GPBTypeFixed64:
-      return @(defaultValue_.valueUInt64);
-    case GPBTypeData:
-      // Like message fields, the default is zero length data.
-      return (defaultValue_.valueData ? defaultValue_.valueData
-                                      : GPBEmptyNSData());
-    case GPBTypeString:
-      // Like message fields, the default is zero length string.
-      return (defaultValue_.valueString ? defaultValue_.valueString : @"");
-    case GPBTypeGroup:
-    case GPBTypeMessage:
-      NSAssert(0, @"Shouldn't get here");
-      return nil;
-  }
-}
-
-#pragma mark Internals
-
-- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
-                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
-                          message:(GPBMessage *)message {
-  GPBCodedInputStreamState *state = &input->state_;
-  if (ExtensionIsPacked(description_)) {
-    int32_t length = GPBCodedInputStreamReadInt32(state);
-    size_t limit = GPBCodedInputStreamPushLimit(state, length);
-    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-      id value = [self newSingleValueFromCodedInputStream:input
-                                        extensionRegistry:extensionRegistry
-                                            existingValue:nil];
-      [message addExtension:self value:value];
-      [value release];
-    }
-    GPBCodedInputStreamPopLimit(state, limit);
-  } else {
-    id existingValue = nil;
-    BOOL isRepeated = ExtensionIsRepeated(description_);
-    if (!isRepeated && GPBTypeIsMessage(description_->type)) {
-      existingValue = [message getExistingExtension:self];
-    }
-    id value = [self newSingleValueFromCodedInputStream:input
-                                      extensionRegistry:extensionRegistry
-                                          existingValue:existingValue];
-    if (isRepeated) {
-      [message addExtension:self value:value];
-    } else {
-      [message setExtension:self value:value];
-    }
-    [value release];
-  }
-}
-
-- (void)writeValue:(id)value
-    includingTagToCodedOutputStream:(GPBCodedOutputStream *)output {
-  if (ExtensionIsRepeated(description_)) {
-    WriteArrayIncludingTagsToCodedOutputStream(value, description_, output);
-  } else {
-    WriteObjectIncludingTagToCodedOutputStream(value, description_, output);
-  }
-}
-
-- (size_t)computeSerializedSizeIncludingTag:(id)value {
-  if (ExtensionIsRepeated(description_)) {
-    return ComputeSerializedSizeIncludingTagOfArray(description_, value);
-  } else {
-    return ComputeSerializedSizeIncludingTagOfObject(description_, value);
-  }
-}
-
-// Note that this returns a retained value intentionally.
-- (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input
-                        extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
-                            existingValue:(GPBMessage *)existingValue {
-  GPBCodedInputStreamState *state = &input->state_;
-  switch (description_->type) {
-    case GPBTypeBool:     return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
-    case GPBTypeFixed32:  return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
-    case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
-    case GPBTypeFloat:    return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
-    case GPBTypeFixed64:  return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
-    case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
-    case GPBTypeDouble:   return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
-    case GPBTypeInt32:    return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
-    case GPBTypeInt64:    return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
-    case GPBTypeSInt32:   return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
-    case GPBTypeSInt64:   return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
-    case GPBTypeUInt32:   return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
-    case GPBTypeUInt64:   return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
-    case GPBTypeData:     return GPBCodedInputStreamReadRetainedData(state);
-    case GPBTypeString:   return GPBCodedInputStreamReadRetainedString(state);
-    case GPBTypeEnum:     return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
-    case GPBTypeGroup:
-    case GPBTypeMessage: {
-      GPBMessage *message;
-      if (existingValue) {
-        message = [existingValue retain];
-      } else {
-        GPBDescriptor *decriptor = [descriptor_.msgClass descriptor];
-        message = [[decriptor.messageClass alloc] init];
-      }
-
-      if (description_->type == GPBTypeGroup) {
-        [input readGroup:description_->fieldNumber
-                 message:message
-            extensionRegistry:extensionRegistry];
-      } else {
-        // description_->type == GPBTypeMessage
-        if (ExtensionIsWireFormat(description_)) {
-          // For MessageSet fields the message length will have already been
-          // read.
-          [message mergeFromCodedInputStream:input
-                           extensionRegistry:extensionRegistry];
-        } else {
-          [input readMessage:message extensionRegistry:extensionRegistry];
-        }
-      }
-
-      return message;
-    }
-  }
-
-  return nil;
-}
-
-- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other {
-  int32_t selfNumber = description_->fieldNumber;
-  int32_t otherNumber = other->description_->fieldNumber;
-  if (selfNumber < otherNumber) {
-    return NSOrderedAscending;
-  } else if (selfNumber == otherNumber) {
-    return NSOrderedSame;
-  } else {
-    return NSOrderedDescending;
-  }
-}
-
-@end
diff --git a/objectivec/GPBExtensionField_PackagePrivate.h b/objectivec/GPBExtensionField_PackagePrivate.h
deleted file mode 100644
index 6256b9a..0000000
--- a/objectivec/GPBExtensionField_PackagePrivate.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 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 <Foundation/Foundation.h>
-
-#import "GPBExtensionField.h"
-
-struct GPBExtensionDescription;
-
-@interface GPBExtensionField ()
-
-- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
-                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
-                          message:(GPBMessage *)message;
-
-- (instancetype)initWithDescription:(struct GPBExtensionDescription *)description;
-
-- (size_t)computeSerializedSizeIncludingTag:(id)value;
-- (void)writeValue:(id)value
-    includingTagToCodedOutputStream:(GPBCodedOutputStream *)output;
-
-- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other;
-
-@end
diff --git a/objectivec/GPBExtensionField.h b/objectivec/GPBExtensionInternals.h
similarity index 72%
rename from objectivec/GPBExtensionField.h
rename to objectivec/GPBExtensionInternals.h
index e5ba156..2b980ae 100644
--- a/objectivec/GPBExtensionField.h
+++ b/objectivec/GPBExtensionInternals.h
@@ -30,22 +30,21 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBWireFormat.h"
-#import "GPBTypes.h"
+#import "GPBDescriptor.h"
 
 @class GPBCodedInputStream;
 @class GPBCodedOutputStream;
 @class GPBExtensionRegistry;
-@class GPBDescriptor;
-@class GPBExtensionDescriptor;
 
-@interface GPBExtensionField : NSObject<NSCopying>
+void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
+                                      BOOL isPackedOnStream,
+                                      GPBCodedInputStream *input,
+                                      GPBExtensionRegistry *extensionRegistry,
+                                      GPBMessage *message);
 
-@property(nonatomic, readonly) int32_t fieldNumber;
-@property(nonatomic, readonly) GPBWireFormat wireType;
-@property(nonatomic, readonly) BOOL isRepeated;
-@property(nonatomic, readonly) GPBDescriptor *containingType;
-@property(nonatomic, readonly) id defaultValue;
-@property(nonatomic, readonly) GPBExtensionDescriptor *descriptor;
+size_t GPBComputeExtensionSerializedSizeIncludingTag(
+    GPBExtensionDescriptor *extension, id value);
 
-@end
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
+                                          id value,
+                                          GPBCodedOutputStream *output);
diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m
new file mode 100644
index 0000000..634c336
--- /dev/null
+++ b/objectivec/GPBExtensionInternals.m
@@ -0,0 +1,380 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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 "GPBExtensionInternals.h"
+
+#import <objc/runtime.h>
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBCodedInputStream *input,
+                                        GPBExtensionRegistry *extensionRegistry,
+                                        GPBMessage *existingValue)
+    __attribute__((ns_returns_retained));
+
+GPB_INLINE size_t DataTypeSize(GPBDataType dataType) {
+  switch (dataType) {
+    case GPBDataTypeBool:
+      return 1;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeFloat:
+      return 4;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeDouble:
+      return 8;
+    default:
+      return 0;
+  }
+}
+
+static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR)                                     \
+  case GPBDataType##TYPE:                                              \
+    return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE)                                              \
+  case GPBDataType##TYPE:                                              \
+    return GPBCompute##TYPE##SizeNoTag(object);
+  switch (dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Message)
+    FIELD_CASE2(Group)
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfObject(
+    GPBExtensionDescription *description, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR)                                   \
+  case GPBDataType##TYPE:                                            \
+    return GPBCompute##TYPE##Size(description->fieldNumber,          \
+                                  [(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE)                                            \
+  case GPBDataType##TYPE:                                            \
+    return GPBCompute##TYPE##Size(description->fieldNumber, object);
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Group)
+    case GPBDataTypeMessage:
+      if (GPBExtensionIsWireFormat(description)) {
+        return GPBComputeMessageSetExtensionSize(description->fieldNumber,
+                                                 object);
+      } else {
+        return GPBComputeMessageSize(description->fieldNumber, object);
+      }
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfArray(
+    GPBExtensionDescription *description, NSArray *values) {
+  if (GPBExtensionIsPacked(description)) {
+    size_t size = 0;
+    size_t typeSize = DataTypeSize(description->dataType);
+    if (typeSize != 0) {
+      size = values.count * typeSize;
+    } else {
+      for (id value in values) {
+        size +=
+            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+      }
+    }
+    return size + GPBComputeTagSize(description->fieldNumber) +
+           GPBComputeRawVarint32SizeForInteger(size);
+  } else {
+    size_t size = 0;
+    for (id value in values) {
+      size += ComputeSerializedSizeIncludingTagOfObject(description, value);
+    }
+    return size;
+  }
+}
+
+static void WriteObjectIncludingTagToCodedOutputStream(
+    id object, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR)                      \
+  case GPBDataType##TYPE:                               \
+    [output write##TYPE:description->fieldNumber        \
+                  value:[(NSNumber *)object ACCESSOR]]; \
+    return;
+#define FIELD_CASE2(TYPE)                                       \
+  case GPBDataType##TYPE:                                       \
+    [output write##TYPE:description->fieldNumber value:object]; \
+    return;
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Group)
+    case GPBDataTypeMessage:
+      if (GPBExtensionIsWireFormat(description)) {
+        [output writeMessageSetExtension:description->fieldNumber value:object];
+      } else {
+        [output writeMessage:description->fieldNumber value:object];
+      }
+      return;
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteObjectNoTagToCodedOutputStream(
+    id object, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR)                             \
+  case GPBDataType##TYPE:                                      \
+    [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
+    return;
+#define FIELD_CASE2(TYPE)               \
+  case GPBDataType##TYPE:               \
+    [output write##TYPE##NoTag:object]; \
+    return;
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Message)
+    case GPBDataTypeGroup:
+      [output writeGroupNoTag:description->fieldNumber value:object];
+      return;
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteArrayIncludingTagsToCodedOutputStream(
+    NSArray *values, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+  if (GPBExtensionIsPacked(description)) {
+    [output writeTag:description->fieldNumber
+              format:GPBWireFormatLengthDelimited];
+    size_t dataSize = 0;
+    size_t typeSize = DataTypeSize(description->dataType);
+    if (typeSize != 0) {
+      dataSize = values.count * typeSize;
+    } else {
+      for (id value in values) {
+        dataSize +=
+            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+      }
+    }
+    [output writeRawVarintSizeTAs32:dataSize];
+    for (id value in values) {
+      WriteObjectNoTagToCodedOutputStream(value, description, output);
+    }
+  } else {
+    for (id value in values) {
+      WriteObjectIncludingTagToCodedOutputStream(value, description, output);
+    }
+  }
+}
+
+void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
+                                      BOOL isPackedOnStream,
+                                      GPBCodedInputStream *input,
+                                      GPBExtensionRegistry *extensionRegistry,
+                                      GPBMessage *message) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  if (isPackedOnStream) {
+    NSCAssert(GPBExtensionIsRepeated(description),
+              @"How was it packed if it isn't repeated?");
+    int32_t length = GPBCodedInputStreamReadInt32(state);
+    size_t limit = GPBCodedInputStreamPushLimit(state, length);
+    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+      id value = NewSingleValueFromInputStream(extension,
+                                               input,
+                                               extensionRegistry,
+                                               nil);
+      [message addExtension:extension value:value];
+      [value release];
+    }
+    GPBCodedInputStreamPopLimit(state, limit);
+  } else {
+    id existingValue = nil;
+    BOOL isRepeated = GPBExtensionIsRepeated(description);
+    if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) {
+      existingValue = [message getExistingExtension:extension];
+    }
+    id value = NewSingleValueFromInputStream(extension,
+                                             input,
+                                             extensionRegistry,
+                                             existingValue);
+    if (isRepeated) {
+      [message addExtension:extension value:value];
+    } else {
+      [message setExtension:extension value:value];
+    }
+    [value release];
+  }
+}
+
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
+                                          id value,
+                                          GPBCodedOutputStream *output) {
+  GPBExtensionDescription *description = extension->description_;
+  if (GPBExtensionIsRepeated(description)) {
+    WriteArrayIncludingTagsToCodedOutputStream(value, description, output);
+  } else {
+    WriteObjectIncludingTagToCodedOutputStream(value, description, output);
+  }
+}
+
+size_t GPBComputeExtensionSerializedSizeIncludingTag(
+    GPBExtensionDescriptor *extension, id value) {
+  GPBExtensionDescription *description = extension->description_;
+  if (GPBExtensionIsRepeated(description)) {
+    return ComputeSerializedSizeIncludingTagOfArray(description, value);
+  } else {
+    return ComputeSerializedSizeIncludingTagOfObject(description, value);
+  }
+}
+
+// Note that this returns a retained value intentionally.
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBCodedInputStream *input,
+                                        GPBExtensionRegistry *extensionRegistry,
+                                        GPBMessage *existingValue) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  switch (description->dataType) {
+    case GPBDataTypeBool:     return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
+    case GPBDataTypeFixed32:  return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
+    case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
+    case GPBDataTypeFloat:    return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
+    case GPBDataTypeFixed64:  return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
+    case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
+    case GPBDataTypeDouble:   return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
+    case GPBDataTypeInt32:    return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
+    case GPBDataTypeInt64:    return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
+    case GPBDataTypeSInt32:   return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
+    case GPBDataTypeSInt64:   return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
+    case GPBDataTypeUInt32:   return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
+    case GPBDataTypeUInt64:   return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
+    case GPBDataTypeBytes:    return GPBCodedInputStreamReadRetainedBytes(state);
+    case GPBDataTypeString:   return GPBCodedInputStreamReadRetainedString(state);
+    case GPBDataTypeEnum:     return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage: {
+      GPBMessage *message;
+      if (existingValue) {
+        message = [existingValue retain];
+      } else {
+        GPBDescriptor *decriptor = [extension.msgClass descriptor];
+        message = [[decriptor.messageClass alloc] init];
+      }
+
+      if (description->dataType == GPBDataTypeGroup) {
+        [input readGroup:description->fieldNumber
+                 message:message
+            extensionRegistry:extensionRegistry];
+      } else {
+        // description->dataType == GPBDataTypeMessage
+        if (GPBExtensionIsWireFormat(description)) {
+          // For MessageSet fields the message length will have already been
+          // read.
+          [message mergeFromCodedInputStream:input
+                           extensionRegistry:extensionRegistry];
+        } else {
+          [input readMessage:message extensionRegistry:extensionRegistry];
+        }
+      }
+
+      return message;
+    }
+  }
+
+  return nil;
+}
diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h
index e382971..07a99e4 100644
--- a/objectivec/GPBExtensionRegistry.h
+++ b/objectivec/GPBExtensionRegistry.h
@@ -31,7 +31,7 @@
 #import <Foundation/Foundation.h>
 
 @class GPBDescriptor;
-@class GPBExtensionField;
+@class GPBExtensionDescriptor;
 
 // A table of known extensions, searchable by name or field number.  When
 // parsing a protocol message that might have extensions, you must provide an
@@ -54,10 +54,10 @@
 //
 @interface GPBExtensionRegistry : NSObject<NSCopying>
 
-- (void)addExtension:(GPBExtensionField *)extension;
+- (void)addExtension:(GPBExtensionDescriptor *)extension;
 - (void)addExtensions:(GPBExtensionRegistry *)registry;
 
-- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType
-                        fieldNumber:(NSInteger)fieldNumber;
+- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
+                                       fieldNumber:(NSInteger)fieldNumber;
 
 @end
diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m
index 4f234f5..df61a17 100644
--- a/objectivec/GPBExtensionRegistry.m
+++ b/objectivec/GPBExtensionRegistry.m
@@ -32,7 +32,6 @@
 
 #import "GPBBootstrap.h"
 #import "GPBDescriptor.h"
-#import "GPBExtensionField.h"
 
 @implementation GPBExtensionRegistry {
   // TODO(dmaclach): Reimplement with CFDictionaries that don't use
@@ -60,31 +59,34 @@
   return result;
 }
 
-- (NSMutableDictionary *)extensionMapForContainingType:
-        (GPBDescriptor *)containingType {
+- (NSMutableDictionary *)extensionMapForContainingMessageClass:
+        (Class)containingMessageClass {
   NSMutableDictionary *extensionMap =
-      [mutableClassMap_ objectForKey:containingType];
+      [mutableClassMap_ objectForKey:containingMessageClass];
   if (extensionMap == nil) {
     extensionMap = [NSMutableDictionary dictionary];
-    [mutableClassMap_ setObject:extensionMap forKey:containingType];
+    [mutableClassMap_ setObject:extensionMap
+                         forKey:(id<NSCopying>)containingMessageClass];
   }
   return extensionMap;
 }
 
-- (void)addExtension:(GPBExtensionField *)extension {
+- (void)addExtension:(GPBExtensionDescriptor *)extension {
   if (extension == nil) {
     return;
   }
 
-  GPBDescriptor *containingType = [extension containingType];
+  Class containingMessageClass = extension.containingMessageClass;
   NSMutableDictionary *extensionMap =
-      [self extensionMapForContainingType:containingType];
-  [extensionMap setObject:extension forKey:@([extension fieldNumber])];
+      [self extensionMapForContainingMessageClass:containingMessageClass];
+  [extensionMap setObject:extension forKey:@(extension.fieldNumber)];
 }
 
-- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType
-                        fieldNumber:(NSInteger)fieldNumber {
-  NSDictionary *extensionMap = [mutableClassMap_ objectForKey:containingType];
+- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
+                                       fieldNumber:(NSInteger)fieldNumber {
+  Class messageClass = descriptor.messageClass;
+  NSDictionary *extensionMap =
+      [mutableClassMap_ objectForKey:messageClass];
   return [extensionMap objectForKey:@(fieldNumber)];
 }
 
@@ -94,11 +96,11 @@
     return;
   }
   NSMutableDictionary *otherClassMap = registry->mutableClassMap_;
-  for (GPBDescriptor *containingType in otherClassMap) {
+  for (Class containingMessageClass in otherClassMap) {
     NSMutableDictionary *extensionMap =
-        [self extensionMapForContainingType:containingType];
+        [self extensionMapForContainingMessageClass:containingMessageClass];
     NSMutableDictionary *otherExtensionMap =
-        [registry extensionMapForContainingType:containingType];
+        [registry extensionMapForContainingMessageClass:containingMessageClass];
     [extensionMap addEntriesFromDictionary:otherExtensionMap];
   }
 }
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
index 1c6c091..64d3ba1 100644
--- a/objectivec/GPBMessage.h
+++ b/objectivec/GPBMessage.h
@@ -35,7 +35,7 @@
 @class GPBDescriptor;
 @class GPBCodedInputStream;
 @class GPBCodedOutputStream;
-@class GPBExtensionField;
+@class GPBExtensionDescriptor;
 @class GPBExtensionRegistry;
 @class GPBFieldDescriptor;
 @class GPBUnknownFieldSet;
@@ -148,14 +148,14 @@
 // Extensions use boxed values (NSNumbers) for PODs, NSMutableArrays for
 // repeated. If the extension is a Message one will be auto created for you
 // and returned similar to fields.
-- (BOOL)hasExtension:(GPBExtensionField *)extension;
-- (id)getExtension:(GPBExtensionField *)extension;
-- (void)setExtension:(GPBExtensionField *)extension value:(id)value;
-- (void)addExtension:(GPBExtensionField *)extension value:(id)value;
-- (void)setExtension:(GPBExtensionField *)extension
+- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension;
+- (id)getExtension:(GPBExtensionDescriptor *)extension;
+- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value;
+- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value;
+- (void)setExtension:(GPBExtensionDescriptor *)extension
                index:(NSUInteger)index
                value:(id)value;
-- (void)clearExtension:(GPBExtensionField *)extension;
+- (void)clearExtension:(GPBExtensionDescriptor *)extension;
 
 - (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields;
 
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index bd3235f..c655edd 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -38,7 +38,7 @@
 #import "GPBCodedOutputStream.h"
 #import "GPBDescriptor_PackagePrivate.h"
 #import "GPBDictionary_PackagePrivate.h"
-#import "GPBExtensionField_PackagePrivate.h"
+#import "GPBExtensionInternals.h"
 #import "GPBExtensionRegistry.h"
 #import "GPBRootObject_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
@@ -54,6 +54,13 @@
 
 static NSString *const kGPBDataCoderKey = @"GPBData";
 
+#ifndef _GPBCompileAssert
+#define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg
+#define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg)
+#define _GPBCompileAssert(test, msg) \
+    typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
+#endif // _GPBCompileAssert
+
 //
 // PLEASE REMEMBER:
 //
@@ -73,7 +80,7 @@
   // mutated, we can inform the creator to make our field visible.
   GPBMessage *autocreator_;
   GPBFieldDescriptor *autocreatorField_;
-  GPBExtensionField *autocreatorExtension_;
+  GPBExtensionDescriptor *autocreatorExtension_;
 }
 @end
 
@@ -110,13 +117,14 @@
 }
 
 
-static void CheckExtension(GPBMessage *self, GPBExtensionField *extension) {
-  if ([[self class] descriptor] != [extension containingType]) {
+static void CheckExtension(GPBMessage *self,
+                           GPBExtensionDescriptor *extension) {
+  if ([self class] != extension.containingMessageClass) {
     [NSException
          raise:NSInvalidArgumentException
         format:@"Extension %@ used on wrong class (%@ instead of %@)",
-               extension.descriptor.singletonName,
-               [[self class] descriptor].name, [extension containingType].name];
+               extension.singletonName,
+               [self class], extension.containingMessageClass];
   }
 }
 
@@ -128,12 +136,11 @@
   NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
       initWithCapacity:extensionMap.count];
 
-  for (GPBExtensionField *field in extensionMap) {
-    id value = [extensionMap objectForKey:field];
-    GPBExtensionDescriptor *fieldDescriptor = field.descriptor;
-    BOOL isMessageExtension = GPBExtensionIsMessage(fieldDescriptor);
+  for (GPBExtensionDescriptor *extension in extensionMap) {
+    id value = [extensionMap objectForKey:extension];
+    BOOL isMessageExtension = GPBExtensionIsMessage(extension);
 
-    if ([field isRepeated]) {
+    if (extension.repeated) {
       if (isMessageExtension) {
         NSMutableArray *list =
             [[NSMutableArray alloc] initWithCapacity:[value count]];
@@ -142,20 +149,20 @@
           [list addObject:copiedValue];
           [copiedValue release];
         }
-        [result setObject:list forKey:field];
+        [result setObject:list forKey:extension];
         [list release];
       } else {
         NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
-        [result setObject:copiedValue forKey:field];
+        [result setObject:copiedValue forKey:extension];
         [copiedValue release];
       }
     } else {
       if (isMessageExtension) {
         GPBMessage *copiedValue = [value copyWithZone:zone];
-        [result setObject:copiedValue forKey:field];
+        [result setObject:copiedValue forKey:extension];
         [copiedValue release];
       } else {
-        [result setObject:value forKey:field];
+        [result setObject:value forKey:extension];
       }
     }
   }
@@ -166,45 +173,45 @@
 static id CreateArrayForField(GPBFieldDescriptor *field,
                               GPBMessage *autocreator) {
   id result;
-  GPBType fieldDataType = GPBGetFieldType(field);
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
   switch (fieldDataType) {
-    case GPBTypeBool:
+    case GPBDataTypeBool:
       result = [[GPBBoolArray alloc] init];
       break;
-    case GPBTypeFixed32:
-    case GPBTypeUInt32:
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
       result = [[GPBUInt32Array alloc] init];
       break;
-    case GPBTypeInt32:
-    case GPBTypeSFixed32:
-    case GPBTypeSInt32:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeSInt32:
       result = [[GPBInt32Array alloc] init];
       break;
-    case GPBTypeFixed64:
-    case GPBTypeUInt64:
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
       result = [[GPBUInt64Array alloc] init];
       break;
-    case GPBTypeInt64:
-    case GPBTypeSFixed64:
-    case GPBTypeSInt64:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeSInt64:
       result = [[GPBInt64Array alloc] init];
       break;
-    case GPBTypeFloat:
+    case GPBDataTypeFloat:
       result = [[GPBFloatArray alloc] init];
       break;
-    case GPBTypeDouble:
+    case GPBDataTypeDouble:
       result = [[GPBDoubleArray alloc] init];
       break;
 
-    case GPBTypeEnum:
+    case GPBDataTypeEnum:
       result = [[GPBEnumArray alloc]
                   initWithValidationFunction:field.enumDescriptor.enumVerifier];
       break;
 
-    case GPBTypeData:
-    case GPBTypeGroup:
-    case GPBTypeMessage:
-    case GPBTypeString:
+    case GPBDataTypeBytes:
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
+    case GPBDataTypeString:
       if (autocreator) {
         result = [[GPBAutocreatedArray alloc] init];
       } else {
@@ -214,7 +221,7 @@
   }
 
   if (autocreator) {
-    if (GPBTypeIsObject(fieldDataType)) {
+    if (GPBDataTypeIsObject(fieldDataType)) {
       GPBAutocreatedArray *autoArray = result;
       autoArray->_autocreator =  autocreator;
     } else {
@@ -229,290 +236,291 @@
 static id CreateMapForField(GPBFieldDescriptor *field,
                             GPBMessage *autocreator) {
   id result;
-  GPBType keyType = field.mapKeyType;
-  GPBType valueType = GPBGetFieldType(field);
-  switch (keyType) {
-    case GPBTypeBool:
-      switch (valueType) {
-        case GPBTypeBool:
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  switch (keyDataType) {
+    case GPBDataTypeBool:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBBoolBoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBBoolUInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBBoolInt32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBBoolUInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBBoolInt64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBBoolFloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBBoolDoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBBoolEnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           result = [[GPBBoolObjectDictionary alloc] init];
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
-    case GPBTypeFixed32:
-    case GPBTypeUInt32:
-      switch (valueType) {
-        case GPBTypeBool:
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBUInt32BoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBUInt32UInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBUInt32Int32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBUInt32UInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBUInt32Int64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBUInt32FloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBUInt32DoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBUInt32EnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           result = [[GPBUInt32ObjectDictionary alloc] init];
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
-    case GPBTypeInt32:
-    case GPBTypeSFixed32:
-    case GPBTypeSInt32:
-      switch (valueType) {
-        case GPBTypeBool:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeSInt32:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBInt32BoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBInt32UInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBInt32Int32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBInt32UInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBInt32Int64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBInt32FloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBInt32DoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBInt32EnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           result = [[GPBInt32ObjectDictionary alloc] init];
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
-    case GPBTypeFixed64:
-    case GPBTypeUInt64:
-      switch (valueType) {
-        case GPBTypeBool:
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBUInt64BoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBUInt64UInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBUInt64Int32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBUInt64UInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBUInt64Int64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBUInt64FloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBUInt64DoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBUInt64EnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           result = [[GPBUInt64ObjectDictionary alloc] init];
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
-    case GPBTypeInt64:
-    case GPBTypeSFixed64:
-    case GPBTypeSInt64:
-      switch (valueType) {
-        case GPBTypeBool:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeSInt64:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBInt64BoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBInt64UInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBInt64Int32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBInt64UInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBInt64Int64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBInt64FloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBInt64DoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBInt64EnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           result = [[GPBInt64ObjectDictionary alloc] init];
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
-    case GPBTypeString:
-      switch (valueType) {
-        case GPBTypeBool:
+    case GPBDataTypeString:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
           result = [[GPBStringBoolDictionary alloc] init];
           break;
-        case GPBTypeFixed32:
-        case GPBTypeUInt32:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
           result = [[GPBStringUInt32Dictionary alloc] init];
           break;
-        case GPBTypeInt32:
-        case GPBTypeSFixed32:
-        case GPBTypeSInt32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
           result = [[GPBStringInt32Dictionary alloc] init];
           break;
-        case GPBTypeFixed64:
-        case GPBTypeUInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
           result = [[GPBStringUInt64Dictionary alloc] init];
           break;
-        case GPBTypeInt64:
-        case GPBTypeSFixed64:
-        case GPBTypeSInt64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
           result = [[GPBStringInt64Dictionary alloc] init];
           break;
-        case GPBTypeFloat:
+        case GPBDataTypeFloat:
           result = [[GPBStringFloatDictionary alloc] init];
           break;
-        case GPBTypeDouble:
+        case GPBDataTypeDouble:
           result = [[GPBStringDoubleDictionary alloc] init];
           break;
-        case GPBTypeEnum:
+        case GPBDataTypeEnum:
           result = [[GPBStringEnumDictionary alloc]
               initWithValidationFunction:field.enumDescriptor.enumVerifier];
           break;
-        case GPBTypeData:
-        case GPBTypeMessage:
-        case GPBTypeString:
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
           if (autocreator) {
             result = [[GPBAutocreatedDictionary alloc] init];
           } else {
             result = [[NSMutableDictionary alloc] init];
           }
           break;
-        case GPBTypeGroup:
+        case GPBDataTypeGroup:
           NSCAssert(NO, @"shouldn't happen");
           return nil;
       }
       break;
 
-    case GPBTypeFloat:
-    case GPBTypeDouble:
-    case GPBTypeEnum:
-    case GPBTypeData:
-    case GPBTypeGroup:
-    case GPBTypeMessage:
+    case GPBDataTypeFloat:
+    case GPBDataTypeDouble:
+    case GPBDataTypeEnum:
+    case GPBDataTypeBytes:
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
       NSCAssert(NO, @"shouldn't happen");
       return nil;
   }
 
   if (autocreator) {
-    if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) {
+    if ((keyDataType == GPBDataTypeString) &&
+        GPBDataTypeIsObject(valueDataType)) {
       GPBAutocreatedDictionary *autoDict = result;
       autoDict->_autocreator =  autocreator;
     } else {
@@ -608,11 +616,12 @@
 }
 
 static GPBMessage *CreateMessageWithAutocreatorForExtension(
-    Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension)
+    Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension)
     __attribute__((ns_returns_retained));
 
 static GPBMessage *CreateMessageWithAutocreatorForExtension(
-    Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) {
+    Class msgClass, GPBMessage *autocreator,
+    GPBExtensionDescriptor *extension) {
   GPBMessage *message = [[msgClass alloc] init];
   message->autocreator_ = autocreator;
   message->autocreatorExtension_ = [extension retain];
@@ -647,7 +656,7 @@
     if (field.fieldType == GPBFieldTypeRepeated) {
       id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       if (curArray == array) {
-        if (GPBFieldTypeIsObject(field)) {
+        if (GPBFieldDataTypeIsObject(field)) {
           GPBAutocreatedArray *autoArray = array;
           autoArray->_autocreator = nil;
         } else {
@@ -669,8 +678,8 @@
     if (field.fieldType == GPBFieldTypeMap) {
       id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       if (curDict == dictionary) {
-        if ((field.mapKeyType == GPBTypeString) &&
-            GPBFieldTypeIsObject(field)) {
+        if ((field.mapKeyDataType == GPBDataTypeString) &&
+            GPBFieldDataTypeIsObject(field)) {
           GPBAutocreatedDictionary *autoDict = dictionary;
           autoDict->_autocreator = nil;
         } else {
@@ -812,6 +821,9 @@
   if ((self = [self init])) {
     @try {
       [self mergeFromData:data extensionRegistry:extensionRegistry];
+      if (errorPtr) {
+        *errorPtr = nil;
+      }
     }
     @catch (NSException *exception) {
       [self release];
@@ -841,6 +853,9 @@
   if ((self = [self init])) {
     @try {
       [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+      if (errorPtr) {
+        *errorPtr = nil;
+      }
     }
     @catch (NSException *exception) {
       [self release];
@@ -885,7 +900,7 @@
         // We need to copy the array/map, but the catch is for message fields,
         // we also need to ensure all the messages as those need copying also.
         id newValue;
-        if (GPBFieldTypeIsMessage(field)) {
+        if (GPBFieldDataTypeIsMessage(field)) {
           if (field.fieldType == GPBFieldTypeRepeated) {
             NSArray *existingArray = (NSArray *)value;
             NSMutableArray *newArray =
@@ -897,7 +912,7 @@
               [copiedMsg release];
             }
           } else {
-            if (field.mapKeyType == GPBTypeString) {
+            if (field.mapKeyDataType == GPBDataTypeString) {
               // Map is an NSDictionary.
               NSDictionary *existingDict = value;
               NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
@@ -921,7 +936,7 @@
         } else {
           // Not messages (but is a map/array)...
           if (field.fieldType == GPBFieldTypeRepeated) {
-            if (GPBFieldTypeIsObject(field)) {
+            if (GPBFieldDataTypeIsObject(field)) {
               // NSArray
               newValue = [value mutableCopyWithZone:zone];
             } else {
@@ -929,7 +944,7 @@
               newValue = [value copyWithZone:zone];
             }
           } else {
-            if (field.mapKeyType == GPBTypeString) {
+            if (field.mapKeyDataType == GPBDataTypeString) {
               // NSDictionary
               newValue = [value mutableCopyWithZone:zone];
             } else {
@@ -946,7 +961,7 @@
         GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
                                                   syntax);
       }
-    } else if (GPBFieldTypeIsMessage(field)) {
+    } else if (GPBFieldDataTypeIsMessage(field)) {
       // For object types, if we have a value, copy it.  If we don't,
       // zero it to remove the pointer to something that was autocreated
       // (and the ptr just got memcpyed).
@@ -963,7 +978,8 @@
         id *typePtr = (id *)&storage[field->description_->offset];
         *typePtr = NULL;
       }
-    } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
+    } else if (GPBFieldDataTypeIsObject(field) &&
+               GPBGetHasIvarField(self, field)) {
       // A set string/data value (message picked off above), copy it.
       id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       id newValue = [value copyWithZone:zone];
@@ -973,7 +989,7 @@
       GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
                                                 syntax);
     } else {
-      // memcpy took care of the rest of the primative fields if they were set.
+      // memcpy took care of the rest of the primitive fields if they were set.
     }
   }  // for (field in descriptor->fields_)
 }
@@ -1000,7 +1016,7 @@
       id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       if (arrayOrMap) {
         if (field.fieldType == GPBFieldTypeRepeated) {
-          if (GPBFieldTypeIsObject(field)) {
+          if (GPBFieldDataTypeIsObject(field)) {
             GPBAutocreatedArray *autoArray = arrayOrMap;
             if (autoArray->_autocreator == self) {
               autoArray->_autocreator = nil;
@@ -1013,8 +1029,8 @@
             }
           }
         } else {
-          if ((field.mapKeyType == GPBTypeString) &&
-              GPBFieldTypeIsObject(field)) {
+          if ((field.mapKeyDataType == GPBDataTypeString) &&
+              GPBFieldDataTypeIsObject(field)) {
             GPBAutocreatedDictionary *autoDict = arrayOrMap;
             if (autoDict->_autocreator == self) {
               autoDict->_autocreator = nil;
@@ -1029,11 +1045,12 @@
         }
         [arrayOrMap release];
       }
-    } else if (GPBFieldTypeIsMessage(field)) {
+    } else if (GPBFieldDataTypeIsMessage(field)) {
       GPBClearAutocreatedMessageIvarWithField(self, field);
       GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       [value release];
-    } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
+    } else if (GPBFieldDataTypeIsObject(field) &&
+               GPBGetHasIvarField(self, field)) {
       id value = GPBGetObjectIvarWithField(self, field);
       [value release];
     }
@@ -1076,11 +1093,11 @@
         return NO;
       }
     }
-    if (GPBFieldTypeIsMessage(field)) {
+    if (GPBFieldDataTypeIsMessage(field)) {
       GPBFieldType fieldType = field.fieldType;
       if (fieldType == GPBFieldTypeSingle) {
         if (field.isRequired) {
-          GPBMessage *message = GPBGetMessageIvarWithField(self, field);
+          GPBMessage *message = GPBGetMessageMessageField(self, field);
           if (!message.initialized) {
             return NO;
           }
@@ -1089,7 +1106,7 @@
                    @"%@: Single message field %@ not required or optional?",
                    [self class], field.name);
           if (GPBGetHasIvarField(self, field)) {
-            GPBMessage *message = GPBGetMessageIvarWithField(self, field);
+            GPBMessage *message = GPBGetMessageMessageField(self, field);
             if (!message.initialized) {
               return NO;
             }
@@ -1103,7 +1120,7 @@
           }
         }
       } else {  // fieldType == GPBFieldTypeMap
-        if (field.mapKeyType == GPBTypeString) {
+        if (field.mapKeyDataType == GPBDataTypeString) {
           NSDictionary *map =
               GPBGetObjectIvarWithFieldNoAutocreate(self, field);
           if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
@@ -1123,11 +1140,11 @@
 
   __block BOOL result = YES;
   [extensionMap_
-      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionField *extension, id obj,
+      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension,
+                                          id obj,
                                           BOOL *stop) {
-        GPBExtensionDescriptor *extDesc = extension.descriptor;
-        if (GPBExtensionIsMessage(extDesc)) {
-          if (extDesc.isRepeated) {
+        if (GPBExtensionIsMessage(extension)) {
+          if (extension.isRepeated) {
             for (GPBMessage *msg in obj) {
               if (!msg.initialized) {
                 result = NO;
@@ -1259,15 +1276,15 @@
 //%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
 //%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
 //%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
-//%    case GPBType##TYPE:
+//%    case GPBDataType##TYPE:
 //%      if (fieldType == GPBFieldTypeRepeated) {
 //%        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
 //%        GPB##ARRAY_TYPE##Array *array =
 //%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-//%        [output write##TYPE##s:fieldNumber values:array tag:tag];
+//%        [output write##TYPE##Array:fieldNumber values:array tag:tag];
 //%      } else if (fieldType == GPBFieldTypeSingle) {
 //%        [output write##TYPE:fieldNumber
-//%              TYPE$S  value:GPBGet##REAL_TYPE##IvarWithField(self, field)];
+//%              TYPE$S  value:GPBGetMessage##REAL_TYPE##Field(self, field)];
 //%      } else {  // fieldType == GPBFieldTypeMap
 //%        // Exact type here doesn't matter.
 //%        GPBInt32##ARRAY_TYPE##Dictionary *dict =
@@ -1277,10 +1294,10 @@
 //%      break;
 //%
 //%PDDM-DEFINE FIELD_CASE2(TYPE)
-//%    case GPBType##TYPE:
+//%    case GPBDataType##TYPE:
 //%      if (fieldType == GPBFieldTypeRepeated) {
 //%        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-//%        [output write##TYPE##s:fieldNumber values:array];
+//%        [output write##TYPE##Array:fieldNumber values:array];
 //%      } else if (fieldType == GPBFieldTypeSingle) {
 //%        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
 //%        // again.
@@ -1289,8 +1306,8 @@
 //%      } else {  // fieldType == GPBFieldTypeMap
 //%        // Exact type here doesn't matter.
 //%        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-//%        GPBType mapKeyType = field.mapKeyType;
-//%        if (mapKeyType == GPBTypeString) {
+//%        GPBDataType mapKeyDataType = field.mapKeyDataType;
+//%        if (mapKeyDataType == GPBDataTypeString) {
 //%          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
 //%        } else {
 //%          [dict writeToCodedOutputStream:output asField:field];
@@ -1299,20 +1316,20 @@
 //%      break;
 //%
 
-  switch (GPBGetFieldType(field)) {
+  switch (GPBGetFieldDataType(field)) {
 
 //%PDDM-EXPAND FIELD_CASE(Bool, Bool)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeBool:
+    case GPBDataTypeBool:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBBoolArray *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeBools:fieldNumber values:array tag:tag];
+        [output writeBoolArray:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeBool:fieldNumber
-                    value:GPBGetBoolIvarWithField(self, field)];
+                    value:GPBGetMessageBoolField(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32BoolDictionary *dict =
@@ -1324,15 +1341,15 @@
 //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeFixed32:
+    case GPBDataTypeFixed32:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBUInt32Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeFixed32s:fieldNumber values:array tag:tag];
+        [output writeFixed32Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeFixed32:fieldNumber
-                       value:GPBGetUInt32IvarWithField(self, field)];
+                       value:GPBGetMessageUInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32UInt32Dictionary *dict =
@@ -1344,15 +1361,15 @@
 //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeSFixed32:
+    case GPBDataTypeSFixed32:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt32Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeSFixed32s:fieldNumber values:array tag:tag];
+        [output writeSFixed32Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeSFixed32:fieldNumber
-                        value:GPBGetInt32IvarWithField(self, field)];
+                        value:GPBGetMessageInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int32Dictionary *dict =
@@ -1364,15 +1381,15 @@
 //%PDDM-EXPAND FIELD_CASE(Float, Float)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeFloat:
+    case GPBDataTypeFloat:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBFloatArray *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeFloats:fieldNumber values:array tag:tag];
+        [output writeFloatArray:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeFloat:fieldNumber
-                     value:GPBGetFloatIvarWithField(self, field)];
+                     value:GPBGetMessageFloatField(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32FloatDictionary *dict =
@@ -1384,15 +1401,15 @@
 //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeFixed64:
+    case GPBDataTypeFixed64:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBUInt64Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeFixed64s:fieldNumber values:array tag:tag];
+        [output writeFixed64Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeFixed64:fieldNumber
-                       value:GPBGetUInt64IvarWithField(self, field)];
+                       value:GPBGetMessageUInt64Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32UInt64Dictionary *dict =
@@ -1404,15 +1421,15 @@
 //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeSFixed64:
+    case GPBDataTypeSFixed64:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt64Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeSFixed64s:fieldNumber values:array tag:tag];
+        [output writeSFixed64Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeSFixed64:fieldNumber
-                        value:GPBGetInt64IvarWithField(self, field)];
+                        value:GPBGetMessageInt64Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int64Dictionary *dict =
@@ -1424,15 +1441,15 @@
 //%PDDM-EXPAND FIELD_CASE(Double, Double)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeDouble:
+    case GPBDataTypeDouble:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBDoubleArray *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeDoubles:fieldNumber values:array tag:tag];
+        [output writeDoubleArray:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeDouble:fieldNumber
-                      value:GPBGetDoubleIvarWithField(self, field)];
+                      value:GPBGetMessageDoubleField(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32DoubleDictionary *dict =
@@ -1444,15 +1461,15 @@
 //%PDDM-EXPAND FIELD_CASE(Int32, Int32)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeInt32:
+    case GPBDataTypeInt32:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt32Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeInt32s:fieldNumber values:array tag:tag];
+        [output writeInt32Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeInt32:fieldNumber
-                     value:GPBGetInt32IvarWithField(self, field)];
+                     value:GPBGetMessageInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int32Dictionary *dict =
@@ -1464,15 +1481,15 @@
 //%PDDM-EXPAND FIELD_CASE(Int64, Int64)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeInt64:
+    case GPBDataTypeInt64:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt64Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeInt64s:fieldNumber values:array tag:tag];
+        [output writeInt64Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeInt64:fieldNumber
-                     value:GPBGetInt64IvarWithField(self, field)];
+                     value:GPBGetMessageInt64Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int64Dictionary *dict =
@@ -1484,15 +1501,15 @@
 //%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeSInt32:
+    case GPBDataTypeSInt32:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt32Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeSInt32s:fieldNumber values:array tag:tag];
+        [output writeSInt32Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeSInt32:fieldNumber
-                      value:GPBGetInt32IvarWithField(self, field)];
+                      value:GPBGetMessageInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int32Dictionary *dict =
@@ -1504,15 +1521,15 @@
 //%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeSInt64:
+    case GPBDataTypeSInt64:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBInt64Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeSInt64s:fieldNumber values:array tag:tag];
+        [output writeSInt64Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeSInt64:fieldNumber
-                      value:GPBGetInt64IvarWithField(self, field)];
+                      value:GPBGetMessageInt64Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32Int64Dictionary *dict =
@@ -1524,15 +1541,15 @@
 //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeUInt32:
+    case GPBDataTypeUInt32:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBUInt32Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeUInt32s:fieldNumber values:array tag:tag];
+        [output writeUInt32Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeUInt32:fieldNumber
-                      value:GPBGetUInt32IvarWithField(self, field)];
+                      value:GPBGetMessageUInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32UInt32Dictionary *dict =
@@ -1544,15 +1561,15 @@
 //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeUInt64:
+    case GPBDataTypeUInt64:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBUInt64Array *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeUInt64s:fieldNumber values:array tag:tag];
+        [output writeUInt64Array:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeUInt64:fieldNumber
-                      value:GPBGetUInt64IvarWithField(self, field)];
+                      value:GPBGetMessageUInt64Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32UInt64Dictionary *dict =
@@ -1564,15 +1581,15 @@
 //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeEnum:
+    case GPBDataTypeEnum:
       if (fieldType == GPBFieldTypeRepeated) {
         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
         GPBEnumArray *array =
             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeEnums:fieldNumber values:array tag:tag];
+        [output writeEnumArray:fieldNumber values:array tag:tag];
       } else if (fieldType == GPBFieldTypeSingle) {
         [output writeEnum:fieldNumber
-                    value:GPBGetInt32IvarWithField(self, field)];
+                    value:GPBGetMessageInt32Field(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         GPBInt32EnumDictionary *dict =
@@ -1581,23 +1598,23 @@
       }
       break;
 
-//%PDDM-EXPAND FIELD_CASE2(Data)
+//%PDDM-EXPAND FIELD_CASE2(Bytes)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeData:
+    case GPBDataTypeBytes:
       if (fieldType == GPBFieldTypeRepeated) {
         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeDatas:fieldNumber values:array];
+        [output writeBytesArray:fieldNumber values:array];
       } else if (fieldType == GPBFieldTypeSingle) {
         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
         // again.
-        [output writeData:fieldNumber
-                    value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+        [output writeBytes:fieldNumber
+                     value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        GPBType mapKeyType = field.mapKeyType;
-        if (mapKeyType == GPBTypeString) {
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
         } else {
           [dict writeToCodedOutputStream:output asField:field];
@@ -1608,10 +1625,10 @@
 //%PDDM-EXPAND FIELD_CASE2(String)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeString:
+    case GPBDataTypeString:
       if (fieldType == GPBFieldTypeRepeated) {
         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeStrings:fieldNumber values:array];
+        [output writeStringArray:fieldNumber values:array];
       } else if (fieldType == GPBFieldTypeSingle) {
         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
         // again.
@@ -1620,8 +1637,8 @@
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        GPBType mapKeyType = field.mapKeyType;
-        if (mapKeyType == GPBTypeString) {
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
         } else {
           [dict writeToCodedOutputStream:output asField:field];
@@ -1632,10 +1649,10 @@
 //%PDDM-EXPAND FIELD_CASE2(Message)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeMessage:
+    case GPBDataTypeMessage:
       if (fieldType == GPBFieldTypeRepeated) {
         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeMessages:fieldNumber values:array];
+        [output writeMessageArray:fieldNumber values:array];
       } else if (fieldType == GPBFieldTypeSingle) {
         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
         // again.
@@ -1644,8 +1661,8 @@
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        GPBType mapKeyType = field.mapKeyType;
-        if (mapKeyType == GPBTypeString) {
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
         } else {
           [dict writeToCodedOutputStream:output asField:field];
@@ -1656,10 +1673,10 @@
 //%PDDM-EXPAND FIELD_CASE2(Group)
 // This block of code is generated, do not edit it directly.
 
-    case GPBTypeGroup:
+    case GPBDataTypeGroup:
       if (fieldType == GPBFieldTypeRepeated) {
         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        [output writeGroups:fieldNumber values:array];
+        [output writeGroupArray:fieldNumber values:array];
       } else if (fieldType == GPBFieldTypeSingle) {
         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
         // again.
@@ -1668,8 +1685,8 @@
       } else {  // fieldType == GPBFieldTypeMap
         // Exact type here doesn't matter.
         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-        GPBType mapKeyType = field.mapKeyType;
-        if (mapKeyType == GPBTypeString) {
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
         } else {
           [dict writeToCodedOutputStream:output asField:field];
@@ -1683,22 +1700,20 @@
 
 #pragma mark - Extensions
 
-- (id)getExtension:(GPBExtensionField *)extension {
+- (id)getExtension:(GPBExtensionDescriptor *)extension {
   CheckExtension(self, extension);
   id value = [extensionMap_ objectForKey:extension];
   if (value != nil) {
     return value;
   }
 
-  GPBExtensionDescriptor *extDesc = extension.descriptor;
-
   // No default for repeated.
-  if (extDesc.isRepeated) {
+  if (extension.isRepeated) {
     return nil;
   }
   // Non messages get their default.
-  if (!GPBExtensionIsMessage(extDesc)) {
-    return [extension defaultValue];
+  if (!GPBExtensionIsMessage(extension)) {
+    return extension.defaultValue;
   }
 
   // Check for an autocreated value.
@@ -1706,7 +1721,7 @@
   value = [autocreatedExtensionMap_ objectForKey:extension];
   if (!value) {
     // Auto create the message extensions to match normal fields.
-    value = CreateMessageWithAutocreatorForExtension(extDesc.msgClass, self,
+    value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self,
                                                      extension);
 
     if (autocreatedExtensionMap_ == nil) {
@@ -1723,12 +1738,12 @@
   return value;
 }
 
-- (id)getExistingExtension:(GPBExtensionField *)extension {
+- (id)getExistingExtension:(GPBExtensionDescriptor *)extension {
   // This is an internal method so we don't need to call CheckExtension().
   return [extensionMap_ objectForKey:extension];
 }
 
-- (BOOL)hasExtension:(GPBExtensionField *)extension {
+- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension {
 #if DEBUG
   CheckExtension(self, extension);
 #endif  // DEBUG
@@ -1745,11 +1760,11 @@
       sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
   uint32_t start = range.start;
   uint32_t end = range.end;
-  for (GPBExtensionField *extension in sortedExtensions) {
-    uint32_t fieldNumber = [extension fieldNumber];
+  for (GPBExtensionDescriptor *extension in sortedExtensions) {
+    uint32_t fieldNumber = extension.fieldNumber;
     if (fieldNumber >= start && fieldNumber < end) {
       id value = [extensionMap_ objectForKey:extension];
-      [extension writeValue:value includingTagToCodedOutputStream:output];
+      GPBWriteExtensionValueToOutputStream(extension, value, output);
     }
   }
 }
@@ -1759,7 +1774,7 @@
       sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
 }
 
-- (void)setExtension:(GPBExtensionField *)extension value:(id)value {
+- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
   if (!value) {
     [self clearExtension:extension];
     return;
@@ -1767,7 +1782,7 @@
 
   CheckExtension(self, extension);
 
-  if ([extension isRepeated]) {
+  if (extension.repeated) {
     [NSException raise:NSInvalidArgumentException
                 format:@"Must call addExtension() for repeated types."];
   }
@@ -1778,7 +1793,7 @@
 
   [extensionMap_ setObject:value forKey:extension];
 
-  GPBExtensionDescriptor *descriptor = extension.descriptor;
+  GPBExtensionDescriptor *descriptor = extension;
 
   if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
     GPBMessage *autocreatedValue =
@@ -1793,10 +1808,10 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-- (void)addExtension:(GPBExtensionField *)extension value:(id)value {
+- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value {
   CheckExtension(self, extension);
 
-  if (![extension isRepeated]) {
+  if (!extension.repeated) {
     [NSException raise:NSInvalidArgumentException
                 format:@"Must call setExtension() for singular types."];
   }
@@ -1814,12 +1829,12 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-- (void)setExtension:(GPBExtensionField *)extension
+- (void)setExtension:(GPBExtensionDescriptor *)extension
                index:(NSUInteger)idx
                value:(id)value {
   CheckExtension(self, extension);
 
-  if (![extension isRepeated]) {
+  if (!extension.repeated) {
     [NSException raise:NSInvalidArgumentException
                 format:@"Must call setExtension() for singular types."];
   }
@@ -1834,7 +1849,7 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-- (void)clearExtension:(GPBExtensionField *)extension {
+- (void)clearExtension:(GPBExtensionDescriptor *)extension {
   CheckExtension(self, extension);
 
   // Only become visible if there was actually a value to clear.
@@ -1862,7 +1877,7 @@
   if (GPBCodedInputStreamIsAtEnd(state)) {
     return;
   }
-  NSData *data = GPBCodedInputStreamReadRetainedDataNoCopy(state);
+  NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state);
   if (data == nil) {
     return;
   }
@@ -1903,6 +1918,9 @@
   @try {
     [message mergeDelimitedFromCodedInputStream:input
                               extensionRegistry:extensionRegistry];
+    if (errorPtr) {
+      *errorPtr = nil;
+    }
   }
   @catch (NSException *exception) {
     [message release];
@@ -1942,7 +1960,7 @@
       extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   uint32_t typeId = 0;
   NSData *rawBytes = nil;
-  GPBExtensionField *extension = nil;
+  GPBExtensionDescriptor *extension = nil;
   GPBCodedInputStreamState *state = &input->state_;
   while (true) {
     uint32_t tag = GPBCodedInputStreamReadTag(state);
@@ -1953,11 +1971,12 @@
     if (tag == GPBWireFormatMessageSetTypeIdTag) {
       typeId = GPBCodedInputStreamReadUInt32(state);
       if (typeId != 0) {
-        extension = [extensionRegistry getExtension:[self descriptor]
-                                        fieldNumber:typeId];
+        extension = [extensionRegistry extensionForDescriptor:[self descriptor]
+                                                  fieldNumber:typeId];
       }
     } else if (tag == GPBWireFormatMessageSetMessageTag) {
-      rawBytes = [GPBCodedInputStreamReadRetainedDataNoCopy(state) autorelease];
+      rawBytes =
+          [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
     } else {
       if (![input skipField:tag]) {
         break;
@@ -1971,9 +1990,11 @@
     if (extension != nil) {
       GPBCodedInputStream *newInput =
           [[GPBCodedInputStream alloc] initWithData:rawBytes];
-      [extension mergeFromCodedInputStream:newInput
-                         extensionRegistry:extensionRegistry
-                                   message:self];
+      GPBExtensionMergeFromInputStream(extension,
+                                       extension.packable,
+                                       newInput,
+                                       extensionRegistry,
+                                       self);
       [newInput release];
     } else {
       GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
@@ -1989,19 +2010,33 @@
   int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
 
   GPBDescriptor *descriptor = [self descriptor];
-  GPBExtensionField *extension =
-      [extensionRegistry getExtension:descriptor fieldNumber:fieldNumber];
-
+  GPBExtensionDescriptor *extension =
+      [extensionRegistry extensionForDescriptor:descriptor
+                                    fieldNumber:fieldNumber];
   if (extension == nil) {
     if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
       [self parseMessageSet:input extensionRegistry:extensionRegistry];
       return YES;
     }
   } else {
-    if ([extension wireType] == wireType) {
-      [extension mergeFromCodedInputStream:input
-                         extensionRegistry:extensionRegistry
-                                   message:self];
+    if (extension.wireType == wireType) {
+      GPBExtensionMergeFromInputStream(extension,
+                                       extension.packable,
+                                       input,
+                                       extensionRegistry,
+                                       self);
+      return YES;
+    }
+    // Primitive, repeated types can be packed on unpacked on the wire, and are
+    // parsed either way.
+    if ([extension isRepeated] &&
+        !GPBDataTypeIsObject(extension->description_->dataType) &&
+        (extension.alternateWireType == wireType)) {
+      GPBExtensionMergeFromInputStream(extension,
+                                       !extension.packable,
+                                       input,
+                                       extensionRegistry,
+                                       self);
       return YES;
     }
   }
@@ -2020,1053 +2055,312 @@
 
 #pragma mark - MergeFromCodedInputStream Support
 
-typedef struct MergeFromCodedInputStreamContext {
-  GPBMessage *self;
-  GPBCodedInputStream *stream;
-  GPBMessage *result;
-  GPBExtensionRegistry *registry;
-  uint32_t tag;
-  GPBFileSyntax syntax;
-} MergeFromCodedInputStreamContext;
-
-//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(NAME, TYPE, ARRAY_TYPE)
-//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field,
-//%                                           NAME$S  void *voidContext) {
-//%  MergeFromCodedInputStreamContext *context =
-//%      (MergeFromCodedInputStreamContext *)voidContext;
-//%  GPBCodedInputStreamState *state = &context->stream->state_;
-//%  GPBFieldType fieldType = field.fieldType;
-//%  if (fieldType == GPBFieldTypeRepeated) {
-//%    GPB##ARRAY_TYPE##Array *array =
-//%        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-//%    if (field.isPackable) {
-//%      int32_t length = GPBCodedInputStreamReadInt32(state);
-//%      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-//%      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-//%        TYPE val = GPBCodedInputStreamRead##NAME(state);
-//%        [array addValue:val];
-//%      }
-//%      GPBCodedInputStreamPopLimit(state, limit);
-//%    } else {
-//%      TYPE val = GPBCodedInputStreamRead##NAME(state);
-//%      [array addValue:val];
-//%    }
-//%  } else if (fieldType == GPBFieldTypeSingle) {
-//%    TYPE val = GPBCodedInputStreamRead##NAME(state);
-//%    GPBSet##ARRAY_TYPE##IvarWithFieldInternal(context->result, field, val,
-//%           ARRAY_TYPE$S                     context->syntax);
-//%  } else {  // fieldType == GPBFieldTypeMap
-//%    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-//%    GPBInt32Int32Dictionary *map =
-//%        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-//%    [context->stream readMapEntry:map
-//%                extensionRegistry:nil
-//%                            field:field
-//%                    parentMessage:context->result];
-//%  }
-//%  return NO;
-//%}
-//%
-//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(NAME)
-//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field,
-//%                                           NAME$S  void *voidContext) {
-//%  MergeFromCodedInputStreamContext *context = voidContext;
-//%  GPBCodedInputStreamState *state = &context->stream->state_;
-//%  GPBFieldType fieldType = field.fieldType;
-//%  if (fieldType == GPBFieldTypeMap) {
-//%    // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
-//%    id map =
-//%        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-//%    [context->stream readMapEntry:map
-//%                extensionRegistry:nil
-//%                            field:field
-//%                    parentMessage:context->result];
-//%  } else {
-//%    id val = GPBCodedInputStreamReadRetained##NAME(state);
-//%    if (fieldType == GPBFieldTypeRepeated) {
-//%      NSMutableArray *array =
-//%          GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-//%      [array addObject:val];
-//%      [val release];
-//%    } else {  // fieldType == GPBFieldTypeSingle
-//%      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
-//%                                                context->syntax);
-//%    }
-//%  }
-//%  return NO;
-//%}
-//%
-
-static BOOL DynamicMergeFromCodedInputStreamGroup(GPBFieldDescriptor *field,
-                                                  void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  int number = GPBFieldNumber(field);
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBMessage *message = [[field.msgClass alloc] init];
-    NSMutableArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    [context->stream readGroup:number
-                       message:message
-             extensionRegistry:context->registry];
-    [array addObject:message];
-    [message release];
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL has = GPBGetHasIvarField(context->result, field);
-    if (has) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      GPBMessage *message =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
-      [context->stream readGroup:number
-                         message:message
-               extensionRegistry:context->registry];
-    } else {
-      GPBMessage *message = [[field.msgClass alloc] init];
-      [context->stream readGroup:number
-                         message:message
-               extensionRegistry:context->registry];
-      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
-                                                context->syntax);
+static void MergeSingleFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                             \
+    case GPBDataType##NAME: {                                              \
+      TYPE val = GPBCodedInputStreamRead##NAME(&input->state_);            \
+      GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax);  \
+      break;                                                               \
+            }
+#define CASE_SINGLE_OBJECT(NAME)                                           \
+    case GPBDataType##NAME: {                                              \
+      id val = GPBCodedInputStreamReadRetained##NAME(&input->state_);      \
+      GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
+      break;                                                               \
     }
-  } else {  // fieldType == GPBFieldTypeMap
-    NSCAssert(NO, @"Shouldn't happen");
-    return YES;
-  }
-  return NO;
-}
+      CASE_SINGLE_POD(Bool, BOOL, Bool)
+      CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
+      CASE_SINGLE_POD(SFixed32, int32_t, Int32)
+      CASE_SINGLE_POD(Float, float, Float)
+      CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
+      CASE_SINGLE_POD(SFixed64, int64_t, Int64)
+      CASE_SINGLE_POD(Double, double, Double)
+      CASE_SINGLE_POD(Int32, int32_t, Int32)
+      CASE_SINGLE_POD(Int64, int64_t, Int64)
+      CASE_SINGLE_POD(SInt32, int32_t, Int32)
+      CASE_SINGLE_POD(SInt64, int64_t, Int64)
+      CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
+      CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
+      CASE_SINGLE_OBJECT(Bytes)
+      CASE_SINGLE_OBJECT(String)
+#undef CASE_SINGLE_POD
+#undef CASE_SINGLE_OBJECT
 
-static BOOL DynamicMergeFromCodedInputStreamMessage(GPBFieldDescriptor *field,
-                                                    void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBMessage *message = [[field.msgClass alloc] init];
-    NSMutableArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    [context->stream readMessage:message extensionRegistry:context->registry];
-    [array addObject:message];
-    [message release];
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL has = GPBGetHasIvarField(context->result, field);
-    if (has) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      GPBMessage *message =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
-      [context->stream readMessage:message extensionRegistry:context->registry];
-    } else {
-      GPBMessage *message = [[field.msgClass alloc] init];
-      [context->stream readMessage:message extensionRegistry:context->registry];
-      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
-                                                context->syntax);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // GPB*Dictionary or NSDictionary, exact type doesn't matter.
-    id map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:context->registry
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-static BOOL DynamicMergeFromCodedInputStreamEnum(GPBFieldDescriptor *field,
-                                                 void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  int number = GPBFieldNumber(field);
-  BOOL hasPreservingUnknownEnumSemantics =
-      GPBHasPreservingUnknownEnumSemantics(context->syntax);
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBEnumArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int32_t val = GPBCodedInputStreamReadEnum(state);
-        if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
-          [array addRawValue:val];
-        } else {
-          GPBUnknownFieldSet *unknownFields =
-              GetOrMakeUnknownFields(context->self);
-          [unknownFields mergeVarintField:number value:val];
-        }
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int32_t val = GPBCodedInputStreamReadEnum(state);
-      if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
-        [array addRawValue:val];
+    case GPBDataTypeMessage: {
+      if (GPBGetHasIvarField(self, field)) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
+        // check again.
+        GPBMessage *message =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [input readMessage:message extensionRegistry:extensionRegistry];
       } else {
-        GPBUnknownFieldSet *unknownFields =
-            GetOrMakeUnknownFields(context->self);
-        [unknownFields mergeVarintField:number value:val];
+        GPBMessage *message = [[field.msgClass alloc] init];
+        [input readMessage:message extensionRegistry:extensionRegistry];
+        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+      }
+      break;
+    }
+
+    case GPBDataTypeGroup: {
+      if (GPBGetHasIvarField(self, field)) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
+        // check again.
+        GPBMessage *message =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [input readGroup:GPBFieldNumber(field)
+                      message:message
+            extensionRegistry:extensionRegistry];
+      } else {
+        GPBMessage *message = [[field.msgClass alloc] init];
+        [input readGroup:GPBFieldNumber(field)
+                      message:message
+            extensionRegistry:extensionRegistry];
+        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+      }
+      break;
+    }
+
+    case GPBDataTypeEnum: {
+      int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
+      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+          [field isValidEnumValue:val]) {
+        GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
+      } else {
+        GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+        [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
       }
     }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int32_t val = GPBCodedInputStreamReadEnum(state);
-    if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
-      GPBSetInt32IvarWithFieldInternal(context->result, field, val,
-                                       context->syntax);
-    } else {
-      GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(context->self);
-      [unknownFields mergeVarintField:number value:val];
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a
-    // GPB*EnumDictionary.
-    GPBInt32EnumDictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:context->registry
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
+  }  // switch
 }
 
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Bool, BOOL, Bool)
-// This block of code is generated, do not edit it directly.
+static void MergeRepeatedPackedFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  GPBCodedInputStreamState *state = &input->state_;
+  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  int32_t length = GPBCodedInputStreamReadInt32(state);
+  size_t limit = GPBCodedInputStreamPushLimit(state, length);
+  while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+    switch (fieldDataType) {
+#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE)      \
+     case GPBDataType##NAME: {                                \
+       TYPE val = GPBCodedInputStreamRead##NAME(state);       \
+       [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
+       break;                                                 \
+     }
+        CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool)
+        CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32)
+        CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(Float, float, Float)
+        CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64)
+        CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(Double, double, Double)
+        CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32)
+        CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64)
+#undef CASE_REPEATED_PACKED_POD
 
-static BOOL DynamicMergeFromCodedInputStreamBool(GPBFieldDescriptor *field,
-                                                 void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBBoolArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        BOOL val = GPBCodedInputStreamReadBool(state);
-        [array addValue:val];
+      case GPBDataTypeBytes:
+      case GPBDataTypeString:
+      case GPBDataTypeMessage:
+      case GPBDataTypeGroup:
+        NSCAssert(NO, @"Non primitive types can't be packed");
+        break;
+
+      case GPBDataTypeEnum: {
+        int32_t val = GPBCodedInputStreamReadEnum(state);
+        if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+            [field isValidEnumValue:val]) {
+          [(GPBEnumArray*)genericArray addRawValue:val];
+        } else {
+          GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+          [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
+        }
+        break;
       }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      BOOL val = GPBCodedInputStreamReadBool(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL val = GPBCodedInputStreamReadBool(state);
-    GPBSetBoolIvarWithFieldInternal(context->result, field, val,
-                                    context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
+    }  // switch
+  }  // while(BytesUntilLimit() > 0)
+  GPBCodedInputStreamPopLimit(state, limit);
 }
 
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamInt32(GPBFieldDescriptor *field,
-                                                  void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int32_t val = GPBCodedInputStreamReadInt32(state);
-        [array addValue:val];
+static void MergeRepeatedNotPackedFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+  GPBCodedInputStreamState *state = &input->state_;
+  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  switch (GPBGetFieldDataType(field)) {
+#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
+   case GPBDataType##NAME: {                                 \
+     TYPE val = GPBCodedInputStreamRead##NAME(state);        \
+     [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val];  \
+     break;                                                  \
+   }
+#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME)                \
+   case GPBDataType##NAME: {                                 \
+     id val = GPBCodedInputStreamReadRetained##NAME(state);  \
+     [(NSMutableArray*)genericArray addObject:val];          \
+     [val release];                                          \
+     break;                                                  \
+   }
+      CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool)
+      CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32)
+      CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(Float, float, Float)
+      CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64)
+      CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(Double, double, Double)
+      CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32)
+      CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64)
+      CASE_REPEATED_NOT_PACKED_OBJECT(Bytes)
+      CASE_REPEATED_NOT_PACKED_OBJECT(String)
+#undef CASE_REPEATED_NOT_PACKED_POD
+#undef CASE_NOT_PACKED_OBJECT
+    case GPBDataTypeMessage: {
+      GPBMessage *message = [[field.msgClass alloc] init];
+      [input readMessage:message extensionRegistry:extensionRegistry];
+      [(NSMutableArray*)genericArray addObject:message];
+      [message release];
+      break;
+    }
+    case GPBDataTypeGroup: {
+      GPBMessage *message = [[field.msgClass alloc] init];
+      [input readGroup:GPBFieldNumber(field)
+                    message:message
+          extensionRegistry:extensionRegistry];
+      [(NSMutableArray*)genericArray addObject:message];
+      [message release];
+      break;
+    }
+    case GPBDataTypeEnum: {
+      int32_t val = GPBCodedInputStreamReadEnum(state);
+      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+          [field isValidEnumValue:val]) {
+        [(GPBEnumArray*)genericArray addRawValue:val];
+      } else {
+        GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+        [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
       }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int32_t val = GPBCodedInputStreamReadInt32(state);
-      [array addValue:val];
+      break;
     }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int32_t val = GPBCodedInputStreamReadInt32(state);
-    GPBSetInt32IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
+  }  // switch
 }
 
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamSInt32(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int32_t val = GPBCodedInputStreamReadSInt32(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int32_t val = GPBCodedInputStreamReadSInt32(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int32_t val = GPBCodedInputStreamReadSInt32(state);
-    GPBSetInt32IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamSFixed32(GPBFieldDescriptor *field,
-                                                     void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int32_t val = GPBCodedInputStreamReadSFixed32(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int32_t val = GPBCodedInputStreamReadSFixed32(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int32_t val = GPBCodedInputStreamReadSFixed32(state);
-    GPBSetInt32IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt32, uint32_t, UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamUInt32(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt32Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        uint32_t val = GPBCodedInputStreamReadUInt32(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      uint32_t val = GPBCodedInputStreamReadUInt32(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    uint32_t val = GPBCodedInputStreamReadUInt32(state);
-    GPBSetUInt32IvarWithFieldInternal(context->result, field, val,
-                                      context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed32, uint32_t, UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamFixed32(GPBFieldDescriptor *field,
-                                                    void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt32Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        uint32_t val = GPBCodedInputStreamReadFixed32(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      uint32_t val = GPBCodedInputStreamReadFixed32(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    uint32_t val = GPBCodedInputStreamReadFixed32(state);
-    GPBSetUInt32IvarWithFieldInternal(context->result, field, val,
-                                      context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamInt64(GPBFieldDescriptor *field,
-                                                  void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int64_t val = GPBCodedInputStreamReadInt64(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int64_t val = GPBCodedInputStreamReadInt64(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int64_t val = GPBCodedInputStreamReadInt64(state);
-    GPBSetInt64IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamSFixed64(GPBFieldDescriptor *field,
-                                                     void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int64_t val = GPBCodedInputStreamReadSFixed64(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int64_t val = GPBCodedInputStreamReadSFixed64(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int64_t val = GPBCodedInputStreamReadSFixed64(state);
-    GPBSetInt64IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamSInt64(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        int64_t val = GPBCodedInputStreamReadSInt64(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      int64_t val = GPBCodedInputStreamReadSInt64(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    int64_t val = GPBCodedInputStreamReadSInt64(state);
-    GPBSetInt64IvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt64, uint64_t, UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamUInt64(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt64Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        uint64_t val = GPBCodedInputStreamReadUInt64(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      uint64_t val = GPBCodedInputStreamReadUInt64(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    uint64_t val = GPBCodedInputStreamReadUInt64(state);
-    GPBSetUInt64IvarWithFieldInternal(context->result, field, val,
-                                      context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed64, uint64_t, UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamFixed64(GPBFieldDescriptor *field,
-                                                    void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt64Array *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        uint64_t val = GPBCodedInputStreamReadFixed64(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      uint64_t val = GPBCodedInputStreamReadFixed64(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    uint64_t val = GPBCodedInputStreamReadFixed64(state);
-    GPBSetUInt64IvarWithFieldInternal(context->result, field, val,
-                                      context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Float, float, Float)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamFloat(GPBFieldDescriptor *field,
-                                                  void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBFloatArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        float val = GPBCodedInputStreamReadFloat(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      float val = GPBCodedInputStreamReadFloat(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    float val = GPBCodedInputStreamReadFloat(state);
-    GPBSetFloatIvarWithFieldInternal(context->result, field, val,
-                                     context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Double, double, Double)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamDouble(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context =
-      (MergeFromCodedInputStreamContext *)voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBDoubleArray *array =
-        GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-    if (field.isPackable) {
-      int32_t length = GPBCodedInputStreamReadInt32(state);
-      size_t limit = GPBCodedInputStreamPushLimit(state, length);
-      while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-        double val = GPBCodedInputStreamReadDouble(state);
-        [array addValue:val];
-      }
-      GPBCodedInputStreamPopLimit(state, limit);
-    } else {
-      double val = GPBCodedInputStreamReadDouble(state);
-      [array addValue:val];
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    double val = GPBCodedInputStreamReadDouble(state);
-    GPBSetDoubleIvarWithFieldInternal(context->result, field, val,
-                                      context->syntax);
-  } else {  // fieldType == GPBFieldTypeMap
-    // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
-    GPBInt32Int32Dictionary *map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(String)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamString(GPBFieldDescriptor *field,
-                                                   void *voidContext) {
-  MergeFromCodedInputStreamContext *context = voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeMap) {
-    // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
-    id map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  } else {
-    id val = GPBCodedInputStreamReadRetainedString(state);
-    if (fieldType == GPBFieldTypeRepeated) {
-      NSMutableArray *array =
-          GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-      [array addObject:val];
-      [val release];
-    } else {  // fieldType == GPBFieldTypeSingle
-      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
-                                                context->syntax);
-    }
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(Data)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicMergeFromCodedInputStreamData(GPBFieldDescriptor *field,
-                                                 void *voidContext) {
-  MergeFromCodedInputStreamContext *context = voidContext;
-  GPBCodedInputStreamState *state = &context->stream->state_;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeMap) {
-    // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
-    id map =
-        GetOrCreateMapIvarWithField(context->result, field, context->syntax);
-    [context->stream readMapEntry:map
-                extensionRegistry:nil
-                            field:field
-                    parentMessage:context->result];
-  } else {
-    id val = GPBCodedInputStreamReadRetainedData(state);
-    if (fieldType == GPBFieldTypeRepeated) {
-      NSMutableArray *array =
-          GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
-      [array addObject:val];
-      [val release];
-    } else {  // fieldType == GPBFieldTypeSingle
-      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
-                                                context->syntax);
-    }
-  }
-  return NO;
-}
-
-//%PDDM-EXPAND-END (15 expansions)
-
 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
                 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   GPBDescriptor *descriptor = [self descriptor];
   GPBFileSyntax syntax = descriptor.file.syntax;
-  MergeFromCodedInputStreamContext context = {
-    self, input, self, extensionRegistry, 0, syntax
-  };
-  GPBApplyStrictFunctions funcs =
-      GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicMergeFromCodedInputStream);
+  GPBCodedInputStreamState *state = &input->state_;
+  uint32_t tag = 0;
   NSUInteger startingIndex = 0;
   NSArray *fields = descriptor->fields_;
-  NSUInteger count = fields.count;
+  NSUInteger numFields = fields.count;
   while (YES) {
     BOOL merged = NO;
-    context.tag = GPBCodedInputStreamReadTag(&input->state_);
-    for (NSUInteger i = 0; i < count; ++i) {
-      if (startingIndex >= count) startingIndex = 0;
+    tag = GPBCodedInputStreamReadTag(state);
+    for (NSUInteger i = 0; i < numFields; ++i) {
+      if (startingIndex >= numFields) startingIndex = 0;
       GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
-      if (GPBFieldTag(fieldDescriptor) == context.tag) {
-        GPBApplyFunction function = funcs[GPBGetFieldType(fieldDescriptor)];
-        function(fieldDescriptor, &context);
+      if (GPBFieldTag(fieldDescriptor) == tag) {
+        GPBFieldType fieldType = fieldDescriptor.fieldType;
+        if (fieldType == GPBFieldTypeSingle) {
+          MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax,
+                                               input, extensionRegistry);
+          // Well formed protos will only have a single field once, advance
+          // the starting index to the next field.
+          startingIndex += 1;
+        } else if (fieldType == GPBFieldTypeRepeated) {
+          if (fieldDescriptor.isPackable) {
+            MergeRepeatedPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input);
+            // Well formed protos will only have a repeated field that is
+            // packed once, advance the starting index to the next field.
+            startingIndex += 1;
+          } else {
+            MergeRepeatedNotPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input, extensionRegistry);
+          }
+        } else {  // fieldType == GPBFieldTypeMap
+          // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
+          // point.
+          id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
+          [input readMapEntry:map
+            extensionRegistry:extensionRegistry
+                        field:fieldDescriptor
+                parentMessage:self];
+        }
         merged = YES;
         break;
       } else {
         startingIndex += 1;
       }
-    }
+    }  // for(i < numFields)
+
     if (!merged) {
-      if (context.tag == 0) {
+      // Primitive, repeated types can be packed on unpacked on the wire, and
+      // are parsed either way.  The above loop covered tag in the preferred
+      // for, so this need to check the alternate form.
+      for (NSUInteger i = 0; i < numFields; ++i) {
+        if (startingIndex >= numFields) startingIndex = 0;
+        GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
+        if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
+            !GPBFieldDataTypeIsObject(fieldDescriptor) &&
+            (GPBFieldAlternateTag(fieldDescriptor) == tag)) {
+          BOOL alternateIsPacked = !fieldDescriptor.isPackable;
+          if (alternateIsPacked) {
+            MergeRepeatedPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input);
+            // Well formed protos will only have a repeated field that is
+            // packed once, advance the starting index to the next field.
+            startingIndex += 1;
+          } else {
+            MergeRepeatedNotPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input, extensionRegistry);
+          }
+          merged = YES;
+          break;
+        } else {
+          startingIndex += 1;
+        }
+      }
+    }
+
+    if (!merged) {
+      if (tag == 0) {
         // zero signals EOF / limit reached
         return;
       } else {
         if (GPBPreserveUnknownFields(syntax)) {
           if (![self parseUnknownField:input
                      extensionRegistry:extensionRegistry
-                                   tag:context.tag]) {
+                                   tag:tag]) {
             // it's an endgroup tag
             return;
           }
         } else {
-          if (![input skipField:context.tag]) {
+          if (![input skipField:tag]) {
             return;
           }
         }
       }
-    }
-  }
+    }  // if(!merged)
+
+  }  // while(YES)
 }
 
 #pragma mark - MergeFrom Support
 
-typedef struct MergeFromContext {
-  GPBMessage *other;
-  GPBMessage *result;
-  GPBFileSyntax syntax;
-} MergeFromContext;
-
-//%PDDM-DEFINE GPB_MERGE_FROM_FUNC(NAME)
-//%static BOOL MergeFrom##NAME(GPBFieldDescriptor *field, void *voidContext) {
-//%  MergeFromContext *context = (MergeFromContext *)voidContext;
-//%  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-//%  if (otherHas) {
-//%    GPBSet##NAME##IvarWithFieldInternal(
-//%        context->result, field, GPBGet##NAME##IvarWithField(context->other, field),
-//%        context->syntax);
-//%  }
-//%  return YES;
-//%}
-//%
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Bool)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromBool(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetBoolIvarWithFieldInternal(
-        context->result, field, GPBGetBoolIvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromInt32(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetInt32IvarWithFieldInternal(
-        context->result, field, GPBGetInt32IvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromUInt32(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetUInt32IvarWithFieldInternal(
-        context->result, field, GPBGetUInt32IvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromInt64(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetInt64IvarWithFieldInternal(
-        context->result, field, GPBGetInt64IvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromUInt64(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetUInt64IvarWithFieldInternal(
-        context->result, field, GPBGetUInt64IvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Float)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromFloat(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetFloatIvarWithFieldInternal(
-        context->result, field, GPBGetFloatIvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Double)
-// This block of code is generated, do not edit it directly.
-
-static BOOL MergeFromDouble(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  BOOL otherHas = GPBGetHasIvarField(context->other, field);
-  if (otherHas) {
-    GPBSetDoubleIvarWithFieldInternal(
-        context->result, field, GPBGetDoubleIvarWithField(context->other, field),
-        context->syntax);
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND-END (7 expansions)
-
-static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) {
-  MergeFromContext *context = (MergeFromContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    // In the case of a list, they need to be appended, and there is no
-    // _hasIvar to worry about setting.
-    id otherArray =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
-    if (otherArray) {
-      GPBType fieldDataType = field->description_->type;
-      if (GPBTypeIsObject(fieldDataType)) {
-        NSMutableArray *resultArray = GetOrCreateArrayIvarWithField(
-            context->result, field, context->syntax);
-        [resultArray addObjectsFromArray:otherArray];
-      } else if (fieldDataType == GPBTypeEnum) {
-        GPBEnumArray *resultArray = GetOrCreateArrayIvarWithField(
-            context->result, field, context->syntax);
-        [resultArray addRawValuesFromArray:otherArray];
-      } else {
-        // The array type doesn't matter, that all implment
-        // -addValuesFromArray:.
-        GPBInt32Array *resultArray = GetOrCreateArrayIvarWithField(
-            context->result, field, context->syntax);
-        [resultArray addValuesFromArray:otherArray];
-      }
-    }
-    return YES;
-  }
-  if (fieldType == GPBFieldTypeMap) {
-    // In the case of a map, they need to be merged, and there is no
-    // _hasIvar to worry about setting.
-    id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
-    if (otherDict) {
-      GPBType keyType = field.mapKeyType;
-      GPBType valueType = field->description_->type;
-      if (GPBTypeIsObject(keyType) && GPBTypeIsObject(valueType)) {
-        NSMutableDictionary *resultDict = GetOrCreateMapIvarWithField(
-            context->result, field, context->syntax);
-        [resultDict addEntriesFromDictionary:otherDict];
-      } else if (valueType == GPBTypeEnum) {
-        // The exact type doesn't matter, just need to know it is a
-        // GPB*EnumDictionary.
-        GPBInt32EnumDictionary *resultDict = GetOrCreateMapIvarWithField(
-            context->result, field, context->syntax);
-        [resultDict addRawEntriesFromDictionary:otherDict];
-      } else {
-        // The exact type doesn't matter, they all implement
-        // -addEntriesFromDictionary:.
-        GPBInt32Int32Dictionary *resultDict = GetOrCreateMapIvarWithField(
-            context->result, field, context->syntax);
-        [resultDict addEntriesFromDictionary:otherDict];
-      }
-    }
-    return YES;
-  }
-
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNumber = GPBFieldNumber(field);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNumber);
-  if (!otherHas) {
-    return YES;
-  }
-  // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster.
-  id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
-  if (GPBFieldTypeIsMessage(field)) {
-    if (GPBGetHasIvar(context->result, hasIndex, fieldNumber)) {
-      GPBMessage *message =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
-      [message mergeFrom:otherVal];
-    } else {
-      GPBMessage *message = [otherVal copy];
-      GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
-                                                context->syntax);
-    }
-  } else {
-    GPBSetObjectIvarWithFieldInternal(context->result, field, otherVal,
-                                      context->syntax);
-  }
-  return YES;
-}
-
 - (void)mergeFrom:(GPBMessage *)other {
   Class selfClass = [self class];
   Class otherClass = [other class];
@@ -3076,21 +2370,140 @@
                 format:@"Classes must match %@ != %@", selfClass, otherClass];
   }
 
-  GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(MergeFrom);
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  MergeFromContext context = {other, self, syntax};
-  GPBApplyFunctionsToMessageFields(&funcs, self, &context);
-
-  // We assume someting got done, and become visible.
+  // We assume something will be done and become visible.
   GPBBecomeVisibleToAutocreator(self);
 
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  GPBFileSyntax syntax = descriptor.file.syntax;
+
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    GPBFieldType fieldType = field.fieldType;
+    if (fieldType == GPBFieldTypeSingle) {
+      int32_t hasIndex = GPBFieldHasIndex(field);
+      uint32_t fieldNumber = GPBFieldNumber(field);
+      if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) {
+        // Other doesn't have the field set, on to the next.
+        continue;
+      }
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      switch (fieldDataType) {
+        case GPBDataTypeBool:
+          GPBSetBoolIvarWithFieldInternal(
+              self, field, GPBGetMessageBoolField(other, field), syntax);
+          break;
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+          GPBSetInt32IvarWithFieldInternal(
+              self, field, GPBGetMessageInt32Field(other, field), syntax);
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          GPBSetUInt32IvarWithFieldInternal(
+              self, field, GPBGetMessageUInt32Field(other, field), syntax);
+          break;
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+          GPBSetInt64IvarWithFieldInternal(
+              self, field, GPBGetMessageInt64Field(other, field), syntax);
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          GPBSetUInt64IvarWithFieldInternal(
+              self, field, GPBGetMessageUInt64Field(other, field), syntax);
+          break;
+        case GPBDataTypeFloat:
+          GPBSetFloatIvarWithFieldInternal(
+              self, field, GPBGetMessageFloatField(other, field), syntax);
+          break;
+        case GPBDataTypeDouble:
+          GPBSetDoubleIvarWithFieldInternal(
+              self, field, GPBGetMessageDoubleField(other, field), syntax);
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeString: {
+          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+          GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
+          break;
+        }
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+          if (GPBGetHasIvar(self, hasIndex, fieldNumber)) {
+            GPBMessage *message =
+                GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+            [message mergeFrom:otherVal];
+          } else {
+            GPBMessage *message = [otherVal copy];
+            GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
+                                                      syntax);
+          }
+          break;
+        }
+      } // switch()
+    } else if (fieldType == GPBFieldTypeRepeated) {
+      // In the case of a list, they need to be appended, and there is no
+      // _hasIvar to worry about setting.
+      id otherArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      if (otherArray) {
+        GPBDataType fieldDataType = field->description_->dataType;
+        if (GPBDataTypeIsObject(fieldDataType)) {
+          NSMutableArray *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addObjectsFromArray:otherArray];
+        } else if (fieldDataType == GPBDataTypeEnum) {
+          GPBEnumArray *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addRawValuesFromArray:otherArray];
+        } else {
+          // The array type doesn't matter, that all implment
+          // -addValuesFromArray:.
+          GPBInt32Array *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addValuesFromArray:otherArray];
+        }
+      }
+    } else {  // fieldType = GPBFieldTypeMap
+      // In the case of a map, they need to be merged, and there is no
+      // _hasIvar to worry about setting.
+      id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      if (otherDict) {
+        GPBDataType keyDataType = field.mapKeyDataType;
+        GPBDataType valueDataType = field->description_->dataType;
+        if (GPBDataTypeIsObject(keyDataType) &&
+            GPBDataTypeIsObject(valueDataType)) {
+          NSMutableDictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addEntriesFromDictionary:otherDict];
+        } else if (valueDataType == GPBDataTypeEnum) {
+          // The exact type doesn't matter, just need to know it is a
+          // GPB*EnumDictionary.
+          GPBInt32EnumDictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addRawEntriesFromDictionary:otherDict];
+        } else {
+          // The exact type doesn't matter, they all implement
+          // -addEntriesFromDictionary:.
+          GPBInt32Int32Dictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addEntriesFromDictionary:otherDict];
+        }
+      }
+    }  // if (fieldType)..else if...else
+  }  // for(fields)
+
   // Unknown fields.
   if (!unknownFields_) {
-    [self setUnknownFields:context.other.unknownFields];
+    [self setUnknownFields:other.unknownFields];
   } else {
-    [unknownFields_ mergeUnknownFields:context.other.unknownFields];
+    [unknownFields_ mergeUnknownFields:other.unknownFields];
   }
 
+  // Extensions
+
   if (other->extensionMap_.count == 0) {
     return;
   }
@@ -3099,17 +2512,16 @@
     extensionMap_ =
         CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
   } else {
-    for (GPBExtensionField *thisField in other->extensionMap_) {
-      id otherValue = [other->extensionMap_ objectForKey:thisField];
-      id value = [extensionMap_ objectForKey:thisField];
-      GPBExtensionDescriptor *thisFieldDescriptor = thisField.descriptor;
-      BOOL isMessageExtension = GPBExtensionIsMessage(thisFieldDescriptor);
+    for (GPBExtensionDescriptor *extension in other->extensionMap_) {
+      id otherValue = [other->extensionMap_ objectForKey:extension];
+      id value = [extensionMap_ objectForKey:extension];
+      BOOL isMessageExtension = GPBExtensionIsMessage(extension);
 
-      if ([thisField isRepeated]) {
+      if (extension.repeated) {
         NSMutableArray *list = value;
         if (list == nil) {
           list = [[NSMutableArray alloc] init];
-          [extensionMap_ setObject:list forKey:thisField];
+          [extensionMap_ setObject:list forKey:extension];
           [list release];
         }
         if (isMessageExtension) {
@@ -3127,20 +2539,20 @@
             [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
           } else {
             GPBMessage *copiedValue = [otherValue copy];
-            [extensionMap_ setObject:copiedValue forKey:thisField];
+            [extensionMap_ setObject:copiedValue forKey:extension];
             [copiedValue release];
           }
         } else {
-          [extensionMap_ setObject:otherValue forKey:thisField];
+          [extensionMap_ setObject:otherValue forKey:extension];
         }
       }
 
-      if (isMessageExtension && !thisFieldDescriptor.isRepeated) {
+      if (isMessageExtension && !extension.isRepeated) {
         GPBMessage *autocreatedValue =
-            [[autocreatedExtensionMap_ objectForKey:thisField] retain];
+            [[autocreatedExtensionMap_ objectForKey:extension] retain];
         // Must remove from the map before calling GPBClearMessageAutocreator()
         // so that GPBClearMessageAutocreator() knows its safe to clear.
-        [autocreatedExtensionMap_ removeObjectForKey:thisField];
+        [autocreatedExtensionMap_ removeObjectForKey:extension];
         GPBClearMessageAutocreator(autocreatedValue);
         [autocreatedValue release];
       }
@@ -3148,259 +2560,7 @@
   }
 }
 
-#pragma mark - IsEqual Support
-
-typedef struct IsEqualContext {
-  GPBMessage *other;
-  GPBMessage *self;
-  BOOL outIsEqual;
-} IsEqualContext;
-
-// If both self and other "has" a value then compare.
-//%PDDM-DEFINE IS_EQUAL_FUNC(NAME, TYPE)
-//%static BOOL IsEqual##NAME(GPBFieldDescriptor *field, void *voidContext) {
-//%  IsEqualContext *context = (IsEqualContext *)voidContext;
-//%  int32_t hasIndex = GPBFieldHasIndex(field);
-//%  uint32_t fieldNum = GPBFieldNumber(field);
-//%  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-//%  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-//%  if (selfHas != otherHas) {
-//%    context->outIsEqual = NO;
-//%    return NO;
-//%  }
-//%  if (!selfHas) {
-//%    return YES;
-//%  }
-//%  TYPE selfVal = GPBGet##NAME##IvarWithField(context->self, field);
-//%  TYPE otherVal = GPBGet##NAME##IvarWithField(context->other, field);
-//%  if (selfVal != otherVal) {
-//%    context->outIsEqual = NO;
-//%    return NO;
-//%  }
-//%  return YES;
-//%}
-//%
-//%PDDM-EXPAND IS_EQUAL_FUNC(Bool, BOOL)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualBool(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  BOOL selfVal = GPBGetBoolIvarWithField(context->self, field);
-  BOOL otherVal = GPBGetBoolIvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(Int32, int32_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
-  int32_t otherVal = GPBGetInt32IvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(UInt32, uint32_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualUInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
-  uint32_t otherVal = GPBGetUInt32IvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(Int64, int64_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
-  int64_t otherVal = GPBGetInt64IvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(UInt64, uint64_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualUInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
-  uint64_t otherVal = GPBGetUInt64IvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(Float, float)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualFloat(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  float selfVal = GPBGetFloatIvarWithField(context->self, field);
-  float otherVal = GPBGetFloatIvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND IS_EQUAL_FUNC(Double, double)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IsEqualDouble(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  double selfVal = GPBGetDoubleIvarWithField(context->self, field);
-  double otherVal = GPBGetDoubleIvarWithField(context->other, field);
-  if (selfVal != otherVal) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND-END (7 expansions)
-
-static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) {
-  IsEqualContext *context = (IsEqualContext *)voidContext;
-  if (GPBFieldIsMapOrArray(field)) {
-    // In the case of a list/map, there is no _hasIvar to worry about checking.
-    // NOTE: These are NSArray/GPB*Array/NSDictionary/GPB*Dictionary, but the
-    // type doesn't really matter as the object just has to support
-    // -count/-isEqual:.
-    NSArray *resultMapOrArray =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSArray *otherMapOrArray =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
-    context->outIsEqual =
-        (resultMapOrArray.count == 0 && otherMapOrArray.count == 0) ||
-        [resultMapOrArray isEqual:otherMapOrArray];
-    return context->outIsEqual;
-  }
-  int32_t hasIndex = GPBFieldHasIndex(field);
-  uint32_t fieldNum = GPBFieldNumber(field);
-  BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
-  BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
-  if (selfHas != otherHas) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  if (!selfHas) {
-    return YES;
-  }
-  // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster.
-  NSObject *selfVal =
-      GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-  NSObject *otherVal =
-      GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
-
-  // This covers case where selfVal is set to nil, as well as shortcuts the call
-  // to isEqual: in common cases.
-  if (selfVal == otherVal) {
-    return YES;
-  }
-  if (![selfVal isEqual:otherVal]) {
-    context->outIsEqual = NO;
-    return NO;
-  }
-  return YES;
-}
+#pragma mark - isEqual: & hash Support
 
 - (BOOL)isEqual:(GPBMessage *)other {
   if (other == self) {
@@ -3410,12 +2570,97 @@
       ![self isKindOfClass:[other class]]) {
     return NO;
   }
-  GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(IsEqual);
-  IsEqualContext context = {other, self, YES};
-  GPBApplyFunctionsToMessageFields(&funcs, self, &context);
-  if (!context.outIsEqual) {
-    return NO;
-  }
+
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  uint8_t *selfStorage = (uint8_t *)messageStorage_;
+  uint8_t *otherStorage = (uint8_t *)other->messageStorage_;
+
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (GPBFieldIsMapOrArray(field)) {
+      // In the case of a list or map, there is no _hasIvar to worry about.
+      // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but
+      // the type doesn't really matter as the objects all support -count and
+      // -isEqual:.
+      NSArray *resultMapOrArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      NSArray *otherMapOrArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      // nil and empty are equal
+      if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) {
+        if (![resultMapOrArray isEqual:otherMapOrArray]) {
+          return NO;
+        }
+      }
+    } else {  // Single field
+      int32_t hasIndex = GPBFieldHasIndex(field);
+      uint32_t fieldNum = GPBFieldNumber(field);
+      BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum);
+      BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum);
+      if (selfHas != otherHas) {
+        return NO;  // Differing has values, not equal.
+      }
+      if (!selfHas) {
+        // Same has values, was no, nothing else to check for this field.
+        continue;
+      }
+      // Now compare the values.
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      size_t fieldOffset = field->description_->offset;
+      switch (fieldDataType) {
+        case GPBDataTypeBool: {
+          BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset];
+          BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset];
+          if (*selfValPtr != *otherValPtr) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+        case GPBDataTypeFloat: {
+          _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
+          // These are all 32bit, signed/unsigned doesn't matter for equality.
+          uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset];
+          uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset];
+          if (*selfValPtr != *otherValPtr) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+        case GPBDataTypeDouble: {
+          _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
+          // These are all 64bit, signed/unsigned doesn't matter for equality.
+          uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset];
+          uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset];
+          if (*selfValPtr != *otherValPtr) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeBytes:
+        case GPBDataTypeString:
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          // Type doesn't matter here, they all implement -isEqual:.
+          id *selfValPtr = (id *)&selfStorage[fieldOffset];
+          id *otherValPtr = (id *)&otherStorage[fieldOffset];
+          if (![*selfValPtr isEqual:*otherValPtr]) {
+            return NO;
+          }
+          break;
+        }
+      } // switch()
+    }   // if(mapOrArray)...else
+  }  // for(fields)
 
   // nil and empty are equal
   if (extensionMap_.count != 0 || other->extensionMap_.count != 0) {
@@ -3425,13 +2670,14 @@
   }
 
   // nil and empty are equal
-  GPBUnknownFieldSet *otherUnknowns = other.unknownFields;
+  GPBUnknownFieldSet *otherUnknowns = other->unknownFields_;
   if ([unknownFields_ countOfFields] != 0 ||
       [otherUnknowns countOfFields] != 0) {
     if (![unknownFields_ isEqual:otherUnknowns]) {
       return NO;
     }
   }
+
   return YES;
 }
 
@@ -3449,22 +2695,88 @@
 - (NSUInteger)hash {
   GPBDescriptor *descriptor = [[self class] descriptor];
   const NSUInteger prime = 19;
+  uint8_t *storage = (uint8_t *)messageStorage_;
 
-  // Start with the descriptor and then mix it with the field numbers that
-  // are set.  Hopefully that will give a spread based on classes and what
-  // fields are set.
+  // Start with the descriptor and then mix it with some instance info.
+  // Hopefully that will give a spread based on classes and what fields are set.
   NSUInteger result = (NSUInteger)descriptor;
+
   for (GPBFieldDescriptor *field in descriptor->fields_) {
     if (GPBFieldIsMapOrArray(field)) {
       // Exact type doesn't matter, just check if there are any elements.
       NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-      if (mapOrArray.count) {
+      NSUInteger count = mapOrArray.count;
+      if (count) {
+        // NSArray/NSDictionary use count, use the field number and the count.
         result = prime * result + GPBFieldNumber(field);
+        result = prime * result + count;
       }
     } else if (GPBGetHasIvarField(self, field)) {
-      result = prime * result + GPBFieldNumber(field);
+      // Just using the field number seemed simple/fast, but then a small
+      // message class where all the same fields are always set (to different
+      // things would end up all with the same hash, so pull in some data).
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      size_t fieldOffset = field->description_->offset;
+      switch (fieldDataType) {
+        case GPBDataTypeBool: {
+          BOOL *valPtr = (BOOL *)&storage[fieldOffset];
+          result = prime * result + *valPtr;
+          break;
+        }
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+        case GPBDataTypeFloat: {
+          _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
+          // These are all 32bit, just mix it in.
+          uint32_t *valPtr = (uint32_t *)&storage[fieldOffset];
+          result = prime * result + *valPtr;
+          break;
+        }
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+        case GPBDataTypeDouble: {
+          _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
+          // These are all 64bit, just mix what fits into an NSUInteger in.
+          uint64_t *valPtr = (uint64_t *)&storage[fieldOffset];
+          result = prime * result + (NSUInteger)(*valPtr);
+          break;
+        }
+        case GPBDataTypeBytes:
+        case GPBDataTypeString: {
+          // Type doesn't matter here, they both implement -hash:.
+          id *valPtr = (id *)&storage[fieldOffset];
+          result = prime * result + [*valPtr hash];
+          break;
+        }
+
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset];
+          // Could call -hash on the sub message, but that could recurse pretty
+          // deep; follow the lead of NSArray/NSDictionary and don't really
+          // recurse for hash, instead use the field number and the descriptor
+          // of the sub message.  Yes, this could suck for a bunch of messages
+          // where they all only differ in the sub messages, but if you are
+          // using a message with sub messages for something that needs -hash,
+          // odds are you are also copying them as keys, and that deep copy
+          // will also suck.
+          result = prime * result + GPBFieldNumber(field);
+          result = prime * result + (NSUInteger)[[*valPtr class] descriptor];
+          break;
+        }
+      } // switch()
     }
   }
+
+  // Unknowns and extensions are not included.
+
   return result;
 }
 
@@ -3487,1325 +2799,245 @@
 
 #endif  // DEBUG
 
-#pragma mark - SerializedSize Support
-
-// Serialized size is only calculated once, and then is stored into
-// memoizedSerializedSize.
-
-typedef struct SerializedSizeContext {
-  GPBMessage *self;
-  size_t outSize;
-} SerializedSizeContext;
-
-//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC(NAME, TYPE, REAL_TYPE)
-//%SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, REAL_TYPE, )
-//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)
-//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field,
-//%                                NAME$S  void *voidContext) {
-//%  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-//%  GPBFieldType fieldType = field.fieldType;
-//%  if (fieldType == GPBFieldTypeRepeated) {
-//%    GPB##ARRAY_TYPE##Array *array =
-//%        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%    NSUInteger count = array.count;
-//%    if (count == 0) return YES;
-//%    __block size_t dataSize = 0;
-//%    [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%      #pragma unused(idx, stop)
-//%      dataSize += GPBCompute##NAME##SizeNoTag(value);
-//%    }];
-//%    context->outSize += dataSize;
-//%    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-//%    if (field.isPackable) {
-//%      context->outSize += tagSize;
-//%      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-//%    } else {
-//%      context->outSize += count * tagSize;
-//%    }
-//%  } else if (fieldType == GPBFieldTypeSingle) {
-//%    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-//%    if (selfHas) {
-//%      TYPE selfVal = GPBGet##REAL_TYPE##IvarWithField(context->self, field);
-//%      context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal);
-//%    }
-//%  } else {  // fieldType == GPBFieldTypeMap
-//%    // Type will be GPB*##REAL_TYPE##Dictionary, exact type doesn't matter.
-//%    GPBInt32##REAL_TYPE##Dictionary *map =
-//%        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%    context->outSize += [map computeSerializedSizeAsField:field];
-//%  }
-//%  return YES;
-//%}
-//%
-//%PDDM-DEFINE SERIALIZED_SIZE_OBJECT_FUNC(NAME)
-//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field,
-//%                                NAME$S  void *voidContext) {
-//%  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-//%  GPBFieldType fieldType = field.fieldType;
-//%  if (fieldType == GPBFieldTypeRepeated) {
-//%    NSArray *array =
-//%        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%    for (id value in array) {
-//%      context->outSize += GPBCompute##NAME##SizeNoTag(value);
-//%    }
-//%    size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
-//%                                                 GPBGetFieldType(field));
-//%    context->outSize += array.count * tagSize;
-//%  } else if (fieldType == GPBFieldTypeSingle) {
-//%    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-//%    if (selfHas) {
-//%      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-//%      // again.
-//%      id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%      context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal);
-//%    }
-//%  } else {  // fieldType == GPBFieldTypeMap
-//%    GPBType mapKeyType = field.mapKeyType;
-//%    if (mapKeyType == GPBTypeString) {
-//%      // If key type was string, then the map is an NSDictionary.
-//%      NSDictionary *map =
-//%          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%      context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
-//%    } else {
-//%      // Type will be GPB*##NAME##Dictionary, exact type doesn't matter.
-//%      GPBInt32ObjectDictionary *map =
-//%          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-//%      context->outSize += [map computeSerializedSizeAsField:field];
-//%    }
-//%  }
-//%  return YES;
-//%}
-//%
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Bool, BOOL, Bool)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeBool(GPBFieldDescriptor *field,
-                                      void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBBoolArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeBoolSizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      BOOL selfVal = GPBGetBoolIvarWithField(context->self, field);
-      context->outSize += GPBComputeBoolSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*BoolDictionary, exact type doesn't matter.
-    GPBInt32BoolDictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeInt32(GPBFieldDescriptor *field,
-                                       void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeInt32SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeInt32Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int32Dictionary, exact type doesn't matter.
-    GPBInt32Int32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeSInt32(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeSInt32SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeSInt32Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int32Dictionary, exact type doesn't matter.
-    GPBInt32Int32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeSFixed32(GPBFieldDescriptor *field,
-                                          void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt32Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeSFixed32SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeSFixed32Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int32Dictionary, exact type doesn't matter.
-    GPBInt32Int32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC_FULL(Enum, int32_t, Int32, Enum, Raw)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeEnum(GPBFieldDescriptor *field,
-                                      void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBEnumArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeEnumSizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeEnumSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int32Dictionary, exact type doesn't matter.
-    GPBInt32Int32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt32, uint32_t, UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeUInt32(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt32Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeUInt32SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeUInt32Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*UInt32Dictionary, exact type doesn't matter.
-    GPBInt32UInt32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed32, uint32_t, UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeFixed32(GPBFieldDescriptor *field,
-                                         void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt32Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeFixed32SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
-      context->outSize += GPBComputeFixed32Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*UInt32Dictionary, exact type doesn't matter.
-    GPBInt32UInt32Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeInt64(GPBFieldDescriptor *field,
-                                       void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeInt64SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
-      context->outSize += GPBComputeInt64Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int64Dictionary, exact type doesn't matter.
-    GPBInt32Int64Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeSFixed64(GPBFieldDescriptor *field,
-                                          void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeSFixed64SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
-      context->outSize += GPBComputeSFixed64Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int64Dictionary, exact type doesn't matter.
-    GPBInt32Int64Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeSInt64(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBInt64Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeSInt64SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
-      context->outSize += GPBComputeSInt64Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*Int64Dictionary, exact type doesn't matter.
-    GPBInt32Int64Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt64, uint64_t, UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeUInt64(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt64Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeUInt64SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
-      context->outSize += GPBComputeUInt64Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*UInt64Dictionary, exact type doesn't matter.
-    GPBInt32UInt64Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed64, uint64_t, UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeFixed64(GPBFieldDescriptor *field,
-                                         void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBUInt64Array *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeFixed64SizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
-      context->outSize += GPBComputeFixed64Size(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*UInt64Dictionary, exact type doesn't matter.
-    GPBInt32UInt64Dictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Float, float, Float)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeFloat(GPBFieldDescriptor *field,
-                                       void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBFloatArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeFloatSizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      float selfVal = GPBGetFloatIvarWithField(context->self, field);
-      context->outSize += GPBComputeFloatSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*FloatDictionary, exact type doesn't matter.
-    GPBInt32FloatDictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Double, double, Double)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeDouble(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    GPBDoubleArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    NSUInteger count = array.count;
-    if (count == 0) return YES;
-    __block size_t dataSize = 0;
-    [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
-      #pragma unused(idx, stop)
-      dataSize += GPBComputeDoubleSizeNoTag(value);
-    }];
-    context->outSize += dataSize;
-    size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
-    if (field.isPackable) {
-      context->outSize += tagSize;
-      context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
-    } else {
-      context->outSize += count * tagSize;
-    }
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      double selfVal = GPBGetDoubleIvarWithField(context->self, field);
-      context->outSize += GPBComputeDoubleSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    // Type will be GPB*DoubleDictionary, exact type doesn't matter.
-    GPBInt32DoubleDictionary *map =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    context->outSize += [map computeSerializedSizeAsField:field];
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(String)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeString(GPBFieldDescriptor *field,
-                                        void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    NSArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    for (id value in array) {
-      context->outSize += GPBComputeStringSizeNoTag(value);
-    }
-    size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
-                                                 GPBGetFieldType(field));
-    context->outSize += array.count * tagSize;
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBComputeStringSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    GPBType mapKeyType = field.mapKeyType;
-    if (mapKeyType == GPBTypeString) {
-      // If key type was string, then the map is an NSDictionary.
-      NSDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
-    } else {
-      // Type will be GPB*StringDictionary, exact type doesn't matter.
-      GPBInt32ObjectDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += [map computeSerializedSizeAsField:field];
-    }
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Data)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeData(GPBFieldDescriptor *field,
-                                      void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    NSArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    for (id value in array) {
-      context->outSize += GPBComputeDataSizeNoTag(value);
-    }
-    size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
-                                                 GPBGetFieldType(field));
-    context->outSize += array.count * tagSize;
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBComputeDataSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    GPBType mapKeyType = field.mapKeyType;
-    if (mapKeyType == GPBTypeString) {
-      // If key type was string, then the map is an NSDictionary.
-      NSDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
-    } else {
-      // Type will be GPB*DataDictionary, exact type doesn't matter.
-      GPBInt32ObjectDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += [map computeSerializedSizeAsField:field];
-    }
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Message)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeMessage(GPBFieldDescriptor *field,
-                                         void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    NSArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    for (id value in array) {
-      context->outSize += GPBComputeMessageSizeNoTag(value);
-    }
-    size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
-                                                 GPBGetFieldType(field));
-    context->outSize += array.count * tagSize;
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBComputeMessageSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    GPBType mapKeyType = field.mapKeyType;
-    if (mapKeyType == GPBTypeString) {
-      // If key type was string, then the map is an NSDictionary.
-      NSDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
-    } else {
-      // Type will be GPB*MessageDictionary, exact type doesn't matter.
-      GPBInt32ObjectDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += [map computeSerializedSizeAsField:field];
-    }
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Group)
-// This block of code is generated, do not edit it directly.
-
-static BOOL DynamicSerializedSizeGroup(GPBFieldDescriptor *field,
-                                       void *voidContext) {
-  SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
-  GPBFieldType fieldType = field.fieldType;
-  if (fieldType == GPBFieldTypeRepeated) {
-    NSArray *array =
-        GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-    for (id value in array) {
-      context->outSize += GPBComputeGroupSizeNoTag(value);
-    }
-    size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
-                                                 GPBGetFieldType(field));
-    context->outSize += array.count * tagSize;
-  } else if (fieldType == GPBFieldTypeSingle) {
-    BOOL selfHas = GPBGetHasIvarField(context->self, field);
-    if (selfHas) {
-      // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
-      // again.
-      id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBComputeGroupSize(GPBFieldNumber(field), selfVal);
-    }
-  } else {  // fieldType == GPBFieldTypeMap
-    GPBType mapKeyType = field.mapKeyType;
-    if (mapKeyType == GPBTypeString) {
-      // If key type was string, then the map is an NSDictionary.
-      NSDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
-    } else {
-      // Type will be GPB*GroupDictionary, exact type doesn't matter.
-      GPBInt32ObjectDictionary *map =
-          GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
-      context->outSize += [map computeSerializedSizeAsField:field];
-    }
-  }
-  return YES;
-}
-
-//%PDDM-EXPAND-END (18 expansions)
+#pragma mark - SerializedSize
 
 - (size_t)serializedSize {
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  size_t result = 0;
+
+  // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate()
+  // avoids doing the has check again.
+
   // Fields.
-  SerializedSizeContext context = {self, 0};
-  GPBApplyStrictFunctions funcs =
-      GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicSerializedSize);
-  GPBApplyStrictFunctionsToMessageFields(&funcs, self, &context);
+  for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
+    GPBFieldType fieldType = fieldDescriptor.fieldType;
+    GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor);
+
+    // Single Fields
+    if (fieldType == GPBFieldTypeSingle) {
+      BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor);
+      if (!selfHas) {
+        continue;  // Nothing to do.
+      }
+
+      uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor);
+
+      switch (fieldDataType) {
+#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                                \
+        case GPBDataType##NAME: {                                             \
+          TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \
+          result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
+          break;                                                              \
+        }
+#define CASE_SINGLE_OBJECT(NAME)                                              \
+        case GPBDataType##NAME: {                                             \
+          id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \
+          result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
+          break;                                                              \
+        }
+          CASE_SINGLE_POD(Bool, BOOL, Bool)
+          CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
+          CASE_SINGLE_POD(SFixed32, int32_t, Int32)
+          CASE_SINGLE_POD(Float, float, Float)
+          CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
+          CASE_SINGLE_POD(SFixed64, int64_t, Int64)
+          CASE_SINGLE_POD(Double, double, Double)
+          CASE_SINGLE_POD(Int32, int32_t, Int32)
+          CASE_SINGLE_POD(Int64, int64_t, Int64)
+          CASE_SINGLE_POD(SInt32, int32_t, Int32)
+          CASE_SINGLE_POD(SInt64, int64_t, Int64)
+          CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
+          CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
+          CASE_SINGLE_OBJECT(Bytes)
+          CASE_SINGLE_OBJECT(String)
+          CASE_SINGLE_OBJECT(Message)
+          CASE_SINGLE_OBJECT(Group)
+          CASE_SINGLE_POD(Enum, int32_t, Int32)
+#undef CASE_SINGLE_POD
+#undef CASE_SINGLE_OBJECT
+      }
+
+    // Repeated Fields
+    } else if (fieldType == GPBFieldTypeRepeated) {
+      id genericArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+      NSUInteger count = [genericArray count];
+      if (count == 0) {
+        continue;  // Nothing to add.
+      }
+      __block size_t dataSize = 0;
+
+      switch (fieldDataType) {
+#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE)                             \
+    CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, )
+#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)  \
+        case GPBDataType##NAME: {                                             \
+          GPB##ARRAY_TYPE##Array *array = genericArray;                       \
+          [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \
+            _Pragma("unused(idx, stop)");                                     \
+            dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
+          }];                                                                 \
+          break;                                                              \
+        }
+#define CASE_REPEATED_OBJECT(NAME)                                            \
+        case GPBDataType##NAME: {                                             \
+          for (id value in genericArray) {                                    \
+            dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
+          }                                                                   \
+          break;                                                              \
+        }
+          CASE_REPEATED_POD(Bool, BOOL, Bool)
+          CASE_REPEATED_POD(Fixed32, uint32_t, UInt32)
+          CASE_REPEATED_POD(SFixed32, int32_t, Int32)
+          CASE_REPEATED_POD(Float, float, Float)
+          CASE_REPEATED_POD(Fixed64, uint64_t, UInt64)
+          CASE_REPEATED_POD(SFixed64, int64_t, Int64)
+          CASE_REPEATED_POD(Double, double, Double)
+          CASE_REPEATED_POD(Int32, int32_t, Int32)
+          CASE_REPEATED_POD(Int64, int64_t, Int64)
+          CASE_REPEATED_POD(SInt32, int32_t, Int32)
+          CASE_REPEATED_POD(SInt64, int64_t, Int64)
+          CASE_REPEATED_POD(UInt32, uint32_t, UInt32)
+          CASE_REPEATED_POD(UInt64, uint64_t, UInt64)
+          CASE_REPEATED_OBJECT(Bytes)
+          CASE_REPEATED_OBJECT(String)
+          CASE_REPEATED_OBJECT(Message)
+          CASE_REPEATED_OBJECT(Group)
+          CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw)
+#undef CASE_REPEATED_POD
+#undef CASE_REPEATED_POD_EXTRA
+#undef CASE_REPEATED_OBJECT
+      }  // switch
+      result += dataSize;
+      size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor));
+      if (fieldDataType == GPBDataTypeGroup) {
+        // Groups have both a start and an end tag.
+        tagSize *= 2;
+      }
+      if (fieldDescriptor.isPackable) {
+        result += tagSize;
+        result += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+      } else {
+        result += count * tagSize;
+      }
+
+    // Map<> Fields
+    } else {  // fieldType == GPBFieldTypeMap
+      if (GPBDataTypeIsObject(fieldDataType) &&
+          (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) {
+        // If key type was string, then the map is an NSDictionary.
+        NSDictionary *map =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+        if (map) {
+          result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor);
+        }
+      } else {
+        // Type will be GPB*GroupDictionary, exact type doesn't matter.
+        GPBInt32Int32Dictionary *map =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+        result += [map computeSerializedSizeAsField:fieldDescriptor];
+      }
+    }
+  }  // for(fields)
+
   // Add any unknown fields.
-  const GPBDescriptor *descriptor = [self descriptor];
   if (descriptor.wireFormat) {
-    context.outSize += [unknownFields_ serializedSizeAsMessageSet];
+    result += [unknownFields_ serializedSizeAsMessageSet];
   } else {
-    context.outSize += [unknownFields_ serializedSize];
-  }
-  // Add any extensions.
-  for (GPBExtensionField *extension in extensionMap_) {
-    id value = [extensionMap_ objectForKey:extension];
-    context.outSize += [extension computeSerializedSizeIncludingTag:value];
+    result += [unknownFields_ serializedSize];
   }
 
-  return context.outSize;
+  // Add any extensions.
+  for (GPBExtensionDescriptor *extension in extensionMap_) {
+    id value = [extensionMap_ objectForKey:extension];
+    result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value);
+  }
+
+  return result;
 }
 
 #pragma mark - Resolve Methods Support
 
-typedef struct IvarAccessorMethodContext {
-  GPBFileSyntax syntax;
+typedef struct ResolveIvarAccessorMethodResult {
   IMP impToAdd;
   SEL encodingSelector;
-} IvarAccessorMethodContext;
+} ResolveIvarAccessorMethodResult;
 
-//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME)
-//%static BOOL IvarGet##NAME(GPBFieldDescriptor *field, void *voidContext) {
-//%  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-//%  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-//%    return GPBGet##TRUE_NAME##IvarWithField(obj, field);
-//%  });
-//%  context->encodingSelector = @selector(get##NAME);
-//%  return NO;
-//%}
-//%
-//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_OBJECT(NAME, TYPE)
-//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, Object)
-//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) {
-//%  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-//%  // Local for syntax so the block doesn't capture context and use random
-//%  // memory in the future.
-//%  const GPBFileSyntax syntax = context->syntax;
-//%  context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {
-//%    return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
-//%  });
-//%  context->encodingSelector = @selector(set##NAME:);
-//%  return NO;
-//%}
-//%
-//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION(NAME, TYPE)
-//%IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, NAME)
-//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, TRUE_NAME)
-//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME)
-//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) {
-//%  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-//%  // Local for syntax so the block doesn't capture context and use random
-//%  // memory in the future.
-//%  const GPBFileSyntax syntax = context->syntax;
-//%  context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {
-//%    return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax);
-//%  });
-//%  context->encodingSelector = @selector(set##NAME:);
-//%  return NO;
-//%}
-//%
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Bool, BOOL)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetBool(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetBoolIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getBool);
-  return NO;
+static void ResolveIvarGet(GPBFieldDescriptor *field,
+                           ResolveIvarAccessorMethodResult *result) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_GET(NAME, TYPE, TRUE_NAME)                          \
+    case GPBDataType##NAME: {                                    \
+      result->impToAdd = imp_implementationWithBlock(^(id obj) { \
+        return GPBGetMessage##TRUE_NAME##Field(obj, field);      \
+       });                                                       \
+      result->encodingSelector = @selector(get##NAME);           \
+      break;                                                     \
+    }
+#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME)                   \
+    case GPBDataType##NAME: {                                    \
+      result->impToAdd = imp_implementationWithBlock(^(id obj) { \
+        return GPBGetObjectIvarWithField(obj, field);            \
+       });                                                       \
+      result->encodingSelector = @selector(get##NAME);           \
+      break;                                                     \
+    }
+      CASE_GET(Bool, BOOL, Bool)
+      CASE_GET(Fixed32, uint32_t, UInt32)
+      CASE_GET(SFixed32, int32_t, Int32)
+      CASE_GET(Float, float, Float)
+      CASE_GET(Fixed64, uint64_t, UInt64)
+      CASE_GET(SFixed64, int64_t, Int64)
+      CASE_GET(Double, double, Double)
+      CASE_GET(Int32, int32_t, Int32)
+      CASE_GET(Int64, int64_t, Int64)
+      CASE_GET(SInt32, int32_t, Int32)
+      CASE_GET(SInt64, int64_t, Int64)
+      CASE_GET(UInt32, uint32_t, UInt32)
+      CASE_GET(UInt64, uint64_t, UInt64)
+      CASE_GET_OBJECT(Bytes, id, Object)
+      CASE_GET_OBJECT(String, id, Object)
+      CASE_GET_OBJECT(Message, id, Object)
+      CASE_GET_OBJECT(Group, id, Object)
+      CASE_GET(Enum, int32_t, Enum)
+#undef CASE_GET
+  }
 }
 
-static BOOL IvarSetBool(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
-    return GPBSetBoolIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setBool:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int32, int32_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt32IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getInt32);
-  return NO;
-}
-
-static BOOL IvarSetInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
-    return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setInt32:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetSInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt32IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getSInt32);
-  return NO;
-}
-
-static BOOL IvarSetSInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
-    return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setSInt32:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed32, int32_t, Int32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetSFixed32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt32IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getSFixed32);
-  return NO;
-}
-
-static BOOL IvarSetSFixed32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
-    return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setSFixed32:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt32, uint32_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetUInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetUInt32IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getUInt32);
-  return NO;
-}
-
-static BOOL IvarSetUInt32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) {
-    return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setUInt32:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed32, uint32_t, UInt32)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetFixed32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetUInt32IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getFixed32);
-  return NO;
-}
-
-static BOOL IvarSetFixed32(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) {
-    return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setFixed32:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int64, int64_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt64IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getInt64);
-  return NO;
-}
-
-static BOOL IvarSetInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
-    return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setInt64:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetSFixed64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt64IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getSFixed64);
-  return NO;
-}
-
-static BOOL IvarSetSFixed64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
-    return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setSFixed64:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt64, int64_t, Int64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetSInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetInt64IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getSInt64);
-  return NO;
-}
-
-static BOOL IvarSetSInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
-    return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setSInt64:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt64, uint64_t)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetUInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetUInt64IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getUInt64);
-  return NO;
-}
-
-static BOOL IvarSetUInt64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) {
-    return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setUInt64:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed64, uint64_t, UInt64)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetFixed64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetUInt64IvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getFixed64);
-  return NO;
-}
-
-static BOOL IvarSetFixed64(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) {
-    return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setFixed64:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Float, float)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetFloat(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetFloatIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getFloat);
-  return NO;
-}
-
-static BOOL IvarSetFloat(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, float value) {
-    return GPBSetFloatIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setFloat:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Double, double)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetDouble(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetDoubleIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getDouble);
-  return NO;
-}
-
-static BOOL IvarSetDouble(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, double value) {
-    return GPBSetDoubleIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setDouble:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(String, id)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetString(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetObjectIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getString);
-  return NO;
-}
-
-static BOOL IvarSetString(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
-    return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setString:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Data, id)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetData(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetObjectIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getData);
-  return NO;
-}
-
-static BOOL IvarSetData(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
-    return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setData:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Message, id)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetMessage(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetObjectIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getMessage);
-  return NO;
-}
-
-static BOOL IvarSetMessage(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
-    return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setMessage:);
-  return NO;
-}
-
-//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Group, id)
-// This block of code is generated, do not edit it directly.
-
-static BOOL IvarGetGroup(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetObjectIvarWithField(obj, field);
-  });
-  context->encodingSelector = @selector(getGroup);
-  return NO;
-}
-
-static BOOL IvarSetGroup(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
-    return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setGroup:);
-  return NO;
-}
-
-//%PDDM-EXPAND-END (17 expansions)
-
-// Enum gets custom hooks because get needs the syntax to Get.
-
-static BOOL IvarGetEnum(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj) {
-    return GPBGetEnumIvarWithFieldInternal(obj, field, syntax);
-  });
-  context->encodingSelector = @selector(getEnum);
-  return NO;
-}
-
-static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) {
-  IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
-  // Local for syntax so the block doesn't capture context and use random
-  // memory in the future.
-  const GPBFileSyntax syntax = context->syntax;
-  context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
-    return GPBSetEnumIvarWithFieldInternal(obj, field, value, syntax);
-  });
-  context->encodingSelector = @selector(setEnum:);
-  return NO;
+static void ResolveIvarSet(GPBFieldDescriptor *field,
+                           GPBFileSyntax syntax,
+                           ResolveIvarAccessorMethodResult *result) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_SET(NAME, TYPE, TRUE_NAME)                                       \
+    case GPBDataType##NAME: {                                                 \
+      result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {  \
+        return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
+      });                                                                     \
+      result->encodingSelector = @selector(set##NAME:);                       \
+      break;                                                                  \
+    }
+      CASE_SET(Bool, BOOL, Bool)
+      CASE_SET(Fixed32, uint32_t, UInt32)
+      CASE_SET(SFixed32, int32_t, Int32)
+      CASE_SET(Float, float, Float)
+      CASE_SET(Fixed64, uint64_t, UInt64)
+      CASE_SET(SFixed64, int64_t, Int64)
+      CASE_SET(Double, double, Double)
+      CASE_SET(Int32, int32_t, Int32)
+      CASE_SET(Int64, int64_t, Int64)
+      CASE_SET(SInt32, int32_t, Int32)
+      CASE_SET(SInt64, int64_t, Int64)
+      CASE_SET(UInt32, uint32_t, UInt32)
+      CASE_SET(UInt64, uint64_t, UInt64)
+      CASE_SET(Bytes, id, Object)
+      CASE_SET(String, id, Object)
+      CASE_SET(Message, id, Object)
+      CASE_SET(Group, id, Object)
+      CASE_SET(Enum, int32_t, Enum)
+#undef CASE_SET
+  }
 }
 
 + (BOOL)resolveInstanceMethod:(SEL)sel {
@@ -4814,29 +3046,31 @@
     return NO;
   }
 
-  // NOTE: hasSel_/setHasSel_ will be NULL if the field for the given message
-  // should not have has support (done in GPBDescriptor.m), so there is no need
-  // for checks here to see if has*/setHas* are allowed.
+  // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given
+  // message should not have has support (done in GPBDescriptor.m), so there is
+  // no need for checks here to see if has*/setHas* are allowed.
 
-  IvarAccessorMethodContext context = {descriptor.file.syntax, NULL, NULL};
+  ResolveIvarAccessorMethodResult result = {NULL, NULL};
   for (GPBFieldDescriptor *field in descriptor->fields_) {
     BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
     if (!isMapOrArray) {
+      // Single fields.
       if (sel == field->getSel_) {
-        static const GPBApplyStrictFunctions funcs =
-            GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarGet);
-        funcs[GPBGetFieldType(field)](field, &context);
+        ResolveIvarGet(field, &result);
         break;
-      } else if (sel == field->hasSel_) {
+      } else if (sel == field->setSel_) {
+        ResolveIvarSet(field, descriptor.file.syntax, &result);
+        break;
+      } else if (sel == field->hasOrCountSel_) {
         int32_t index = GPBFieldHasIndex(field);
         uint32_t fieldNum = GPBFieldNumber(field);
-        context.impToAdd = imp_implementationWithBlock(^(id obj) {
+        result.impToAdd = imp_implementationWithBlock(^(id obj) {
           return GPBGetHasIvar(obj, index, fieldNum);
         });
-        context.encodingSelector = @selector(getBool);
+        result.encodingSelector = @selector(getBool);
         break;
       } else if (sel == field->setHasSel_) {
-        context.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
+        result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
           if (value) {
             [NSException raise:NSInvalidArgumentException
                         format:@"%@: %@ can only be set to NO (to clear field).",
@@ -4845,53 +3079,60 @@
           }
           GPBClearMessageField(obj, field);
         });
-        context.encodingSelector = @selector(setBool:);
-        break;
-      } else if (sel == field->setSel_) {
-        GPBApplyStrictFunctions funcs = GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarSet);
-        funcs[GPBGetFieldType(field)](field, &context);
+        result.encodingSelector = @selector(setBool:);
         break;
       } else {
         GPBOneofDescriptor *oneof = field->containingOneof_;
         if (oneof && (sel == oneof->caseSel_)) {
           int32_t index = oneof->oneofDescription_->index;
-          context.impToAdd = imp_implementationWithBlock(^(id obj) {
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
             return GPBGetHasOneof(obj, index);
           });
-          context.encodingSelector = @selector(getEnum);
+          result.encodingSelector = @selector(getEnum);
           break;
         }
       }
     } else {
+      // map<>/repeated fields.
       if (sel == field->getSel_) {
         if (field.fieldType == GPBFieldTypeRepeated) {
-          context.impToAdd = imp_implementationWithBlock(^(id obj) {
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
             return GetArrayIvarWithField(obj, field);
           });
         } else {
-          context.impToAdd = imp_implementationWithBlock(^(id obj) {
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
             return GetMapIvarWithField(obj, field);
           });
         }
-        context.encodingSelector = @selector(getArray);
+        result.encodingSelector = @selector(getArray);
         break;
       } else if (sel == field->setSel_) {
-        // Local for syntax so the block doesn't capture context and use random
-        // memory in the future.
-        const GPBFileSyntax syntax = context.syntax;
-        context.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+        // Local for syntax so the block can directly capture it and not the
+        // full lookup.
+        const GPBFileSyntax syntax = descriptor.file.syntax;
+        result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
           return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
         });
-        context.encodingSelector = @selector(setArray:);
+        result.encodingSelector = @selector(setArray:);
+        break;
+      } else if (sel == field->hasOrCountSel_) {
+        result.impToAdd = imp_implementationWithBlock(^(id obj) {
+          // Type doesn't matter, all *Array and *Dictionary types support
+          // -count.
+          NSArray *arrayOrMap =
+              GPBGetObjectIvarWithFieldNoAutocreate(obj, field);
+          return [arrayOrMap count];
+        });
+        result.encodingSelector = @selector(getArrayCount);
         break;
       }
     }
   }
-  if (context.impToAdd) {
+  if (result.impToAdd) {
     const char *encoding =
-        GPBMessageEncodingForSelector(context.encodingSelector, YES);
+        GPBMessageEncodingForSelector(result.encodingSelector, YES);
     BOOL methodAdded = class_addMethod(descriptor.messageClass, sel,
-                                       context.impToAdd, encoding);
+                                       result.impToAdd, encoding);
     return methodAdded;
   }
   return [super resolveInstanceMethod:sel];
diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h
index c437c55..d4c3501 100644
--- a/objectivec/GPBMessage_PackagePrivate.h
+++ b/objectivec/GPBMessage_PackagePrivate.h
@@ -67,9 +67,9 @@
 
 // Gets an extension value without autocreating the result if not found. (i.e.
 // returns nil if the extension is not set)
-- (id)getExistingExtension:(GPBExtensionField *)extension;
+- (id)getExistingExtension:(GPBExtensionDescriptor *)extension;
 
-// Returns an array of GPBExtensionField* for all the extensions currently
+// Returns an array of GPBExtensionDescriptor* for all the extensions currently
 // in use on the message.  They are sorted by field number.
 - (NSArray *)sortedExtensionsInUse;
 
diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h
index 436c983..a66f295 100644
--- a/objectivec/GPBProtocolBuffers.h
+++ b/objectivec/GPBProtocolBuffers.h
@@ -35,11 +35,10 @@
 #import "GPBCodedOutputStream.h"
 #import "GPBDescriptor.h"
 #import "GPBDictionary.h"
-#import "GPBExtensionField.h"
 #import "GPBExtensionRegistry.h"
-#import "GPBField.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
+#import "GPBUnknownField.h"
 #import "GPBUnknownFieldSet.h"
 #import "GPBUtilities.h"
 #import "GPBWireFormat.h"
diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m
index 96eeb1d..e9cbfb4 100644
--- a/objectivec/GPBProtocolBuffers.m
+++ b/objectivec/GPBProtocolBuffers.m
@@ -36,14 +36,27 @@
 #import "GPBCodedOutputStream.m"
 #import "GPBDescriptor.m"
 #import "GPBDictionary.m"
-#import "GPBExtensionField.m"
+#import "GPBExtensionInternals.m"
 #import "GPBExtensionRegistry.m"
-#import "GPBField.m"
 #import "GPBMessage.m"
 #import "GPBRootObject.m"
+#import "GPBUnknownField.m"
 #import "GPBUnknownFieldSet.m"
 #import "GPBUtilities.m"
 #import "GPBWellKnownTypes.m"
 #import "GPBWireFormat.m"
 
 #import "google/protobuf/Descriptor.pbobjc.m"
+
+// Duration and Timestamp are #imported into GPBWellKnownTypes.m to the
+// Objective C categories added will always be linked in with the classes.
+#import "google/protobuf/Any.pbobjc.m"
+#import "google/protobuf/Api.pbobjc.m"
+// #import "google/protobuf/Duration.pbobjc.m"
+#import "google/protobuf/Empty.pbobjc.m"
+#import "google/protobuf/FieldMask.pbobjc.m"
+#import "google/protobuf/SourceContext.pbobjc.m"
+#import "google/protobuf/Struct.pbobjc.m"
+// #import "google/protobuf/Timestamp.pbobjc.m"
+#import "google/protobuf/Type.pbobjc.m"
+#import "google/protobuf/Wrappers.pbobjc.m"
diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
index 7fd7b4c..fea75b9 100644
--- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h
+++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
@@ -34,8 +34,7 @@
 #import "GPBProtocolBuffers.h"
 
 #import "GPBDescriptor_PackagePrivate.h"
-#import "GPBExtensionField_PackagePrivate.h"
-#import "GPBExtensionRegistry.h"
+#import "GPBExtensionInternals.h"
 #import "GPBMessage_PackagePrivate.h"
 #import "GPBRootObject_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m
index 38dab66..3f64825 100644
--- a/objectivec/GPBRootObject.m
+++ b/objectivec/GPBRootObject.m
@@ -36,7 +36,6 @@
 #import <CoreFoundation/CoreFoundation.h>
 
 #import "GPBDescriptor.h"
-#import "GPBExtensionField.h"
 #import "GPBUtilities_PackagePrivate.h"
 
 @interface GPBExtensionDescriptor (GPBRootObject)
@@ -130,14 +129,14 @@
   return nil;
 }
 
-+ (void)globallyRegisterExtension:(GPBExtensionField *)field {
-  const char *key = [field.descriptor singletonNameC];
++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field {
+  const char *key = [field singletonNameC];
   OSSpinLockLock(&gExtensionSingletonDictionaryLock_);
   CFDictionarySetValue(gExtensionSingletonDictionary, key, field);
   OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_);
 }
 
-GPB_INLINE id ExtensionForName(id self, SEL _cmd) {
+static id ExtensionForName(id self, SEL _cmd) {
   // Really fast way of doing "classname_selName".
   // This came up as a hotspot (creation of NSString *) when accessing a
   // lot of extensions.
diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h
index f1cfe99..3c8f09c 100644
--- a/objectivec/GPBRootObject_PackagePrivate.h
+++ b/objectivec/GPBRootObject_PackagePrivate.h
@@ -32,12 +32,12 @@
 
 #import "GPBRootObject.h"
 
-@class GPBExtensionField;
+@class GPBExtensionDescriptor;
 
 @interface GPBRootObject ()
 
 // Globally register.
-+ (void)globallyRegisterExtension:(GPBExtensionField *)field;
++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field;
 
 @end
 
diff --git a/objectivec/GPBTypes.h b/objectivec/GPBRuntimeTypes.h
similarity index 82%
rename from objectivec/GPBTypes.h
rename to objectivec/GPBRuntimeTypes.h
index 49c2b9e..e91d86a 100644
--- a/objectivec/GPBTypes.h
+++ b/objectivec/GPBRuntimeTypes.h
@@ -63,36 +63,36 @@
   GPB_UNSAFE_UNRETAINED NSString *valueString;
   GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage;
   int32_t valueEnum;
-} GPBValue;
+} GPBGenericValue;
 
 // Do not change the order of this enum (or add things to it) without thinking
 // about it very carefully. There are several things that depend on the order.
 typedef enum {
-  GPBTypeBool = 0,
-  GPBTypeFixed32,
-  GPBTypeSFixed32,
-  GPBTypeFloat,
-  GPBTypeFixed64,
-  GPBTypeSFixed64,
-  GPBTypeDouble,
-  GPBTypeInt32,
-  GPBTypeInt64,
-  GPBTypeSInt32,
-  GPBTypeSInt64,
-  GPBTypeUInt32,
-  GPBTypeUInt64,
-  GPBTypeData,  // Maps to Bytes Protobuf type
-  GPBTypeString,
-  GPBTypeMessage,
-  GPBTypeGroup,
-  GPBTypeEnum,
-} GPBType;
+  GPBDataTypeBool = 0,
+  GPBDataTypeFixed32,
+  GPBDataTypeSFixed32,
+  GPBDataTypeFloat,
+  GPBDataTypeFixed64,
+  GPBDataTypeSFixed64,
+  GPBDataTypeDouble,
+  GPBDataTypeInt32,
+  GPBDataTypeInt64,
+  GPBDataTypeSInt32,
+  GPBDataTypeSInt64,
+  GPBDataTypeUInt32,
+  GPBDataTypeUInt64,
+  GPBDataTypeBytes,
+  GPBDataTypeString,
+  GPBDataTypeMessage,
+  GPBDataTypeGroup,
+  GPBDataTypeEnum,
+} GPBDataType;
 
 enum {
-  // A count of the number of types in GPBType. Separated out from the GPBType
-  // enum to avoid warnings regarding not handling GPBTypeCount in switch
-  // statements.
-  GPBTypeCount = GPBTypeEnum + 1
+  // A count of the number of types in GPBDataType. Separated out from the
+  // GPBDataType enum to avoid warnings regarding not handling
+  // GPBDataType_Count in switch statements.
+  GPBDataType_Count = GPBDataTypeEnum + 1
 };
 
 // An extension range.
diff --git a/objectivec/GPBField.h b/objectivec/GPBUnknownField.h
similarity index 93%
rename from objectivec/GPBField.h
rename to objectivec/GPBUnknownField.h
index 041a242..f86d824 100644
--- a/objectivec/GPBField.h
+++ b/objectivec/GPBUnknownField.h
@@ -35,7 +35,7 @@
 @class GPBUInt64Array;
 @class GPBUnknownFieldSet;
 
-@interface GPBField : NSObject<NSCopying>
+@interface GPBUnknownField : NSObject<NSCopying>
 
 @property(nonatomic, readonly, assign) int32_t number;
 
@@ -43,8 +43,8 @@
 @property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
 @property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
 @property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
-@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList;
-@property(nonatomic, readonly, strong) NSArray *groupList;
+@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList;  // NSData
+@property(nonatomic, readonly, strong) NSArray *groupList;  // GPBUnknownFieldSet
 
 // Only one of these should be used per Field.
 - (void)addVarint:(uint64_t)value;
diff --git a/objectivec/GPBField.m b/objectivec/GPBUnknownField.m
similarity index 92%
rename from objectivec/GPBField.m
rename to objectivec/GPBUnknownField.m
index c390ae9..c49c0df 100644
--- a/objectivec/GPBField.m
+++ b/objectivec/GPBUnknownField.m
@@ -28,12 +28,12 @@
 // (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 "GPBField_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
 
 #import "GPBArray.h"
 #import "GPBCodedOutputStream.h"
 
-@interface GPBField () {
+@implementation GPBUnknownField {
  @protected
   int32_t number_;
   GPBUInt64Array *mutableVarintList_;
@@ -42,9 +42,6 @@
   NSMutableArray *mutableLengthDelimitedList_;
   NSMutableArray *mutableGroupList_;
 }
-@end
-
-@implementation GPBField
 
 @synthesize number = number_;
 @synthesize varintList = mutableVarintList_;
@@ -71,7 +68,8 @@
 }
 
 - (id)copyWithZone:(NSZone *)zone {
-  GPBField *result = [[GPBField allocWithZone:zone] initWithNumber:number_];
+  GPBUnknownField *result =
+      [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
   result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
   result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
   result->mutableLengthDelimitedList_ =
@@ -91,8 +89,8 @@
 
 - (BOOL)isEqual:(id)object {
   if (self == object) return YES;
-  if (![object isKindOfClass:[GPBField class]]) return NO;
-  GPBField *field = (GPBField *)object;
+  if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
+  GPBUnknownField *field = (GPBUnknownField *)object;
   BOOL equalVarint =
       (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
       [mutableVarintList_ isEqual:field->mutableVarintList_];
@@ -131,23 +129,23 @@
 - (void)writeToOutput:(GPBCodedOutputStream *)output {
   NSUInteger count = mutableVarintList_.count;
   if (count > 0) {
-    [output writeUInt64s:number_ values:mutableVarintList_ tag:0];
+    [output writeUInt64Array:number_ values:mutableVarintList_ tag:0];
   }
   count = mutableFixed32List_.count;
   if (count > 0) {
-    [output writeFixed32s:number_ values:mutableFixed32List_ tag:0];
+    [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0];
   }
   count = mutableFixed64List_.count;
   if (count > 0) {
-    [output writeFixed64s:number_ values:mutableFixed64List_ tag:0];
+    [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0];
   }
   count = mutableLengthDelimitedList_.count;
   if (count > 0) {
-    [output writeDatas:number_ values:mutableLengthDelimitedList_];
+    [output writeBytesArray:number_ values:mutableLengthDelimitedList_];
   }
   count = mutableGroupList_.count;
   if (count > 0) {
-    [output writeUnknownGroups:number_ values:mutableGroupList_];
+    [output writeUnknownGroupArray:number_ values:mutableGroupList_];
   }
 }
 
@@ -173,7 +171,7 @@
       }];
 
   for (NSData *data in mutableLengthDelimitedList_) {
-    result += GPBComputeDataSize(number, data);
+    result += GPBComputeBytesSize(number, data);
   }
 
   for (GPBUnknownFieldSet *set in mutableGroupList_) {
@@ -229,7 +227,7 @@
   return description;
 }
 
-- (void)mergeFromField:(GPBField *)other {
+- (void)mergeFromField:(GPBUnknownField *)other {
   GPBUInt64Array *otherVarintList = other.varintList;
   if (otherVarintList.count > 0) {
     if (mutableVarintList_ == nil) {
diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h
index 48824f1..ab8ee5e 100644
--- a/objectivec/GPBUnknownFieldSet.h
+++ b/objectivec/GPBUnknownFieldSet.h
@@ -30,15 +30,15 @@
 
 #import <Foundation/Foundation.h>
 
-@class GPBField;
+@class GPBUnknownField;
 
 @interface GPBUnknownFieldSet : NSObject<NSCopying>
 
 - (BOOL)hasField:(int32_t)number;
-- (GPBField *)getField:(int32_t)number;
+- (GPBUnknownField *)getField:(int32_t)number;
 - (NSUInteger)countOfFields;
 
-- (void)addField:(GPBField *)field;
+- (void)addField:(GPBUnknownField *)field;
 
 // Returns an NSArray of the GPBFields sorted by the field numbers.
 - (NSArray *)sortedFields;
diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m
index d7154dc..4ddc0d2 100644
--- a/objectivec/GPBUnknownFieldSet.m
+++ b/objectivec/GPBUnknownFieldSet.m
@@ -32,7 +32,7 @@
 
 #import "GPBCodedInputStream_PackagePrivate.h"
 #import "GPBCodedOutputStream.h"
-#import "GPBField_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUtilities.h"
 #import "GPBWireFormat.h"
 
@@ -85,10 +85,10 @@
 
 static void CopyWorker(const void *key, const void *value, void *context) {
 #pragma unused(key)
-  GPBField *field = value;
+  GPBUnknownField *field = value;
   GPBUnknownFieldSet *result = context;
 
-  GPBField *copied = [field copy];
+  GPBUnknownField *copied = [field copy];
   [result addField:copied];
   [copied release];
 }
@@ -136,9 +136,10 @@
   return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO;
 }
 
-- (GPBField *)getField:(int32_t)number {
+- (GPBUnknownField *)getField:(int32_t)number {
   ssize_t key = number;
-  GPBField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
+  GPBUnknownField *result =
+      fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
   return result;
 }
 
@@ -150,12 +151,12 @@
   if (!fields_) return nil;
   size_t count = CFDictionaryGetCount(fields_);
   ssize_t keys[count];
-  GPBField *values[count];
+  GPBUnknownField *values[count];
   CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
                                (const void **)values);
   struct GPBFieldPair {
     ssize_t key;
-    GPBField *value;
+    GPBUnknownField *value;
   } pairs[count];
   for (size_t i = 0; i < count; ++i) {
     pairs[i].key = keys[i];
@@ -179,13 +180,13 @@
   if (!fields_) return;
   size_t count = CFDictionaryGetCount(fields_);
   ssize_t keys[count];
-  GPBField *values[count];
+  GPBUnknownField *values[count];
   CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
                                (const void **)values);
   if (count > 1) {
     struct GPBFieldPair {
       ssize_t key;
-      GPBField *value;
+      GPBUnknownField *value;
     } pairs[count];
 
     for (size_t i = 0; i < count; ++i) {
@@ -199,7 +200,7 @@
               return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
             });
     for (size_t i = 0; i < count; ++i) {
-      GPBField *value = pairs[i].value;
+      GPBUnknownField *value = pairs[i].value;
       [value writeToOutput:output];
     }
   } else {
@@ -219,7 +220,7 @@
 static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value,
                                              void *context) {
 #pragma unused(key)
-  GPBField *field = value;
+  GPBUnknownField *field = value;
   size_t *result = context;
   *result += [field serializedSize];
 }
@@ -237,7 +238,7 @@
                                                   const void *value,
                                                   void *context) {
 #pragma unused(key)
-  GPBField *field = value;
+  GPBUnknownField *field = value;
   GPBCodedOutputStream *output = context;
   [field writeAsMessageSetExtensionToOutput:output];
 }
@@ -253,7 +254,7 @@
                                                          const void *value,
                                                          void *context) {
 #pragma unused(key)
-  GPBField *field = value;
+  GPBUnknownField *field = value;
   size_t *result = context;
   *result += [field serializedSizeAsMessageSetExtension];
 }
@@ -280,7 +281,7 @@
   return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup;
 }
 
-- (void)addField:(GPBField *)field {
+- (void)addField:(GPBUnknownField *)field {
   int32_t number = [field number];
   checkNumber(number);
   if (!fields_) {
@@ -297,12 +298,12 @@
   CFDictionarySetValue(fields_, (const void *)key, field);
 }
 
-- (GPBField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create {
+- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create {
   ssize_t key = number;
-  GPBField *existing =
+  GPBUnknownField *existing =
       fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil;
   if (!existing && create) {
-    existing = [[GPBField alloc] initWithNumber:number];
+    existing = [[GPBUnknownField alloc] initWithNumber:number];
     // This retains existing.
     [self addField:existing];
     [existing release];
@@ -314,19 +315,19 @@
                                                  const void *value,
                                                  void *context) {
 #pragma unused(key)
-  GPBField *field = value;
+  GPBUnknownField *field = value;
   GPBUnknownFieldSet *self = context;
 
   int32_t number = [field number];
   checkNumber(number);
-  GPBField *oldField = [self mutableFieldForNumber:number create:NO];
+  GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO];
   if (oldField) {
     [oldField mergeFromField:field];
   } else {
     // Merge only comes from GPBMessage's mergeFrom:, so it means we are on
     // mutable message and are an mutable instance, so make sure we need
     // mutable fields.
-    GPBField *fieldCopy = [field copy];
+    GPBUnknownField *fieldCopy = [field copy];
     [self addField:fieldCopy];
     [fieldCopy release];
   }
@@ -356,18 +357,18 @@
   GPBCodedInputStreamState *state = &input->state_;
   switch (GPBWireFormatGetTagWireType(tag)) {
     case GPBWireFormatVarint: {
-      GPBField *field = [self mutableFieldForNumber:number create:YES];
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
       [field addVarint:GPBCodedInputStreamReadInt64(state)];
       return YES;
     }
     case GPBWireFormatFixed64: {
-      GPBField *field = [self mutableFieldForNumber:number create:YES];
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
       [field addFixed64:GPBCodedInputStreamReadFixed64(state)];
       return YES;
     }
     case GPBWireFormatLengthDelimited: {
-      NSData *data = GPBCodedInputStreamReadRetainedData(state);
-      GPBField *field = [self mutableFieldForNumber:number create:YES];
+      NSData *data = GPBCodedInputStreamReadRetainedBytes(state);
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
       [field addLengthDelimited:data];
       [data release];
       return YES;
@@ -375,7 +376,7 @@
     case GPBWireFormatStartGroup: {
       GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init];
       [input readUnknownGroup:number message:unknownFieldSet];
-      GPBField *field = [self mutableFieldForNumber:number create:YES];
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
       [field addGroup:unknownFieldSet];
       [unknownFieldSet release];
       return YES;
@@ -383,7 +384,7 @@
     case GPBWireFormatEndGroup:
       return NO;
     case GPBWireFormatFixed32: {
-      GPBField *field = [self mutableFieldForNumber:number create:YES];
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
       [field addFixed32:GPBCodedInputStreamReadFixed32(state)];
       return YES;
     }
@@ -396,7 +397,7 @@
 }
 
 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
-  GPBField *field = [self mutableFieldForNumber:fieldNum create:YES];
+  GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES];
   [field addLengthDelimited:data];
 }
 
diff --git a/objectivec/GPBField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h
similarity index 94%
rename from objectivec/GPBField_PackagePrivate.h
rename to objectivec/GPBUnknownField_PackagePrivate.h
index 73c1fa8..1fbce0f 100644
--- a/objectivec/GPBField_PackagePrivate.h
+++ b/objectivec/GPBUnknownField_PackagePrivate.h
@@ -30,11 +30,11 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GPBField.h"
+#import "GPBUnknownField.h"
 
 @class GPBCodedOutputStream;
 
-@interface GPBField ()
+@interface GPBUnknownField ()
 
 - (instancetype)initWithNumber:(int32_t)number;
 
@@ -44,6 +44,6 @@
 - (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output;
 - (size_t)serializedSizeAsMessageSetExtension;
 
-- (void)mergeFromField:(GPBField *)other;
+- (void)mergeFromField:(GPBUnknownField *)other;
 
 @end
diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h
index 8813f1a..87cd32c 100644
--- a/objectivec/GPBUtilities.h
+++ b/objectivec/GPBUtilities.h
@@ -30,119 +30,13 @@
 
 #import <Foundation/Foundation.h>
 
+#import "GPBArray.h"
 #import "GPBMessage.h"
-#import "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 
 CF_EXTERN_C_BEGIN
 
-BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber);
-BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
-
-void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
-
-// Returns an empty NSData to assign to byte fields when you wish
-// to assign them to empty. Prevents allocating a lot of little [NSData data]
-// objects.
-NSData *GPBEmptyNSData(void) __attribute__((pure));
-
-//%PDDM-EXPAND GPB_IVAR_ACCESSORS()
-// This block of code is generated, do not edit it directly.
-
-// Getters and Setters for ivars named |name| from instance self.
-
-NSData* GPBGetDataIvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field);
-void GPBSetDataIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field,
-                             NSData* value);
-NSString* GPBGetStringIvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field);
-void GPBSetStringIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               NSString* value);
-GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self,
-                                       GPBFieldDescriptor *field);
-void GPBSetMessageIvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                GPBMessage* value);
-GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self,
-                                     GPBFieldDescriptor *field);
-void GPBSetGroupIvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              GPBMessage* value);
-BOOL GPBGetBoolIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field);
-void GPBSetBoolIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field,
-                             BOOL value);
-int32_t GPBGetInt32IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field);
-void GPBSetInt32IvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              int32_t value);
-int32_t GPBGetSFixed32IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field);
-void GPBSetSFixed32IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field,
-                                 int32_t value);
-int32_t GPBGetSInt32IvarWithField(GPBMessage *self,
-                                  GPBFieldDescriptor *field);
-void GPBSetSInt32IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               int32_t value);
-int32_t GPBGetEnumIvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field);
-void GPBSetEnumIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field,
-                             int32_t value);
-uint32_t GPBGetUInt32IvarWithField(GPBMessage *self,
-                                   GPBFieldDescriptor *field);
-void GPBSetUInt32IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               uint32_t value);
-uint32_t GPBGetFixed32IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field);
-void GPBSetFixed32IvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                uint32_t value);
-int64_t GPBGetInt64IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field);
-void GPBSetInt64IvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              int64_t value);
-int64_t GPBGetSInt64IvarWithField(GPBMessage *self,
-                                  GPBFieldDescriptor *field);
-void GPBSetSInt64IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               int64_t value);
-int64_t GPBGetSFixed64IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field);
-void GPBSetSFixed64IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field,
-                                 int64_t value);
-uint64_t GPBGetUInt64IvarWithField(GPBMessage *self,
-                                   GPBFieldDescriptor *field);
-void GPBSetUInt64IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               uint64_t value);
-uint64_t GPBGetFixed64IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field);
-void GPBSetFixed64IvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                uint64_t value);
-float GPBGetFloatIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field);
-void GPBSetFloatIvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              float value);
-double GPBGetDoubleIvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field);
-void GPBSetDoubleIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               double value);
-//%PDDM-EXPAND-END GPB_IVAR_ACCESSORS()
-
-// Generates a sting that should be a valid "Text Format" for the C++ version
+// Generates a string that should be a valid "Text Format" for the C++ version
 // of Protocol Buffers. lineIndent can be nil if no additional line indent is
 // needed. The comments provide the names according to the ObjC library, they
 // most likely won't exactly match the original .proto file.
@@ -150,32 +44,139 @@
 NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
                                           NSString *lineIndent);
 
+//
+// Test if the given field is set on a message.
+//
+BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber);
+BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
+
+//
+// Clear the given field of a message.
+//
+void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
+
+//%PDDM-EXPAND GPB_ACCESSORS()
+// This block of code is generated, do not edit it directly.
+
+
+//
+// Get/Set the given field of a message.
+//
+
+// Single Fields
+
+NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value);
+
+NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value);
+
+GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
+
+GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
+
+BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value);
+
+int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+
+uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value);
+
+int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value);
+
+uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value);
+
+float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value);
+
+double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value);
+
+// Get/Set the given enum field of a message.  You can only Set values that are
+// members of the enum.  For proto3, when doing a Get, if the value isn't a
+// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The
+// the functions with "Raw" in the will bypass all checks.
+int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+
+// Repeated Fields
+
+// The object will/should be GPB*Array or NSMutableArray based on the field's
+// type.
+id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+
+// Map Fields
+
+// The object will/should be GPB*Dictionary or NSMutableDictionary based on the
+// field's type.
+id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
+void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+
+//%PDDM-EXPAND-END GPB_ACCESSORS()
+
+// Returns an empty NSData to assign to byte fields when you wish
+// to assign them to empty. Prevents allocating a lot of little [NSData data]
+// objects.
+NSData *GPBEmptyNSData(void) __attribute__((pure));
+
 CF_EXTERN_C_END
 
-//%PDDM-DEFINE GPB_IVAR_ACCESSORS()
-//%// Getters and Setters for ivars named |name| from instance self.
+
+//%PDDM-DEFINE GPB_ACCESSORS()
 //%
-//%GPB_IVAR_ACCESSORS_DECL(Data, NSData*)
-//%GPB_IVAR_ACCESSORS_DECL(String, NSString*)
-//%GPB_IVAR_ACCESSORS_DECL(Message, GPBMessage*)
-//%GPB_IVAR_ACCESSORS_DECL(Group, GPBMessage*)
-//%GPB_IVAR_ACCESSORS_DECL(Bool, BOOL)
-//%GPB_IVAR_ACCESSORS_DECL(Int32, int32_t)
-//%GPB_IVAR_ACCESSORS_DECL(SFixed32, int32_t)
-//%GPB_IVAR_ACCESSORS_DECL(SInt32, int32_t)
-//%GPB_IVAR_ACCESSORS_DECL(Enum, int32_t)
-//%GPB_IVAR_ACCESSORS_DECL(UInt32, uint32_t)
-//%GPB_IVAR_ACCESSORS_DECL(Fixed32, uint32_t)
-//%GPB_IVAR_ACCESSORS_DECL(Int64, int64_t)
-//%GPB_IVAR_ACCESSORS_DECL(SInt64, int64_t)
-//%GPB_IVAR_ACCESSORS_DECL(SFixed64, int64_t)
-//%GPB_IVAR_ACCESSORS_DECL(UInt64, uint64_t)
-//%GPB_IVAR_ACCESSORS_DECL(Fixed64, uint64_t)
-//%GPB_IVAR_ACCESSORS_DECL(Float, float)
-//%GPB_IVAR_ACCESSORS_DECL(Double, double)
-//%PDDM-DEFINE GPB_IVAR_ACCESSORS_DECL(NAME, TYPE)
-//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
-//% TYPE$S     NAME$S               GPBFieldDescriptor *field);
-//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
-//%            NAME$S             GPBFieldDescriptor *field,
-//%            NAME$S             TYPE value);
+//%//
+//%// Get/Set the given field of a message.
+//%//
+//%
+//%// Single Fields
+//%
+//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, *)
+//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, *)
+//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, *)
+//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, *)
+//%GPB_ACCESSOR_SINGLE(Bool, BOOL)
+//%GPB_ACCESSOR_SINGLE(Int32, int32_t)
+//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t)
+//%GPB_ACCESSOR_SINGLE(Int64, int64_t)
+//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t)
+//%GPB_ACCESSOR_SINGLE(Float, float)
+//%GPB_ACCESSOR_SINGLE(Double, double)
+//%// Get/Set the given enum field of a message.  You can only Set values that are
+//%// members of the enum.  For proto3, when doing a Get, if the value isn't a
+//%// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The
+//%// the functions with "Raw" in the will bypass all checks.
+//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+//%void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+//%void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+//%
+//%// Repeated Fields
+//%
+//%// The object will/should be GPB*Array or NSMutableArray based on the field's
+//%// type.
+//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
+//%void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+//%
+//%// Map Fields
+//%
+//%// The object will/should be GPB*Dictionary or NSMutableDictionary based on the
+//%// field's type.
+//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
+//%void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+//%
+
+//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE)
+//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, )
+//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, TisP)
+//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field);
+//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value);
+//%
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index f912b97..7a035ce 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -35,9 +35,8 @@
 #import "GPBArray_PackagePrivate.h"
 #import "GPBDescriptor_PackagePrivate.h"
 #import "GPBDictionary_PackagePrivate.h"
-#import "GPBExtensionField.h"
-#import "GPBField.h"
 #import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownField.h"
 #import "GPBUnknownFieldSet.h"
 
 static void AppendTextFormatForMessage(GPBMessage *message,
@@ -53,6 +52,15 @@
   return defaultNSData;
 }
 
+void GPBCheckRuntimeVersionInternal(int32_t version) {
+  if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) {
+    [NSException raise:NSInternalInconsistencyException
+                format:@"Linked to ProtocolBuffer runtime version %d,"
+                       @" but code compiled with version %d!",
+                       GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
+  }
+}
+
 BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
   GPBDescriptor *descriptor = [self descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
@@ -166,8 +174,8 @@
 #pragma mark - IVar accessors
 
 //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
-//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
-//% TYPE$S     NAME$S               GPBFieldDescriptor *field) {
+//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
+//% TYPE$S            NAME$S       GPBFieldDescriptor *field) {
 //%  if (GPBGetHasIvarField(self, field)) {
 //%    uint8_t *storage = (uint8_t *)self->messageStorage_;
 //%    TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
@@ -178,9 +186,9 @@
 //%}
 //%
 //%// Only exists for public api, no core code should use this.
-//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
-//%            NAME$S             GPBFieldDescriptor *field,
-//%            NAME$S             TYPE value) {
+//%void GPBSetMessage##NAME##Field(GPBMessage *self,
+//%                   NAME$S     GPBFieldDescriptor *field,
+//%                   NAME$S     TYPE value) {
 //%  if (self == nil || field == nil) return;
 //%  GPBFileSyntax syntax = [self descriptor].file.syntax;
 //%  GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
@@ -211,18 +219,18 @@
 //%  GPBBecomeVisibleToAutocreator(self);
 //%}
 //%
-//%PDDM-DEFINE IVAR_ALIAS_DEFN(NAME, ALIAS_NAME, TYPE, ALIAS_TYPE)
+//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
 //%// Only exists for public api, no core code should use this.
-//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
-//% TYPE$S     NAME$S               GPBFieldDescriptor *field) {
-//%  return (TYPE)GPBGet##ALIAS_NAME##IvarWithField(self, field);
+//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
+//% TYPE$S             NAME$S       GPBFieldDescriptor *field) {
+//%  return (TYPE *)GPBGetObjectIvarWithField(self, field);
 //%}
 //%
 //%// Only exists for public api, no core code should use this.
-//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
-//%            NAME$S             GPBFieldDescriptor *field,
-//%            NAME$S             TYPE value) {
-//%  GPBSet##ALIAS_NAME##IvarWithField(self, field, (ALIAS_TYPE)value);
+//%void GPBSetMessage##NAME##Field(GPBMessage *self,
+//%                   NAME$S     GPBFieldDescriptor *field,
+//%                   NAME$S     TYPE *value) {
+//%  GPBSetObjectIvarWithField(self, field, (id)value);
 //%}
 //%
 
@@ -252,8 +260,8 @@
 }
 
 // This exists only for briging some aliased types, nothing else should use it.
-GPB_INLINE void GPBSetObjectIvarWithField(GPBMessage *self,
-                                          GPBFieldDescriptor *field, id value) {
+static void GPBSetObjectIvarWithField(GPBMessage *self,
+                                      GPBFieldDescriptor *field, id value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
@@ -276,9 +284,9 @@
 #if defined(__clang_analyzer__)
   if (self->messageStorage_ == NULL) return;
 #endif
-  GPBType fieldType = GPBGetFieldType(field);
+  GPBDataType fieldType = GPBGetFieldDataType(field);
   BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
-  BOOL fieldIsMessage = GPBTypeIsMessage(fieldType);
+  BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
 #ifdef DEBUG
   if (value == nil && !isMapOrArray && !fieldIsMessage &&
       field.hasDefaultValue) {
@@ -294,7 +302,7 @@
     // field, and fall back on the default value. The warning below will only
     // appear in debug, but the could should be changed so the intention is
     // clear.
-    NSString *hasSel = NSStringFromSelector(field->hasSel_);
+    NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_);
     NSString *propName = field.name;
     NSString *className = self.descriptor.name;
     NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
@@ -302,7 +310,7 @@
           @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
           @"'%@'. Defaulting to resetting default value.",
           className, propName, className, propName,
-          (fieldType == GPBTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
+          (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
           className, hasSel, field.defaultValue.valueString);
     // Note: valueString, depending on the type, it could easily be
     // valueData/valueMessage.
@@ -317,9 +325,9 @@
     }
     // Clear "has" if they are being set to nil.
     BOOL setHasValue = (value != nil);
-    // Under proto3, Data & String fields get cleared by resetting them to their
-    // default (empty) values, so if they are set to something of length zero,
-    // they are being cleared.
+    // Under proto3, Bytes & String fields get cleared by resetting them to
+    // their default (empty) values, so if they are set to something of length
+    // zero, they are being cleared.
     if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
         ([value length] == 0)) {
       setHasValue = NO;
@@ -338,7 +346,7 @@
     if (isMapOrArray) {
       if (field.fieldType == GPBFieldTypeRepeated) {
         // If the old array was autocreated by us, then clear it.
-        if (GPBTypeIsObject(fieldType)) {
+        if (GPBDataTypeIsObject(fieldType)) {
           GPBAutocreatedArray *autoArray = oldValue;
           if (autoArray->_autocreator == self) {
             autoArray->_autocreator = nil;
@@ -352,8 +360,8 @@
         }
       } else { // GPBFieldTypeMap
         // If the old map was autocreated by us, then clear it.
-        if ((field.mapKeyType == GPBTypeString) &&
-            GPBTypeIsObject(fieldType)) {
+        if ((field.mapKeyDataType == GPBDataTypeString) &&
+            GPBDataTypeIsObject(fieldType)) {
           GPBAutocreatedDictionary *autoDict = oldValue;
           if (autoDict->_autocreator == self) {
             autoDict->_autocreator = nil;
@@ -399,7 +407,7 @@
   // Not set...
 
   // Non messages (string/data), get their default.
-  if (!GPBFieldTypeIsMessage(field)) {
+  if (!GPBFieldDataTypeIsMessage(field)) {
     return field.defaultValue.valueMessage;
   }
 
@@ -417,7 +425,7 @@
 }
 
 // Only exists for public api, no core code should use this.
-int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
 }
@@ -425,9 +433,9 @@
 int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
                                         GPBFieldDescriptor *field,
                                         GPBFileSyntax syntax) {
-  int32_t result = GPBGetInt32IvarWithField(self, field);
-  // If this is presevering unknown enums, make sure the value is
-  // valid before returning it.
+  int32_t result = GPBGetMessageInt32Field(self, field);
+  // If this is presevering unknown enums, make sure the value is valid before
+  // returning it.
   if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
       ![field isValidEnumValue:result]) {
     result = kGPBUnrecognizedEnumeratorValue;
@@ -436,8 +444,8 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field,
-                             int32_t value) {
+void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
+                            int32_t value) {
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 }
@@ -454,11 +462,25 @@
   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 }
 
+// Only exists for public api, no core code should use this.
+int32_t GPBGetMessageRawEnumField(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
+  int32_t result = GPBGetMessageInt32Field(self, field);
+  return result;
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
+                               int32_t value) {
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Bool, BOOL)
 // This block of code is generated, do not edit it directly.
 
-BOOL GPBGetBoolIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field) {
+BOOL GPBGetMessageBoolField(GPBMessage *self,
+                            GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     BOOL *typePtr = (BOOL *)&storage[field->description_->offset];
@@ -469,9 +491,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetBoolIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field,
-                             BOOL value) {
+void GPBSetMessageBoolField(GPBMessage *self,
+                            GPBFieldDescriptor *field,
+                            BOOL value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
@@ -505,8 +527,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
 // This block of code is generated, do not edit it directly.
 
-int32_t GPBGetInt32IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field) {
+int32_t GPBGetMessageInt32Field(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
@@ -517,9 +539,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetInt32IvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              int32_t value) {
+void GPBSetMessageInt32Field(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             int32_t value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
@@ -553,8 +575,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
 // This block of code is generated, do not edit it directly.
 
-uint32_t GPBGetUInt32IvarWithField(GPBMessage *self,
-                                   GPBFieldDescriptor *field) {
+uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
@@ -565,9 +587,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetUInt32IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               uint32_t value) {
+void GPBSetMessageUInt32Field(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              uint32_t value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
@@ -601,8 +623,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
 // This block of code is generated, do not edit it directly.
 
-int64_t GPBGetInt64IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field) {
+int64_t GPBGetMessageInt64Field(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
@@ -613,9 +635,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetInt64IvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              int64_t value) {
+void GPBSetMessageInt64Field(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             int64_t value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
@@ -649,8 +671,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
 // This block of code is generated, do not edit it directly.
 
-uint64_t GPBGetUInt64IvarWithField(GPBMessage *self,
-                                   GPBFieldDescriptor *field) {
+uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
@@ -661,9 +683,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetUInt64IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               uint64_t value) {
+void GPBSetMessageUInt64Field(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              uint64_t value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
@@ -697,8 +719,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
 // This block of code is generated, do not edit it directly.
 
-float GPBGetFloatIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field) {
+float GPBGetMessageFloatField(GPBMessage *self,
+                              GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     float *typePtr = (float *)&storage[field->description_->offset];
@@ -709,9 +731,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetFloatIvarWithField(GPBMessage *self,
-                              GPBFieldDescriptor *field,
-                              float value) {
+void GPBSetMessageFloatField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             float value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
@@ -745,8 +767,8 @@
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
 // This block of code is generated, do not edit it directly.
 
-double GPBGetDoubleIvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field) {
+double GPBGetMessageDoubleField(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     double *typePtr = (double *)&storage[field->description_->offset];
@@ -757,9 +779,9 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetDoubleIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               double value) {
+void GPBSetMessageDoubleField(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              double value) {
   if (self == nil || field == nil) return;
   GPBFileSyntax syntax = [self descriptor].file.syntax;
   GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
@@ -794,224 +816,226 @@
 
 // Aliases are function calls that are virtually the same.
 
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt32, Int32, int32_t, int32_t)
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString)
 // This block of code is generated, do not edit it directly.
 
 // Only exists for public api, no core code should use this.
-int32_t GPBGetSInt32IvarWithField(GPBMessage *self,
-                                  GPBFieldDescriptor *field) {
-  return (int32_t)GPBGetInt32IvarWithField(self, field);
+NSString *GPBGetMessageStringField(GPBMessage *self,
+                                   GPBFieldDescriptor *field) {
+  return (NSString *)GPBGetObjectIvarWithField(self, field);
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetSInt32IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               int32_t value) {
-  GPBSetInt32IvarWithField(self, field, (int32_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed32, Int32, int32_t, int32_t)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-int32_t GPBGetSFixed32IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field) {
-  return (int32_t)GPBGetInt32IvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetSFixed32IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field,
-                                 int32_t value) {
-  GPBSetInt32IvarWithField(self, field, (int32_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed32, UInt32, uint32_t, uint32_t)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-uint32_t GPBGetFixed32IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field) {
-  return (uint32_t)GPBGetUInt32IvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetFixed32IvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                uint32_t value) {
-  GPBSetUInt32IvarWithField(self, field, (uint32_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt64, Int64, int64_t, int64_t)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-int64_t GPBGetSInt64IvarWithField(GPBMessage *self,
-                                  GPBFieldDescriptor *field) {
-  return (int64_t)GPBGetInt64IvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetSInt64IvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               int64_t value) {
-  GPBSetInt64IvarWithField(self, field, (int64_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed64, Int64, int64_t, int64_t)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-int64_t GPBGetSFixed64IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field) {
-  return (int64_t)GPBGetInt64IvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetSFixed64IvarWithField(GPBMessage *self,
-                                 GPBFieldDescriptor *field,
-                                 int64_t value) {
-  GPBSetInt64IvarWithField(self, field, (int64_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed64, UInt64, uint64_t, uint64_t)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-uint64_t GPBGetFixed64IvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field) {
-  return (uint64_t)GPBGetUInt64IvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetFixed64IvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                uint64_t value) {
-  GPBSetUInt64IvarWithField(self, field, (uint64_t)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(String, Object, NSString*, id)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-NSString* GPBGetStringIvarWithField(GPBMessage *self,
-                                    GPBFieldDescriptor *field) {
-  return (NSString*)GPBGetObjectIvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetStringIvarWithField(GPBMessage *self,
-                               GPBFieldDescriptor *field,
-                               NSString* value) {
-  GPBSetObjectIvarWithField(self, field, (id)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(Data, Object, NSData*, id)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-NSData* GPBGetDataIvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field) {
-  return (NSData*)GPBGetObjectIvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetDataIvarWithField(GPBMessage *self,
-                             GPBFieldDescriptor *field,
-                             NSData* value) {
-  GPBSetObjectIvarWithField(self, field, (id)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(Message, Object, GPBMessage*, id)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self,
-                                       GPBFieldDescriptor *field) {
-  return (GPBMessage*)GPBGetObjectIvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetMessageIvarWithField(GPBMessage *self,
-                                GPBFieldDescriptor *field,
-                                GPBMessage* value) {
-  GPBSetObjectIvarWithField(self, field, (id)value);
-}
-
-//%PDDM-EXPAND IVAR_ALIAS_DEFN(Group, Object, GPBMessage*, id)
-// This block of code is generated, do not edit it directly.
-
-// Only exists for public api, no core code should use this.
-GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self,
-                                     GPBFieldDescriptor *field) {
-  return (GPBMessage*)GPBGetObjectIvarWithField(self, field);
-}
-
-// Only exists for public api, no core code should use this.
-void GPBSetGroupIvarWithField(GPBMessage *self,
+void GPBSetMessageStringField(GPBMessage *self,
                               GPBFieldDescriptor *field,
-                              GPBMessage* value) {
+                              NSString *value) {
   GPBSetObjectIvarWithField(self, field, (id)value);
 }
 
-//%PDDM-EXPAND-END (10 expansions)
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+NSData *GPBGetMessageBytesField(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
+  return (NSData *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageBytesField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             NSData *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
+                                      GPBFieldDescriptor *field) {
+  return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageMessageField(GPBMessage *self,
+                               GPBFieldDescriptor *field,
+                               GPBMessage *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
+                                    GPBFieldDescriptor *field) {
+  return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageGroupField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             GPBMessage *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND-END (4 expansions)
+
+// Only exists for public api, no core code should use this.
+id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeRepeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a repeated field.",
+                       [self class], field.name];
+  }
+#endif
+  return GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeRepeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a repeated field.",
+                       [self class], field.name];
+  }
+  Class expectedClass = Nil;
+  switch (GPBGetFieldDataType(field)) {
+    case GPBDataTypeBool:
+      expectedClass = [GPBBoolArray class];
+      break;
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+      expectedClass = [GPBInt32Array class];
+      break;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      expectedClass = [GPBUInt32Array class];
+      break;
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+      expectedClass = [GPBInt64Array class];
+      break;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      expectedClass = [GPBUInt64Array class];
+      break;
+    case GPBDataTypeFloat:
+      expectedClass = [GPBFloatArray class];
+      break;
+    case GPBDataTypeDouble:
+      expectedClass = [GPBDoubleArray class];
+      break;
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      expectedClass = [NSMutableDictionary class];
+      break;
+    case GPBDataTypeEnum:
+      expectedClass = [GPBBoolArray class];
+      break;
+  }
+  if (array && ![array isKindOfClass:expectedClass]) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@: Expected %@ object, got %@.",
+                       [self class], field.name, expectedClass, [array class]];
+  }
+#endif
+  GPBSetObjectIvarWithField(self, field, array);
+}
+
+#if DEBUG
+static NSString *TypeToStr(GPBDataType dataType) {
+  switch (dataType) {
+    case GPBDataTypeBool:
+      return @"Bool";
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+      return @"Int32";
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      return @"UInt32";
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+      return @"Int64";
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      return @"UInt64";
+    case GPBDataTypeFloat:
+      return @"Float";
+    case GPBDataTypeDouble:
+      return @"Double";
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      return @"Object";
+    case GPBDataTypeEnum:
+      return @"Bool";
+  }
+}
+#endif
+
+// Only exists for public api, no core code should use this.
+id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeMap) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a map<> field.",
+                       [self class], field.name];
+  }
+#endif
+  return GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
+                           id dictionary) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeMap) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a map<> field.",
+                       [self class], field.name];
+  }
+  if (dictionary) {
+    GPBDataType keyDataType = field.mapKeyDataType;
+    GPBDataType valueDataType = GPBGetFieldDataType(field);
+    NSString *keyStr = TypeToStr(keyDataType);
+    NSString *valueStr = TypeToStr(valueDataType);
+    if (keyDataType == GPBDataTypeString) {
+      keyStr = @"String";
+    }
+    Class expectedClass = Nil;
+    if ((keyDataType == GPBDataTypeString) &&
+        GPBDataTypeIsObject(valueDataType)) {
+      expectedClass = [NSMutableDictionary class];
+    } else {
+      NSString *className =
+          [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
+      expectedClass = NSClassFromString(className);
+      NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
+    }
+    if (![dictionary isKindOfClass:expectedClass]) {
+      [NSException raise:NSInvalidArgumentException
+                  format:@"%@.%@: Expected %@ object, got %@.",
+                         [self class], field.name, expectedClass,
+                         [dictionary class]];
+    }
+  }
+#endif
+  GPBSetObjectIvarWithField(self, field, dictionary);
+}
 
 #pragma mark - Misc Dynamic Runtime Utils
 
-void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions,
-                                      GPBMessage *msg, void *context) {
-  GPBDescriptor *descriptor = [[msg class] descriptor];
-  for (GPBFieldDescriptor *field in descriptor->fields_) {
-    BOOL wasGood;
-    if (GPBFieldIsMapOrArray(field)) {
-      wasGood = (*functions)[GPBApplyFunctionObject](field, context);
-    } else {
-      wasGood = GPBApplyFunctionsBasedOnField(field, functions, context);
-    }
-    if (!wasGood) {
-      break;
-    }
-  }
-}
-
-BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field,
-                                   GPBApplyFunctions *functions,
-                                   void *context) {
-  static const GPBApplyFunctionOrder typeMap[GPBTypeCount] = {
-    GPBApplyFunctionBool,
-    GPBApplyFunctionUInt32,
-    GPBApplyFunctionInt32,
-    GPBApplyFunctionFloat,
-    GPBApplyFunctionUInt64,
-    GPBApplyFunctionInt64,
-    GPBApplyFunctionDouble,
-    GPBApplyFunctionInt32,
-    GPBApplyFunctionInt64,
-    GPBApplyFunctionInt32,
-    GPBApplyFunctionInt64,
-    GPBApplyFunctionUInt32,
-    GPBApplyFunctionUInt64,
-    GPBApplyFunctionObject,
-    GPBApplyFunctionObject,
-    GPBApplyFunctionObject,
-    GPBApplyFunctionObject,
-    GPBApplyFunctionInt32
-  };
-  return (*functions)[typeMap[GPBGetFieldType(field)]](field, context);
-}
-
-void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions,
-                                            GPBMessage *msg, void *context) {
-  GPBDescriptor *descriptor = [[msg class] descriptor];
-  for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
-    GPBApplyFunction function = (*functions)[GPBGetFieldType(fieldDescriptor)];
-    BOOL wasGood = function(fieldDescriptor, context);
-    if (!wasGood) {
-      break;
-    }
-  }
-}
-
 const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
   Protocol *protocol =
       objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
@@ -1072,9 +1096,9 @@
 static void AppendTextFormatForMapMessageField(
     id map, GPBFieldDescriptor *field, NSMutableString *toStr,
     NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
-  GPBType keyType = field.mapKeyType;
-  GPBType valueType = GPBGetFieldType(field);
-  BOOL isMessageValue = GPBTypeIsMessage(valueType);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
 
   NSString *msgStartFirst =
       [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
@@ -1088,7 +1112,8 @@
 
   __block BOOL isFirst = YES;
 
-  if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) {
+  if ((keyDataType == GPBDataTypeString) &&
+      GPBDataTypeIsObject(valueDataType)) {
     // map is an NSDictionary.
     NSDictionary *dict = map;
     [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
@@ -1101,16 +1126,16 @@
       [toStr appendString:@"\n"];
 
       [toStr appendString:valueLine];
-      switch (valueType) {
-        case GPBTypeString:
+      switch (valueDataType) {
+        case GPBDataTypeString:
           AppendStringEscaped(value, toStr);
           break;
 
-        case GPBTypeData:
+        case GPBDataTypeBytes:
           AppendBufferAsString(value, toStr);
           break;
 
-        case GPBTypeMessage:
+        case GPBDataTypeMessage:
           [toStr appendString:@"{\n"];
           NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
           AppendTextFormatForMessage(value, toStr, subIndent);
@@ -1133,7 +1158,7 @@
       isFirst = NO;
 
       // Key always is a NSString.
-      if (keyType == GPBTypeString) {
+      if (keyDataType == GPBDataTypeString) {
         [toStr appendString:keyLine];
         AppendStringEscaped(keyObj, toStr);
         [toStr appendString:@"\n"];
@@ -1142,23 +1167,23 @@
       }
 
       [toStr appendString:valueLine];
-      switch (valueType) {
-        case GPBTypeString:
+      switch (valueDataType) {
+        case GPBDataTypeString:
           AppendStringEscaped(valueObj, toStr);
           break;
 
-        case GPBTypeData:
+        case GPBDataTypeBytes:
           AppendBufferAsString(valueObj, toStr);
           break;
 
-        case GPBTypeMessage:
+        case GPBDataTypeMessage:
           [toStr appendString:@"{\n"];
           NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
           AppendTextFormatForMessage(valueObj, toStr, subIndent);
           [toStr appendFormat:@"%@  }", lineIndent];
           break;
 
-        case GPBTypeEnum: {
+        case GPBDataTypeEnum: {
           int32_t enumValue = [valueObj intValue];
           NSString *valueStr = nil;
           GPBEnumDescriptor *descriptor = field.enumDescriptor;
@@ -1174,7 +1199,7 @@
         }
 
         default:
-          NSCAssert(valueType != GPBTypeGroup, @"Can't happen");
+          NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
           // Everything else is a NSString.
           [toStr appendString:valueObj];
           break;
@@ -1245,8 +1270,8 @@
   id array = arrayOrMap;
   const BOOL isRepeated = (array != nil);
 
-  GPBType fieldDataType = GPBGetFieldType(field);
-  BOOL isMessageField = GPBTypeIsMessage(fieldDataType);
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
   for (NSUInteger j = 0; j < count; ++j) {
     // Start the line.
     [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
@@ -1254,12 +1279,12 @@
 
     // The value.
     switch (fieldDataType) {
-#define FIELD_CASE(GPBTYPE, CTYPE, ARRAY_TYPE, ...)                          \
-  case GPBType##GPBTYPE: {                                                   \
-    CTYPE v = (isRepeated ? [(GPB##ARRAY_TYPE##Array *)array valueAtIndex:j] \
-                          : GPBGet##GPBTYPE##IvarWithField(message, field)); \
-    [toStr appendFormat:__VA_ARGS__, v];                                     \
-    break;                                                                   \
+#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...)                        \
+  case GPBDataType##GPBDATATYPE: {                                            \
+    CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j]   \
+                          : GPBGetMessage##REAL_TYPE##Field(message, field)); \
+    [toStr appendFormat:__VA_ARGS__, v];                                      \
+    break;                                                                    \
   }
 
       FIELD_CASE(Int32, int32_t, Int32, @"%d")
@@ -1277,9 +1302,9 @@
 
 #undef FIELD_CASE
 
-      case GPBTypeEnum: {
+      case GPBDataTypeEnum: {
         int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
-                                : GPBGetInt32IvarWithField(message, field));
+                                : GPBGetMessageInt32Field(message, field));
         NSString *valueStr = nil;
         GPBEnumDescriptor *descriptor = field.enumDescriptor;
         if (descriptor) {
@@ -1293,29 +1318,29 @@
         break;
       }
 
-      case GPBTypeBool: {
+      case GPBDataTypeBool: {
         BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
-                             : GPBGetBoolIvarWithField(message, field));
+                             : GPBGetMessageBoolField(message, field));
         [toStr appendString:(v ? @"true" : @"false")];
         break;
       }
 
-      case GPBTypeString: {
+      case GPBDataTypeString: {
         NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
-                                  : GPBGetStringIvarWithField(message, field));
+                                  : GPBGetMessageStringField(message, field));
         AppendStringEscaped(v, toStr);
         break;
       }
 
-      case GPBTypeData: {
+      case GPBDataTypeBytes: {
         NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
-                                : GPBGetDataIvarWithField(message, field));
+                                : GPBGetMessageBytesField(message, field));
         AppendBufferAsString(v, toStr);
         break;
       }
 
-      case GPBTypeGroup:
-      case GPBTypeMessage: {
+      case GPBDataTypeGroup:
+      case GPBDataTypeMessage: {
         GPBMessage *v =
             (isRepeated ? [(NSArray *)array objectAtIndex:j]
                         : GPBGetObjectIvarWithField(message, field));
@@ -1342,7 +1367,7 @@
                                                      NSString *lineIndent) {
   uint32_t start = range.start;
   uint32_t end = range.end;
-  for (GPBExtensionField *extension in activeExtensions) {
+  for (GPBExtensionDescriptor *extension in activeExtensions) {
     uint32_t fieldNumber = extension.fieldNumber;
     if (fieldNumber < start) {
       // Not there yet.
@@ -1354,8 +1379,7 @@
     }
 
     id rawExtValue = [message getExtension:extension];
-    GPBExtensionDescriptor *extDescriptor = [extension descriptor];
-    BOOL isRepeated = extDescriptor.isRepeated;
+    BOOL isRepeated = extension.isRepeated;
 
     NSUInteger numValues = 1;
     NSString *lineEnding = @"";
@@ -1363,28 +1387,28 @@
       numValues = [(NSArray *)rawExtValue count];
     }
 
-    NSString *singletonName = extension.descriptor.singletonName;
+    NSString *singletonName = extension.singletonName;
     if (numValues == 1) {
       lineEnding = [NSString stringWithFormat:@"  # [%@]", singletonName];
     } else {
       [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
     }
 
-    GPBType extType = extDescriptor.type;
+    GPBDataType extDataType = extension.dataType;
     for (NSUInteger j = 0; j < numValues; ++j) {
       id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
 
       // Start the line.
       [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
-                          (GPBTypeIsMessage(extType) ? "" : ":")];
+                          (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
 
       // The value.
-      switch (extType) {
-#define FIELD_CASE(GPBTYPE, CTYPE, NUMSELECTOR, ...) \
-  case GPBType##GPBTYPE: {                           \
-    CTYPE v = [(NSNumber *)curValue NUMSELECTOR];    \
-    [toStr appendFormat:__VA_ARGS__, v];             \
-    break;                                           \
+      switch (extDataType) {
+#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
+  case GPBDataType##GPBDATATYPE: {                       \
+    CTYPE v = [(NSNumber *)curValue NUMSELECTOR];        \
+    [toStr appendFormat:__VA_ARGS__, v];                 \
+    break;                                               \
   }
 
         FIELD_CASE(Int32, int32_t, intValue, @"%d")
@@ -1408,21 +1432,21 @@
 
 #undef FIELD_CASE
 
-        case GPBTypeBool:
+        case GPBDataTypeBool:
           [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
                                                                 : @"false")];
           break;
 
-        case GPBTypeString:
+        case GPBDataTypeString:
           AppendStringEscaped(curValue, toStr);
           break;
 
-        case GPBTypeData:
+        case GPBDataTypeBytes:
           AppendBufferAsString((NSData *)curValue, toStr);
           break;
 
-        case GPBTypeGroup:
-        case GPBTypeMessage: {
+        case GPBDataTypeGroup:
+        case GPBDataTypeMessage: {
           [toStr appendFormat:@"{%@\n", lineEnding];
           NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
           AppendTextFormatForMessage(curValue, toStr, subIndent);
@@ -1431,7 +1455,7 @@
           break;
         }
 
-      }  // switch(extType)
+      }  // switch(extDataType)
 
     }  //  for(numValues)
 
@@ -1487,7 +1511,7 @@
   if (lineIndent == nil) lineIndent = @"";
 
   NSMutableString *result = [NSMutableString string];
-  for (GPBField *field in [unknownSet sortedFields]) {
+  for (GPBUnknownField *field in [unknownSet sortedFields]) {
     int32_t fieldNumber = [field number];
 
 #define PRINT_LOOP(PROPNAME, CTYPE, FORMAT)                                   \
@@ -1527,13 +1551,13 @@
 // Helpers to decode a varint. Not using GPBCodedInputStream version because
 // that needs a state object, and we don't want to create an input stream out
 // of the data.
-static inline int8_t ReadRawByteFromData(const uint8_t **data) {
+GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
   int8_t result = *((int8_t *)(*data));
   ++(*data);
   return result;
 }
 
-static inline int32_t ReadRawVarint32FromData(const uint8_t **data) {
+static int32_t ReadRawVarint32FromData(const uint8_t **data) {
   int8_t tmp = ReadRawByteFromData(data);
   if (tmp >= 0) {
     return tmp;
diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h
index 1481d07..cac551f 100644
--- a/objectivec/GPBUtilities_PackagePrivate.h
+++ b/objectivec/GPBUtilities_PackagePrivate.h
@@ -48,6 +48,15 @@
 
 CF_EXTERN_C_BEGIN
 
+// These two are used to inject a runtime check for version mismatch into the
+// generated sources to make sure they are linked with a supporting runtime.
+void GPBCheckRuntimeVersionInternal(int32_t version);
+GPB_INLINE void GPBDebugCheckRuntimeVersion() {
+#if DEBUG
+  GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION);
+#endif
+}
+
 // Conversion functions for de/serializing floating point types.
 
 GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) {
@@ -116,40 +125,38 @@
   return (n << 1) ^ (n >> 63);
 }
 
-GPB_INLINE BOOL GPBTypeIsObject(GPBType type) {
+GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) {
   switch (type) {
-    case GPBTypeData:
-    case GPBTypeString:
-    case GPBTypeMessage:
-    case GPBTypeGroup:
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
       return YES;
     default:
       return NO;
   }
 }
 
-GPB_INLINE BOOL GPBTypeIsMessage(GPBType type) {
+GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) {
   switch (type) {
-    case GPBTypeMessage:
-    case GPBTypeGroup:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
       return YES;
     default:
       return NO;
   }
 }
 
-GPB_INLINE BOOL GPBTypeIsEnum(GPBType type) { return type == GPBTypeEnum; }
-
-GPB_INLINE BOOL GPBFieldTypeIsMessage(GPBFieldDescriptor *field) {
-  return GPBTypeIsMessage(field->description_->type);
+GPB_INLINE BOOL GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) {
+  return GPBDataTypeIsMessage(field->description_->dataType);
 }
 
-GPB_INLINE BOOL GPBFieldTypeIsObject(GPBFieldDescriptor *field) {
-  return GPBTypeIsObject(field->description_->type);
+GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) {
+  return GPBDataTypeIsObject(field->description_->dataType);
 }
 
 GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) {
-  return GPBTypeIsMessage(ext->description_->type);
+  return GPBDataTypeIsMessage(ext->description_->dataType);
 }
 
 // The field is an array/map or it has an object value.
@@ -158,7 +165,7 @@
   if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) {
     return YES;
   }
-  return GPBTypeIsObject(desc->type);
+  return GPBDataTypeIsObject(desc->dataType);
 }
 
 BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber);
@@ -272,109 +279,6 @@
 void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
                                              GPBFieldDescriptor *field);
 
-// Utilities for applying various functions based on Objective C types.
-
-// A basic functor that is passed a field and a context. Returns YES
-// if the calling function should continue processing, and NO if the calling
-// function should stop processing.
-typedef BOOL (*GPBApplyFunction)(GPBFieldDescriptor *field, void *context);
-
-// Functions called for various types. See ApplyFunctionsToMessageFields.
-typedef enum {
-  GPBApplyFunctionObject,
-  GPBApplyFunctionBool,
-  GPBApplyFunctionInt32,
-  GPBApplyFunctionUInt32,
-  GPBApplyFunctionInt64,
-  GPBApplyFunctionUInt64,
-  GPBApplyFunctionFloat,
-  GPBApplyFunctionDouble,
-} GPBApplyFunctionOrder;
-
-enum {
-  // A count of the number of types in GPBApplyFunctionOrder. Separated out
-  // from the GPBApplyFunctionOrder enum to avoid warnings regarding not
-  // handling GPBApplyFunctionCount in switch statements.
-  GPBApplyFunctionCount = GPBApplyFunctionDouble + 1
-};
-
-typedef GPBApplyFunction GPBApplyFunctions[GPBApplyFunctionCount];
-
-// Functions called for various types.
-// See ApplyStrictFunctionsToMessageFields.
-// They are in the same order as the GPBTypes enum.
-typedef GPBApplyFunction GPBApplyStrictFunctions[GPBTypeCount];
-
-// A macro for easily initializing a GPBApplyFunctions struct
-// GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(Foo);
-#define GPBAPPLY_FUNCTIONS_INIT(PREFIX) \
-  { \
-    PREFIX##Object,  \
-    PREFIX##Bool,    \
-    PREFIX##Int32,   \
-    PREFIX##UInt32,  \
-    PREFIX##Int64,   \
-    PREFIX##UInt64,  \
-    PREFIX##Float,   \
-    PREFIX##Double,  \
-  }
-
-// A macro for easily initializing a GPBApplyStrictFunctions struct
-// GPBApplyStrictFunctions foo = GPBAPPLY_STRICT_FUNCTIONS_INIT(Foo);
-// These need to stay in the same order as
-// the GPBType enum.
-#define GPBAPPLY_STRICT_FUNCTIONS_INIT(PREFIX) \
-  { \
-    PREFIX##Bool,     \
-    PREFIX##Fixed32,  \
-    PREFIX##SFixed32, \
-    PREFIX##Float,    \
-    PREFIX##Fixed64,  \
-    PREFIX##SFixed64, \
-    PREFIX##Double,   \
-    PREFIX##Int32,    \
-    PREFIX##Int64,    \
-    PREFIX##SInt32,   \
-    PREFIX##SInt64,   \
-    PREFIX##UInt32,   \
-    PREFIX##UInt64,   \
-    PREFIX##Data,     \
-    PREFIX##String,   \
-    PREFIX##Message,  \
-    PREFIX##Group,    \
-    PREFIX##Enum,     \
-}
-
-// Iterates over the fields of a proto |msg| and applies the functions in
-// |functions| to them with |context|. If one of the functions in |functions|
-// returns NO, it will return immediately and not process the rest of the
-// ivars. The types in the fields are mapped so:
-// Int32, Enum, SInt32 and SFixed32 will be mapped to the int32Function,
-// UInt32 and Fixed32 will be mapped to the uint32Function,
-// Bytes, String, Message and Group will be mapped to the objectFunction,
-// etc..
-// If you require more specific mappings look at
-// GPBApplyStrictFunctionsToMessageFields.
-void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions,
-                                      GPBMessage *msg, void *context);
-
-// Iterates over the fields of a proto |msg| and applies the functions in
-// |functions| to them with |context|. If one of the functions in |functions|
-// returns NO, it will return immediately and not process the rest of the
-// ivars. The types in the fields are mapped directly:
-// Int32 -> functions[GPBTypeInt32],
-// SFixed32 -> functions[GPBTypeSFixed32],
-// etc...
-// If you can use looser mappings look at GPBApplyFunctionsToMessageFields.
-void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions,
-                                            GPBMessage *msg, void *context);
-
-// Applies the appropriate function in |functions| based on |field|.
-// Returns the value from function(name, context).
-// Throws an exception if the type is unrecognized.
-BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field,
-                                   GPBApplyFunctions *functions, void *context);
-
 // Returns an Objective C encoding for |selector|. |instanceSel| should be
 // YES if it's an instance selector (as opposed to a class selector).
 // |selector| must be a selector from MessageSignatureProtocol.
@@ -410,7 +314,7 @@
 GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64)
 GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32)
 GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64)
-GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Data)
+GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Bytes)
 GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String)
 GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message)
 GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group)
@@ -419,6 +323,7 @@
 #undef GPB_MESSAGE_SIGNATURE_ENTRY
 
 - (id)getArray;
+- (NSUInteger)getArrayCount;
 - (void)setArray:(NSArray *)array;
 + (id)getClassValue;
 @end
diff --git a/objectivec/GPBWireFormat.h b/objectivec/GPBWireFormat.h
index 55f2edf..45089bd 100644
--- a/objectivec/GPBWireFormat.h
+++ b/objectivec/GPBWireFormat.h
@@ -28,7 +28,7 @@
 // (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 "GPBTypes.h"
+#import "GPBRuntimeTypes.h"
 
 CF_EXTERN_C_BEGIN
 
@@ -52,7 +52,7 @@
 GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const));
 uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const));
 
-GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked)
+GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked)
     __attribute__((const));
 
 #define GPBWireFormatMessageSetItemTag \
diff --git a/objectivec/GPBWireFormat.m b/objectivec/GPBWireFormat.m
index 7435221..193235d 100644
--- a/objectivec/GPBWireFormat.m
+++ b/objectivec/GPBWireFormat.m
@@ -49,30 +49,30 @@
   return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits);
 }
 
-GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) {
+GPBWireFormat GPBWireFormatForType(GPBDataType type, BOOL isPacked) {
   if (isPacked) {
     return GPBWireFormatLengthDelimited;
   }
 
-  static const GPBWireFormat format[GPBTypeCount] = {
-      GPBWireFormatVarint,           // GPBTypeBool
-      GPBWireFormatFixed32,          // GPBTypeFixed32
-      GPBWireFormatFixed32,          // GPBTypeSFixed32
-      GPBWireFormatFixed32,          // GPBTypeFloat
-      GPBWireFormatFixed64,          // GPBTypeFixed64
-      GPBWireFormatFixed64,          // GPBTypeSFixed64
-      GPBWireFormatFixed64,          // GPBTypeDouble
-      GPBWireFormatVarint,           // GPBTypeInt32
-      GPBWireFormatVarint,           // GPBTypeInt64
-      GPBWireFormatVarint,           // GPBTypeSInt32
-      GPBWireFormatVarint,           // GPBTypeSInt64
-      GPBWireFormatVarint,           // GPBTypeUInt32
-      GPBWireFormatVarint,           // GPBTypeUInt64
-      GPBWireFormatLengthDelimited,  // GPBTypeBytes
-      GPBWireFormatLengthDelimited,  // GPBTypeString
-      GPBWireFormatLengthDelimited,  // GPBTypeMessage
-      GPBWireFormatStartGroup,       // GPBTypeGroup
-      GPBWireFormatVarint            // GPBTypeEnum
+  static const GPBWireFormat format[GPBDataType_Count] = {
+      GPBWireFormatVarint,           // GPBDataTypeBool
+      GPBWireFormatFixed32,          // GPBDataTypeFixed32
+      GPBWireFormatFixed32,          // GPBDataTypeSFixed32
+      GPBWireFormatFixed32,          // GPBDataTypeFloat
+      GPBWireFormatFixed64,          // GPBDataTypeFixed64
+      GPBWireFormatFixed64,          // GPBDataTypeSFixed64
+      GPBWireFormatFixed64,          // GPBDataTypeDouble
+      GPBWireFormatVarint,           // GPBDataTypeInt32
+      GPBWireFormatVarint,           // GPBDataTypeInt64
+      GPBWireFormatVarint,           // GPBDataTypeSInt32
+      GPBWireFormatVarint,           // GPBDataTypeSInt64
+      GPBWireFormatVarint,           // GPBDataTypeUInt32
+      GPBWireFormatVarint,           // GPBDataTypeUInt64
+      GPBWireFormatLengthDelimited,  // GPBDataTypeBytes
+      GPBWireFormatLengthDelimited,  // GPBDataTypeString
+      GPBWireFormatLengthDelimited,  // GPBDataTypeMessage
+      GPBWireFormatStartGroup,       // GPBDataTypeGroup
+      GPBWireFormatVarint            // GPBDataTypeEnum
   };
   return format[type];
 }
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index f18ba2f..b0a0712 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -6,20 +6,6 @@
 	objectVersion = 47;
 	objects = {
 
-/* Begin PBXAggregateTarget section */
-		8BD3981414BE4AE70081D629 /* Compile_Protos */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */;
-			buildPhases = (
-				8BD3981814BE4AF30081D629 /* ShellScript */,
-			);
-			dependencies = (
-			);
-			name = Compile_Protos;
-			productName = Compile_Protos;
-		};
-/* End PBXAggregateTarget section */
-
 /* Begin PBXBuildFile section */
 		2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
 		5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; };
@@ -27,7 +13,7 @@
 		7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; };
 		7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; };
 		7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; };
-		7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBField.m */; };
+		7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; };
 		7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; };
 		7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; };
 		7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; };
@@ -51,7 +37,6 @@
 		8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; };
 		8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; };
 		8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
-		8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */; };
 		8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
 		8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
 		F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; };
@@ -71,8 +56,24 @@
 		F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */; };
 		F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */; };
 		F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */; };
-		F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionField.m */; };
+		F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; };
 		F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */; };
+		F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; };
+		F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; };
+		F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; };
+		F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; };
+		F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; };
+		F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; };
+		F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; };
+		F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; };
+		F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; };
+		F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; };
+		F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; };
+		F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; };
+		F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; };
+		F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; };
+		F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; };
+		F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -83,12 +84,12 @@
 			remoteGlobalIDString = 7461B52D0F94FAF800A0C422;
 			remoteInfo = ProtocolBuffers;
 		};
-		8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = {
+		F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
 			proxyType = 1;
-			remoteGlobalIDString = 8BD3981414BE4AE70081D629;
-			remoteInfo = Compile_Protos;
+			remoteGlobalIDString = F45BBC141B0CE3C6002D064D;
+			remoteInfo = "Compile Unittest Protos";
 		};
 /* End PBXContainerItemProxy section */
 
@@ -106,8 +107,8 @@
 		7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = "<group>"; };
 		7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = "<group>"; };
 		7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = "<group>"; };
-		7461B4AE0F94F99000A0C422 /* GPBField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBField.h; sourceTree = "<group>"; };
-		7461B4AF0F94F99000A0C422 /* GPBField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBField.m; sourceTree = "<group>"; };
+		7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = "<group>"; };
+		7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.m; sourceTree = "<group>"; };
 		7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = "<group>"; };
 		7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = "<group>"; };
 		7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = "<group>"; };
@@ -126,10 +127,7 @@
 		7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = "<group>"; };
 		7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = "<group>"; };
 		7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = "<group>"; };
-		748F0CAF0FD70602000858A9 /* GPBExtensionField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField.h; sourceTree = "<group>"; };
 		8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = "<group>"; };
-		8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter1.txt; sourceTree = "<group>"; };
-		8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_filter.proto; sourceTree = "<group>"; };
 		8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = "<group>"; };
 		8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = "<group>"; };
 		8B4248B81A8C254000BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_OSX.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -162,12 +160,11 @@
 		8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStringTests.m; sourceTree = "<group>"; };
 		8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
 		8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFilteredMessageTests.m; sourceTree = "<group>"; };
 		8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
 		8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
 		8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
 		8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Descriptor.pbobjc.m; path = google/protobuf/Descriptor.pbobjc.m; sourceTree = SOURCE_ROOT; };
-		8BEB5AE01498033E0078BF9D /* GPBTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBTypes.h; sourceTree = "<group>"; };
+		8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
 		F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = "<group>"; };
 		F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = "<group>"; };
 		F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
@@ -192,16 +189,39 @@
 		F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = "<group>"; };
 		F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
 		F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
-		F44B25D81A729803005CCF68 /* Filter2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter2.txt; sourceTree = "<group>"; };
 		F451D3F51A8AAE8700B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
-		F45C69CB16DFD08D0081955B /* GPBExtensionField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionField.m; sourceTree = "<group>"; };
+		F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = "<group>"; };
 		F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = "<group>"; };
 		F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = "<group>"; };
-		F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = "<group>"; };
+		F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = "<group>"; };
 		F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
-		F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = "<group>"; };
+		F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; };
 		F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
-		F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; };
+		F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; };
+		F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; };
+		F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; };
+		F4E675881B21D0000054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = "<group>"; };
+		F4E675891B21D0000054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = "<group>"; };
+		F4E6758A1B21D0000054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = "<group>"; };
+		F4E6758B1B21D0000054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = "<group>"; };
+		F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = "<group>"; };
+		F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = "<group>"; };
+		F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = "<group>"; };
+		F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = "<group>"; };
+		F4E675901B21D0000054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = "<group>"; };
+		F4E675911B21D0000054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = "<group>"; };
+		F4E675921B21D0000054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = "<group>"; };
+		F4E675931B21D0000054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = "<group>"; };
+		F4E675941B21D0000054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = "<group>"; };
+		F4E675951B21D0000054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = "<group>"; };
+		F4E675A61B21D05C0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = "<group>"; };
+		F4E675A71B21D05C0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = "<group>"; };
+		F4E675A81B21D05C0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = "<group>"; };
+		F4E675A91B21D05C0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = "<group>"; };
+		F4E675AA1B21D05C0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = "<group>"; };
+		F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; };
+		F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; };
+		F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -273,15 +293,39 @@
 		29B97315FDCFA39411CA2CEA /* Generated */ = {
 			isa = PBXGroup;
 			children = (
-				8B42494B1A92A16600BC1EC6 /* descriptor.proto */,
-				8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */,
+				F4E675861B21D0000054530B /* Any.pbobjc.h */,
+				F4E675871B21D0000054530B /* Any.pbobjc.m */,
+				F4E675A61B21D05C0054530B /* any.proto */,
+				F4E675881B21D0000054530B /* Api.pbobjc.h */,
+				F4E675891B21D0000054530B /* Api.pbobjc.m */,
+				F4E675A71B21D05C0054530B /* api.proto */,
 				8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */,
-				8B42494C1A92A16600BC1EC6 /* duration.proto */,
+				8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */,
+				8B42494B1A92A16600BC1EC6 /* descriptor.proto */,
 				8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */,
 				8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */,
-				8B42494D1A92A16600BC1EC6 /* timestamp.proto */,
+				8B42494C1A92A16600BC1EC6 /* duration.proto */,
+				F4E6758A1B21D0000054530B /* Empty.pbobjc.h */,
+				F4E6758B1B21D0000054530B /* Empty.pbobjc.m */,
+				F4E675A81B21D05C0054530B /* empty.proto */,
+				F4E675A91B21D05C0054530B /* field_mask.proto */,
+				F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */,
+				F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */,
+				F4E675AA1B21D05C0054530B /* source_context.proto */,
+				F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */,
+				F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */,
+				F4E675901B21D0000054530B /* Struct.pbobjc.h */,
+				F4E675911B21D0000054530B /* Struct.pbobjc.m */,
+				F4E675AB1B21D05C0054530B /* struct.proto */,
 				8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */,
 				8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */,
+				8B42494D1A92A16600BC1EC6 /* timestamp.proto */,
+				F4E675921B21D0000054530B /* Type.pbobjc.h */,
+				F4E675931B21D0000054530B /* Type.pbobjc.m */,
+				F4E675AC1B21D05C0054530B /* type.proto */,
+				F4E675941B21D0000054530B /* Wrappers.pbobjc.h */,
+				F4E675951B21D0000054530B /* Wrappers.pbobjc.m */,
+				F4E675AD1B21D05C0054530B /* wrappers.proto */,
 			);
 			name = Generated;
 			sourceTree = "<group>";
@@ -297,9 +341,8 @@
 		7461B3C50F94F84100A0C422 /* Extensions */ = {
 			isa = PBXGroup;
 			children = (
-				F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */,
-				748F0CAF0FD70602000858A9 /* GPBExtensionField.h */,
-				F45C69CB16DFD08D0081955B /* GPBExtensionField.m */,
+				F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */,
+				F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */,
 				7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */,
 				7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */,
 				F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */,
@@ -312,9 +355,9 @@
 		7461B4850F94F96600A0C422 /* Fields */ = {
 			isa = PBXGroup;
 			children = (
-				F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */,
-				7461B4AE0F94F99000A0C422 /* GPBField.h */,
-				7461B4AF0F94F99000A0C422 /* GPBField.m */,
+				F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */,
+				7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
+				7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
 				F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
 				7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
 				7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
@@ -353,8 +396,6 @@
 			isa = PBXGroup;
 			children = (
 				8B4248B81A8C254000BC1EC6 /* protobuf */,
-				8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */,
-				F44B25D81A729803005CCF68 /* Filter2.txt */,
 				8B210CCD159383D60032D72D /* golden_message */,
 				8B210CCF159386920032D72D /* golden_packed_fields_message */,
 				8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
@@ -370,7 +411,6 @@
 				F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */,
 				F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */,
 				F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */,
-				8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */,
 				7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
 				F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */,
 				F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */,
@@ -392,13 +432,12 @@
 				8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
 				8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
 				8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
-				8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */,
 				8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
 				8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
 				8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
-				F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */,
 				8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
 				8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
+				F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */,
 				8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
 				F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */,
 				F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */,
@@ -419,7 +458,7 @@
 				F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */,
 				F4353D201ABB1537005A6198 /* GPBDictionary.h */,
 				F4353D211ABB1537005A6198 /* GPBDictionary.m */,
-				8BEB5AE01498033E0078BF9D /* GPBTypes.h */,
+				8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */,
 				F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */,
 				7461B4E50F94F99000A0C422 /* GPBUtilities.h */,
 				7461B4E60F94F99000A0C422 /* GPBUtilities.m */,
@@ -448,6 +487,22 @@
 		};
 /* End PBXHeadersBuildPhase section */
 
+/* Begin PBXLegacyTarget section */
+		F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = "$(ACTION)";
+			buildConfigurationList = F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */;
+			buildPhases = (
+			);
+			buildToolPath = DevTools/compile_testing_protos.sh;
+			dependencies = (
+			);
+			name = "Compile Unittest Protos";
+			passBuildSettingsInEnvironment = 1;
+			productName = "Compile Unittest Protos";
+		};
+/* End PBXLegacyTarget section */
+
 /* Begin PBXNativeTarget section */
 		7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = {
 			isa = PBXNativeTarget;
@@ -479,7 +534,7 @@
 			);
 			dependencies = (
 				8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */,
-				8BD3982114BE59EB0081D629 /* PBXTargetDependency */,
+				F45BBC191B0CE3D7002D064D /* PBXTargetDependency */,
 			);
 			name = UnitTests;
 			productName = UnitTests;
@@ -510,11 +565,14 @@
 			isa = PBXProject;
 			attributes = {
 				LastTestingUpgradeCheck = 0600;
-				LastUpgradeCheck = 0620;
+				LastUpgradeCheck = 0630;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
 						TestTargetID = 8B9A5EA41831993600A9D33B;
 					};
+					F45BBC141B0CE3C6002D064D = {
+						CreatedOnToolsVersion = 6.3.2;
+					};
 				};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */;
@@ -530,8 +588,8 @@
 			targets = (
 				7461B52D0F94FAF800A0C422 /* ProtocolBuffers */,
 				8BBEA4A5147C727100C4ADB7 /* UnitTests */,
-				8BD3981414BE4AE70081D629 /* Compile_Protos */,
 				F4487C381A9F8E0200531423 /* TestSingleSourceBuild */,
+				F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */,
 			);
 		};
 /* End PBXProject section */
@@ -551,51 +609,6 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		8BD3981814BE4AF30081D629 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-				"$(SRCROOT)/../src/google/protobuf/unittest_custom_options.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_embed_optimize_for.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_empty.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_enormous_descriptor.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_lite_imports_nonlite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_mset.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_no_generic_services.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest.proto",
-				"$(SRCROOT)/Tests/unittest_objc.proto",
-				"$(SRCROOT)/../src/.libs/libprotoc.10.dylib",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_public_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_public.proto",
-				"$(SRCROOT)/Tests/unittest_filter.proto",
-				"$(SRCROOT)/../src/.libs/libprotobuf.10.dylib",
-				"$(SRCROOT)/../src/.libs/protoc",
-				"$(SRCROOT)/Tests/Filter1.txt",
-				"$(SRCROOT)/Tests/Filter2.txt",
-				"$(SRCROOT)/Tests/unittest_cycle.proto",
-				"$(SRCROOT)/Tests/unittest_name_mangling.proto",
-				"$(SRCROOT)/Tests/unittest_runtime_proto2.proto",
-				"$(SRCROOT)/Tests/unittest_runtime_proto3.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_drop_unknown_fields.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_preserve_unknown_enum.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_lite_unittest.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_proto2_unittest.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_unittest.proto",
-			);
-			outputPaths = (
-				"$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.h",
-				"$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.m",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/bash;
-			shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n";
-			showEnvVarsInLog = 0;
-		};
 		F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -620,19 +633,27 @@
 			files = (
 				2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */,
 				7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */,
+				F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */,
 				7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
 				F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */,
 				7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */,
-				7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */,
+				F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */,
+				7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */,
 				7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */,
 				7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */,
 				7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */,
 				7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */,
+				F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */,
+				F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */,
 				F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */,
 				8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */,
 				8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */,
-				F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */,
+				F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */,
+				F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */,
 				8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */,
+				F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */,
+				F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */,
+				F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -645,12 +666,18 @@
 				F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */,
 				F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
 				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+				F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */,
 				8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
 				F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */,
 				8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
+				F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */,
+				F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */,
 				F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */,
+				F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */,
+				F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */,
 				8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */,
 				5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
+				F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */,
 				F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */,
 				F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
 				8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
@@ -665,9 +692,10 @@
 				8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
 				8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */,
 				8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
+				F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */,
 				8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */,
-				8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */,
 				8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
+				F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -687,10 +715,10 @@
 			target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */;
 			targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */;
 		};
-		8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = {
+		F45BBC191B0CE3D7002D064D /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
-			target = 8BD3981414BE4AE70081D629 /* Compile_Protos */;
-			targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */;
+			target = F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */;
+			targetProxy = F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */;
 		};
 /* End PBXTargetDependency section */
 
@@ -746,20 +774,6 @@
 			};
 			name = Release;
 		};
-		8BD3981514BE4AE70081D629 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		8BD3981614BE4AE70081D629 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Release;
-		};
 		C01FCF4F08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -864,6 +878,18 @@
 			};
 			name = Release;
 		};
+		F45BBC151B0CE3C6002D064D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		F45BBC161B0CE3C6002D064D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
@@ -885,15 +911,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				8BD3981514BE4AE70081D629 /* Debug */,
-				8BD3981614BE4AE70081D629 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
 		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -912,6 +929,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F45BBC151B0CE3C6002D064D /* Debug */,
+				F45BBC161B0CE3C6002D064D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
index 7083f5e..3b3eeb1 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0620"
+   LastUpgradeVersion = "0630"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -39,9 +39,6 @@
             </BuildableReference>
             <SkippedTests>
                <Test
-                  Identifier = "ArrayTests">
-               </Test>
-               <Test
                   Identifier = "CodedInputStreamTests">
                </Test>
                <Test
@@ -51,16 +48,223 @@
                   Identifier = "ConcurrencyTests">
                </Test>
                <Test
-                  Identifier = "FilteredMessageTests">
+                  Identifier = "DescriptorTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolBoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolDoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolFloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolUInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolUInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBridgeTests">
+               </Test>
+               <Test
+                  Identifier = "GPBDoubleArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBEnumArrayCustomTests">
+               </Test>
+               <Test
+                  Identifier = "GPBEnumArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBFloatArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringBoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringDoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringEnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringEnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringFloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringInt64DictionaryTests">
                </Test>
                <Test
                   Identifier = "GPBStringTests">
                </Test>
                <Test
+                  Identifier = "GPBStringUInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringUInt64DictionaryTests">
+               </Test>
+               <Test
                   Identifier = "GPBTestCase">
                </Test>
                <Test
-                  Identifier = "GeneratedMessageTests">
+                  Identifier = "GPBUInt32ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "MessageMergeTests">
+               </Test>
+               <Test
+                  Identifier = "MessageRuntimeTests">
+               </Test>
+               <Test
+                  Identifier = "MessageSerializationTests">
                </Test>
                <Test
                   Identifier = "MessageTests">
@@ -72,6 +276,9 @@
                   Identifier = "UtilitiesTests">
                </Test>
                <Test
+                  Identifier = "WellKnownTypesTest">
+               </Test>
+               <Test
                   Identifier = "WireFormatTests">
                </Test>
             </SkippedTests>
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
index 617fb47..583a464 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0620"
+   LastUpgradeVersion = "0630"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index d6e621e..23e9f16 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -6,20 +6,6 @@
 	objectVersion = 47;
 	objects = {
 
-/* Begin PBXAggregateTarget section */
-		8BD3981414BE4AE70081D629 /* Compile_Protos */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */;
-			buildPhases = (
-				8BD3981814BE4AF30081D629 /* ShellScript */,
-			);
-			dependencies = (
-			);
-			name = Compile_Protos;
-			productName = Compile_Protos;
-		};
-/* End PBXAggregateTarget section */
-
 /* Begin PBXBuildFile section */
 		2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
 		5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; };
@@ -27,7 +13,7 @@
 		7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; };
 		7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; };
 		7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; };
-		7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBField.m */; };
+		7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; };
 		7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; };
 		7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; };
 		7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; };
@@ -59,7 +45,6 @@
 		8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; };
 		8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; };
 		8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
-		8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */; };
 		8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
 		8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
 		F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; };
@@ -73,15 +58,30 @@
 		F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; };
 		F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; };
 		F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
-		F4487C5B1A9F8F8100531423 /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
 		F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
 		F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
 		F4487C731A9F906200531423 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C711A9F906200531423 /* GPBArray.m */; };
 		F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */; };
 		F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */; };
 		F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */; };
-		F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionField.m */; };
+		F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; };
 		F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */; };
+		F4E675C81B21D1610054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; };
+		F4E675C91B21D1610054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; };
+		F4E675CA1B21D1610054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; };
+		F4E675CB1B21D1610054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */; };
+		F4E675CC1B21D1610054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */; };
+		F4E675CD1B21D1610054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; };
+		F4E675CE1B21D1610054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; };
+		F4E675CF1B21D1610054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; };
+		F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; };
+		F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; };
+		F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; };
+		F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */; };
+		F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */; };
+		F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; };
+		F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; };
+		F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -99,12 +99,12 @@
 			remoteGlobalIDString = 7461B52D0F94FAF800A0C422;
 			remoteInfo = ProtocolBuffers;
 		};
-		8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = {
+		F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
 			proxyType = 1;
-			remoteGlobalIDString = 8BD3981414BE4AE70081D629;
-			remoteInfo = Compile_Protos;
+			remoteGlobalIDString = F45BBC0E1B0CDB50002D064D;
+			remoteInfo = "Compile Unittest Protos";
 		};
 /* End PBXContainerItemProxy section */
 
@@ -122,8 +122,8 @@
 		7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = "<group>"; };
 		7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = "<group>"; };
 		7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = "<group>"; };
-		7461B4AE0F94F99000A0C422 /* GPBField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBField.h; sourceTree = "<group>"; };
-		7461B4AF0F94F99000A0C422 /* GPBField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBField.m; sourceTree = "<group>"; };
+		7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = "<group>"; };
+		7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.m; sourceTree = "<group>"; };
 		7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = "<group>"; };
 		7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = "<group>"; };
 		7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = "<group>"; };
@@ -142,10 +142,7 @@
 		7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = "<group>"; };
 		7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = "<group>"; };
 		7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = "<group>"; };
-		748F0CAF0FD70602000858A9 /* GPBExtensionField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField.h; sourceTree = "<group>"; };
 		8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = "<group>"; };
-		8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter1.txt; sourceTree = "<group>"; };
-		8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_filter.proto; sourceTree = "<group>"; };
 		8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = "<group>"; };
 		8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = "<group>"; };
 		8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -153,7 +150,6 @@
 		8B4248B71A8BDD9600BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_iOS.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; };
 		8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = google/protobuf/Duration.pbobjc.h; sourceTree = "<group>"; };
 		8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = google/protobuf/Duration.pbobjc.m; sourceTree = "<group>"; };
-		8B4248DF1A929C7D00BC1EC6 /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = /google/protobuf/Timestamp.pbobjc.h; sourceTree = "<group>"; };
 		8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = google/protobuf/Timestamp.pbobjc.m; sourceTree = "<group>"; };
 		8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = "<group>"; };
 		8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = "<group>"; };
@@ -161,7 +157,6 @@
 		8B4249481A92A02300BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = "<group>"; };
 		8B4249491A92A0BA00BC1EC6 /* descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = descriptor.proto; path = ../src/google/protobuf/descriptor.proto; sourceTree = "<group>"; };
 		8B42494A1A92A0BA00BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = "<group>"; };
-		8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Descriptor.pbobjc.h; path = /google/protobuf/Descriptor.pbobjc.h; sourceTree = SOURCE_ROOT; };
 		8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
 		8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
 		8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
@@ -186,12 +181,11 @@
 		8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStringTests.m; sourceTree = "<group>"; };
 		8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
 		8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFilteredMessageTests.m; sourceTree = "<group>"; };
 		8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
 		8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
 		8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
 		8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Descriptor.pbobjc.m; path = google/protobuf/Descriptor.pbobjc.m; sourceTree = SOURCE_ROOT; };
-		8BEB5AE01498033E0078BF9D /* GPBTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBTypes.h; sourceTree = "<group>"; };
+		8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
 		F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
 		F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
 		F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
@@ -216,16 +210,41 @@
 		F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = "<group>"; };
 		F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
 		F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
-		F44B25D81A729803005CCF68 /* Filter2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter2.txt; sourceTree = "<group>"; };
 		F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
-		F45C69CB16DFD08D0081955B /* GPBExtensionField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionField.m; sourceTree = "<group>"; };
+		F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = "<group>"; };
 		F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = "<group>"; };
 		F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = "<group>"; };
-		F4B6B8B01A9CC99500892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = "<group>"; };
+		F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = "<group>"; };
 		F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
-		F4B6B8B31A9CD1C600892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = "<group>"; };
+		F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; };
 		F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
-		F4B6B8BA1A9D343B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; };
+		F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; };
+		F4E675B61B21D1440054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; };
+		F4E675B71B21D1440054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; };
+		F4E675B81B21D1440054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = "<group>"; };
+		F4E675B91B21D1440054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = "<group>"; };
+		F4E675BA1B21D1440054530B /* Descriptor.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Descriptor.pbobjc.h; path = google/protobuf/Descriptor.pbobjc.h; sourceTree = "<group>"; };
+		F4E675BB1B21D1440054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = "<group>"; };
+		F4E675BC1B21D1440054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = "<group>"; };
+		F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = "<group>"; };
+		F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = "<group>"; };
+		F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = "<group>"; };
+		F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = "<group>"; };
+		F4E675C11B21D1440054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = "<group>"; };
+		F4E675C21B21D1440054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = "<group>"; };
+		F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = google/protobuf/Timestamp.pbobjc.h; sourceTree = "<group>"; };
+		F4E675C41B21D1440054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = "<group>"; };
+		F4E675C51B21D1440054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = "<group>"; };
+		F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = "<group>"; };
+		F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = "<group>"; };
+		F4E675D81B21D1DE0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = "<group>"; };
+		F4E675D91B21D1DE0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = "<group>"; };
+		F4E675DA1B21D1DE0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = "<group>"; };
+		F4E675DB1B21D1DE0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = "<group>"; };
+		F4E675DC1B21D1DE0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = "<group>"; };
+		F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; };
+		F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; };
+		F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -309,15 +328,39 @@
 		29B97315FDCFA39411CA2CEA /* Generated */ = {
 			isa = PBXGroup;
 			children = (
-				8B4249491A92A0BA00BC1EC6 /* descriptor.proto */,
+				F4E675B61B21D1440054530B /* Any.pbobjc.h */,
+				F4E675B71B21D1440054530B /* Any.pbobjc.m */,
+				F4E675D81B21D1DE0054530B /* any.proto */,
+				F4E675B81B21D1440054530B /* Api.pbobjc.h */,
+				F4E675B91B21D1440054530B /* Api.pbobjc.m */,
+				F4E675D91B21D1DE0054530B /* api.proto */,
+				F4E675BA1B21D1440054530B /* Descriptor.pbobjc.h */,
 				8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */,
-				8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */,
-				8B42494A1A92A0BA00BC1EC6 /* duration.proto */,
+				8B4249491A92A0BA00BC1EC6 /* descriptor.proto */,
 				8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */,
 				8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */,
-				8B4249481A92A02300BC1EC6 /* timestamp.proto */,
-				8B4248DF1A929C7D00BC1EC6 /* Timestamp.pbobjc.h */,
+				8B42494A1A92A0BA00BC1EC6 /* duration.proto */,
+				F4E675BB1B21D1440054530B /* Empty.pbobjc.h */,
+				F4E675BC1B21D1440054530B /* Empty.pbobjc.m */,
+				F4E675DA1B21D1DE0054530B /* empty.proto */,
+				F4E675DB1B21D1DE0054530B /* field_mask.proto */,
+				F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */,
+				F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */,
+				F4E675DC1B21D1DE0054530B /* source_context.proto */,
+				F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */,
+				F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */,
+				F4E675C11B21D1440054530B /* Struct.pbobjc.h */,
+				F4E675C21B21D1440054530B /* Struct.pbobjc.m */,
+				F4E675DD1B21D1DE0054530B /* struct.proto */,
+				F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */,
 				8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */,
+				8B4249481A92A02300BC1EC6 /* timestamp.proto */,
+				F4E675C41B21D1440054530B /* Type.pbobjc.h */,
+				F4E675C51B21D1440054530B /* Type.pbobjc.m */,
+				F4E675DE1B21D1DE0054530B /* type.proto */,
+				F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */,
+				F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */,
+				F4E675DF1B21D1DE0054530B /* wrappers.proto */,
 			);
 			name = Generated;
 			sourceTree = "<group>";
@@ -335,9 +378,8 @@
 		7461B3C50F94F84100A0C422 /* Extensions */ = {
 			isa = PBXGroup;
 			children = (
-				F4B6B8B31A9CD1C600892426 /* GPBExtensionField_PackagePrivate.h */,
-				748F0CAF0FD70602000858A9 /* GPBExtensionField.h */,
-				F45C69CB16DFD08D0081955B /* GPBExtensionField.m */,
+				F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */,
+				F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */,
 				7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */,
 				7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */,
 				F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */,
@@ -350,9 +392,9 @@
 		7461B4850F94F96600A0C422 /* Fields */ = {
 			isa = PBXGroup;
 			children = (
-				F4B6B8B01A9CC99500892426 /* GPBField_PackagePrivate.h */,
-				7461B4AE0F94F99000A0C422 /* GPBField.h */,
-				7461B4AF0F94F99000A0C422 /* GPBField.m */,
+				F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */,
+				7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
+				7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
 				F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
 				7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
 				7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
@@ -392,8 +434,6 @@
 			children = (
 				8B9A5EA91831993600A9D33B /* iOSTestHarness */,
 				8B4248B71A8BDD9600BC1EC6 /* protobuf */,
-				8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */,
-				F44B25D81A729803005CCF68 /* Filter2.txt */,
 				8B210CCD159383D60032D72D /* golden_message */,
 				8B210CCF159386920032D72D /* golden_packed_fields_message */,
 				8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
@@ -409,7 +449,6 @@
 				F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */,
 				F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */,
 				F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */,
-				8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */,
 				7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
 				F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
 				F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
@@ -431,13 +470,12 @@
 				8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
 				8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
 				8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
-				8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */,
 				8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
 				8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
 				8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
-				F4B6B8BA1A9D343B00892426 /* unittest_name_mangling.proto */,
 				8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
 				8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
+				F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */,
 				8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
 				F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */,
 				F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */,
@@ -478,7 +516,7 @@
 				F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */,
 				F4353D241ABB156F005A6198 /* GPBDictionary.h */,
 				F4353D251ABB156F005A6198 /* GPBDictionary.m */,
-				8BEB5AE01498033E0078BF9D /* GPBTypes.h */,
+				8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */,
 				F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */,
 				7461B4E50F94F99000A0C422 /* GPBUtilities.h */,
 				7461B4E60F94F99000A0C422 /* GPBUtilities.m */,
@@ -507,6 +545,23 @@
 		};
 /* End PBXHeadersBuildPhase section */
 
+/* Begin PBXLegacyTarget section */
+		F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = "$(ACTION)";
+			buildConfigurationList = F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */;
+			buildPhases = (
+			);
+			buildToolPath = DevTools/compile_testing_protos.sh;
+			buildWorkingDirectory = "";
+			dependencies = (
+			);
+			name = "Compile Unittest Protos";
+			passBuildSettingsInEnvironment = 1;
+			productName = "Compile Unittest Protos";
+		};
+/* End PBXLegacyTarget section */
+
 /* Begin PBXNativeTarget section */
 		7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = {
 			isa = PBXNativeTarget;
@@ -555,7 +610,7 @@
 			);
 			dependencies = (
 				8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */,
-				8BD3982114BE59EB0081D629 /* PBXTargetDependency */,
+				F45BBC131B0CDBBA002D064D /* PBXTargetDependency */,
 				8B9A5ED11831994600A9D33B /* PBXTargetDependency */,
 			);
 			name = UnitTests;
@@ -587,11 +642,14 @@
 			isa = PBXProject;
 			attributes = {
 				LastTestingUpgradeCheck = 0600;
-				LastUpgradeCheck = 0610;
+				LastUpgradeCheck = 0630;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
 						TestTargetID = 8B9A5EA41831993600A9D33B;
 					};
+					F45BBC0E1B0CDB50002D064D = {
+						CreatedOnToolsVersion = 6.3.2;
+					};
 				};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */;
@@ -607,9 +665,9 @@
 			targets = (
 				7461B52D0F94FAF800A0C422 /* ProtocolBuffers */,
 				8BBEA4A5147C727100C4ADB7 /* UnitTests */,
-				8BD3981414BE4AE70081D629 /* Compile_Protos */,
 				8B9A5EA41831993600A9D33B /* iOSTestHarness */,
 				F4487C551A9F8F8100531423 /* TestSingleSourceBuild */,
+				F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */,
 			);
 		};
 /* End PBXProject section */
@@ -639,51 +697,6 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		8BD3981814BE4AF30081D629 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-				"$(SRCROOT)/../src/google/protobuf/unittest_custom_options.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_embed_optimize_for.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_empty.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_enormous_descriptor.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_lite_imports_nonlite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_mset.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_no_generic_services.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest.proto",
-				"$(SRCROOT)/Tests/unittest_objc.proto",
-				"$(SRCROOT)/../src/.libs/libprotoc.10.dylib",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_public_lite.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_import_public.proto",
-				"$(SRCROOT)/Tests/unittest_filter.proto",
-				"$(SRCROOT)/../src/.libs/libprotobuf.10.dylib",
-				"$(SRCROOT)/../src/.libs/protoc",
-				"$(SRCROOT)/Tests/Filter1.txt",
-				"$(SRCROOT)/Tests/Filter2.txt",
-				"$(SRCROOT)/Tests/unittest_cycle.proto",
-				"$(SRCROOT)/Tests/unittest_name_mangling.proto",
-				"$(SRCROOT)/Tests/unittest_runtime_proto2.proto",
-				"$(SRCROOT)/Tests/unittest_runtime_proto3.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_drop_unknown_fields.proto",
-				"$(SRCROOT)/../src/google/protobuf/unittest_preserve_unknown_enum.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_lite_unittest.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_proto2_unittest.proto",
-				"$(SRCROOT)/../src/google/protobuf/map_unittest.proto",
-			);
-			outputPaths = (
-				"$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.h",
-				"$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.m",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/bash;
-			shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n";
-			showEnvVarsInLog = 0;
-		};
 		F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -708,19 +721,27 @@
 			files = (
 				2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */,
 				7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */,
+				F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */,
 				F4487C731A9F906200531423 /* GPBArray.m in Sources */,
 				7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
 				7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */,
-				7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */,
+				F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */,
+				7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */,
 				7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */,
 				7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */,
 				7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */,
 				7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */,
+				F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */,
+				F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */,
 				F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */,
 				8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */,
 				8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */,
-				F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */,
+				F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */,
+				F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */,
 				8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */,
+				F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */,
+				F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */,
+				F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -741,12 +762,18 @@
 				F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */,
 				F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
 				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+				F4E675CC1B21D1610054530B /* SourceContext.pbobjc.m in Sources */,
 				8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
 				F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */,
 				8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
+				F4E675CA1B21D1610054530B /* Empty.pbobjc.m in Sources */,
+				F4E675CE1B21D1610054530B /* Type.pbobjc.m in Sources */,
 				F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */,
+				F4E675CF1B21D1610054530B /* Wrappers.pbobjc.m in Sources */,
+				F4E675C81B21D1610054530B /* Any.pbobjc.m in Sources */,
 				8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
 				5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
+				F4E675CD1B21D1610054530B /* Struct.pbobjc.m in Sources */,
 				F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
 				F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
 				8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
@@ -761,9 +788,10 @@
 				8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
 				8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */,
 				8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
+				F4E675CB1B21D1610054530B /* FieldMask.pbobjc.m in Sources */,
 				8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */,
-				8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */,
 				8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
+				F4E675C91B21D1610054530B /* Api.pbobjc.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -771,7 +799,6 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				F4487C5B1A9F8F8100531423 /* Descriptor.pbobjc.m in Sources */,
 				F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -789,10 +816,10 @@
 			target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */;
 			targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */;
 		};
-		8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = {
+		F45BBC131B0CDBBA002D064D /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
-			target = 8BD3981414BE4AE70081D629 /* Compile_Protos */;
-			targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */;
+			target = F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */;
+			targetProxy = F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */;
 		};
 /* End PBXTargetDependency section */
 
@@ -909,20 +936,6 @@
 			};
 			name = Release;
 		};
-		8BD3981514BE4AE70081D629 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		8BD3981614BE4AE70081D629 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Release;
-		};
 		C01FCF4F08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1029,6 +1042,18 @@
 			};
 			name = Release;
 		};
+		F45BBC0F1B0CDB50002D064D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		F45BBC101B0CDB50002D064D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
@@ -1059,15 +1084,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				8BD3981514BE4AE70081D629 /* Debug */,
-				8BD3981614BE4AE70081D629 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
 		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -1086,6 +1102,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F45BBC0F1B0CDB50002D064D /* Debug */,
+				F45BBC101B0CDB50002D064D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
index f5479ba..4898eb5 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0610"
+   LastUpgradeVersion = "0630"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -39,9 +39,6 @@
             </BuildableReference>
             <SkippedTests>
                <Test
-                  Identifier = "ArrayTests">
-               </Test>
-               <Test
                   Identifier = "CodedInputStreamTests">
                </Test>
                <Test
@@ -51,16 +48,223 @@
                   Identifier = "ConcurrencyTests">
                </Test>
                <Test
-                  Identifier = "FilteredMessageTests">
+                  Identifier = "DescriptorTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolBoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolDoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolFloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolUInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBoolUInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBBridgeTests">
+               </Test>
+               <Test
+                  Identifier = "GPBDoubleArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBEnumArrayCustomTests">
+               </Test>
+               <Test
+                  Identifier = "GPBEnumArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBFloatArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt32UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBInt64UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringBoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringDoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringEnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringEnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringFloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringInt64DictionaryTests">
                </Test>
                <Test
                   Identifier = "GPBStringTests">
                </Test>
                <Test
+                  Identifier = "GPBStringUInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBStringUInt64DictionaryTests">
+               </Test>
+               <Test
                   Identifier = "GPBTestCase">
                </Test>
                <Test
-                  Identifier = "GeneratedMessageTests">
+                  Identifier = "GPBUInt32ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt32UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64ArrayTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64BoolDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64DoubleDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64EnumDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64EnumDictionaryUnknownEnumTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64FloatDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64Int32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64Int64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64ObjectDictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64UInt32DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "GPBUInt64UInt64DictionaryTests">
+               </Test>
+               <Test
+                  Identifier = "MessageMergeTests">
+               </Test>
+               <Test
+                  Identifier = "MessageRuntimeTests">
+               </Test>
+               <Test
+                  Identifier = "MessageSerializationTests">
                </Test>
                <Test
                   Identifier = "MessageTests">
@@ -72,6 +276,9 @@
                   Identifier = "UtilitiesTests">
                </Test>
                <Test
+                  Identifier = "WellKnownTypesTest">
+               </Test>
+               <Test
                   Identifier = "WireFormatTests">
                </Test>
             </SkippedTests>
@@ -96,7 +303,8 @@
       ignoresPersistentStateOnLaunch = "NO"
       debugDocumentVersioning = "YES"
       allowLocationSimulation = "YES">
-      <BuildableProductRunnable>
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
index c3c2c7d..19267fc 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0610"
+   LastUpgradeVersion = "0630"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/objectivec/README.md b/objectivec/README.md
index 186e45b..134bf1a 100644
--- a/objectivec/README.md
+++ b/objectivec/README.md
@@ -21,15 +21,15 @@
 ------------
 
 The full distribution pulled from github includes the sources for both the
-compiler (protoc) and the runtime (this directory).  To build the compiler
+compiler (protoc) and the runtime (this directory). To build the compiler
 and run the runtime tests, you can use:
 
      $ objectivec/DevTools/full_mac_build.sh
 
 This will generate the `src/protoc` binary.
 
-Usage
------
+Building
+--------
 
 There are two ways to include the Runtime sources in your project:
 
@@ -47,6 +47,80 @@
 The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h' and
 `\*.pbobjc.m`) are then also added to the target.
 
+Usage
+-----
+
+The objects generated for messages should work like any other Objective C
+object. They are mutable objects, but if you don't change them, they are safe
+to share between threads (similar to passing an NSMutableDictionary between
+threads/queues; as long as no one mutates it, things are fine).
+
+There are a few behaviors worth calling out:
+
+A property that is type NSString\* will never return nil. If the value is
+unset, it will return an empty string (@""). This is inpart to align things
+with the Protocol Buffers spec which says the default for strings is an empty
+string, but also so you can always safely pass them to isEqual:/compare:, etc.
+and have deterministic results.
+
+A property that is type NSData\* also won't return nil, it will return an empty
+data ([NSData data]). The reasoning is the same as for NSString not returning
+nil.
+
+A property that is another GPBMessage class also will not return nil. If the
+field wasn't already set, you will get a instance of the correct class. This
+instance will be a temporary instance unless you mutate it, at which point it
+will be attached to its parent object. We call this pattern *autocreators*.
+Similar to NSString and NSData properties it makes things a little safer when
+using them with isEqual:/etc.; but more importantly, this allows you to write
+code that uses Objective C's property dot notation to walk into nested objects
+and access and/or assign things without having to check that they are not nil
+and create them each step along the way. You can write this:
+
+```
+- (void)updateRecord:(MyMessage *)msg {
+  ...
+  // Note: You don't have to check subMessage and otherMessage for nil and
+  // alloc/init/assign them back along the way.
+  msg.subMessage.otherMessage.lastName = @"Smith";
+  ...
+}
+```
+
+If you want to check if a GPBMessage property is present, there is always as
+`has\[NAME\]` property to go with the main property to check if it is set.
+
+A property that is of an Array or Dictionary type also provides *autocreator*
+behavior and will never return nil. This provides all the same benefits you
+see for the message properties. Again, you can write:
+
+```
+- (void)updateRecord:(MyMessage *)msg {
+  ...
+  // Note: Just like above, you don't have to check subMessage and otherMessage
+  // for nil and alloc/init/assign them back along the way. You also don't have
+  // to create the siblingsArray, you can safely just append to it.
+  [msg.subMessage.otherMessage.siblingsArray addObject:@"Pat"];
+  ...
+}
+```
+
+If you are inspecting a message you got from some other place (server, disk,
+etc), you may want to check if the Array or Dictionary has entries without
+causing it to be created for you. For this, there is always a `\[NAME\]_Count`
+property also provided that can return zero or the real count, but won't trigger
+the creation.
+
+For primitive type fields (ints, floats, bools, enum) in messages defined in a
+`.proto` file that use *proto2* syntax there are conceptual differences between
+having an *explicit* and *default* value. You can always get the value of the
+property. In the case that it hasn't been set you will get the default. In
+cases where you need to know whether it was set explicitly or you are just
+getting the default, you can use the `has\[NAME\]` property. If the value has
+been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`.
+*proto3* syntax messages do away with this concept, thus the default values are
+never included when the message is encoded.
+
 The Objective C classes/enums can be used from Swift code.
 
 Objective C Generator Options
@@ -55,18 +129,19 @@
 **objc_class_prefix=\<prefix\>** (no default)
 
 Since Objective C uses a global namespace for all of its classes, there can
-be collisions.  This option provides a prefix that will be added to the Enums
-and Objects (for messages) generated from the proto.  Convention is to base
+be collisions. This option provides a prefix that will be added to the Enums
+and Objects (for messages) generated from the proto. Convention is to base
 the prefix on the package the proto is in.
 
 Contributing
 ------------
 
 Please make updates to the tests along with changes. If just changing the
-runtime, the Xcode projects can be used to build and run tests.  If change also
-require changes to the generated code, `objectivec/DevTools/full_mac_build.sh`
-can be used to easily rebuild and test changes. Passing `-h` to the script will
-show the addition options that could be useful.
+runtime, the Xcode projects can be used to build and run tests. If your change
+also requires changes to the generated code,
+`objectivec/DevTools/full_mac_build.sh` can be used to easily rebuild and test
+changes. Passing `-h` to the script will show the addition options that could
+be useful.
 
 Documentation
 -------------
diff --git a/objectivec/Tests/Filter1.txt b/objectivec/Tests/Filter1.txt
deleted file mode 100644
index 88a5cac..0000000
--- a/objectivec/Tests/Filter1.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 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.
-
-
-// Test the filter system for the ObjC Protocol Buffer Compiler.
-
-// Class names are matched using file name globbing rules.
-// Whitespace is not allowed at the beginning of a line (except for a line
-// that is a single newline).
-
-Keep
-RemoveEnumMessage_KeepNestedInside
-RemoveJustKidding
diff --git a/objectivec/Tests/Filter2.txt b/objectivec/Tests/Filter2.txt
deleted file mode 100644
index 5a2bb0f..0000000
--- a/objectivec/Tests/Filter2.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 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.
-
-
-// Test the filter system for the ObjC Protocol Buffer Compiler to test
-// multiple filter support.
-
-Other
diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m
index daf4eff..d040886 100644
--- a/objectivec/Tests/GPBARCUnittestProtos.m
+++ b/objectivec/Tests/GPBARCUnittestProtos.m
@@ -41,16 +41,15 @@
 #import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h"
 #import "google/protobuf/UnittestEmpty.pbobjc.h"
 #import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h"
-#import "google/protobuf/UnittestFilter.pbobjc.h"
 #import "google/protobuf/UnittestImport.pbobjc.h"
 #import "google/protobuf/UnittestImportLite.pbobjc.h"
 #import "google/protobuf/UnittestImportPublic.pbobjc.h"
 #import "google/protobuf/UnittestImportPublicLite.pbobjc.h"
 #import "google/protobuf/UnittestLite.pbobjc.h"
 #import "google/protobuf/UnittestMset.pbobjc.h"
-#import "google/protobuf/UnittestNameMangling.pbobjc.h"
 #import "google/protobuf/UnittestNoGenericServices.pbobjc.h"
 #import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
 #import "google/protobuf/UnittestOptimizeFor.pbobjc.h"
 #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
 #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
index 5f29d7c..579fe65 100644
--- a/objectivec/Tests/GPBCodedInputStreamTests.m
+++ b/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -260,7 +260,7 @@
       [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
   XCTAssertEqual(tag, [input readTag]);
 
-  XCTAssertThrows([input readData]);
+  XCTAssertThrows([input readBytes]);
 }
 
 // Verifies fix for b/10315336.
diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m
index e500ad7..daf75e7 100644
--- a/objectivec/Tests/GPBConcurrencyTests.m
+++ b/objectivec/Tests/GPBConcurrencyTests.m
@@ -196,7 +196,8 @@
   NSArray *threads = [self createThreadsWithSelector:sel object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
-  GPBExtensionField *extension = [UnittestRoot optionalForeignMessageExtension];
+  GPBExtensionDescriptor *extension =
+      [UnittestRoot optionalForeignMessageExtension];
   for (TestAllExtensions *message in messages) {
     XCTAssertFalse([message hasExtension:extension]);
   }
diff --git a/objectivec/Tests/GPBFilteredMessageTests.m b/objectivec/Tests/GPBFilteredMessageTests.m
deleted file mode 100644
index b058883..0000000
--- a/objectivec/Tests/GPBFilteredMessageTests.m
+++ /dev/null
@@ -1,98 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2013 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.
-
-// Tests our filter system for ObjC.
-// The proto being filtered is unittest_filter.proto.
-// The filter file is Filter.txt.
-
-#import "GPBTestUtilities.h"
-
-#import "google/protobuf/UnittestFilter.pbobjc.h"
-
-// If we get an error about this already being defined, it is most likely
-// because of an error in protoc which is supposed to be filtering
-// the Remove message.
-enum { Other_FieldNumber_B = 0 };
-
-@interface FilteredMessageTests : GPBTestCase
-@end
-
-@implementation FilteredMessageTests
-
-- (void)testEnumFiltering {
-  // If compile fails here it is because protoc did not generate KeepEnum.
-  XCTAssertTrue(KeepEnum_IsValidValue(KeepEnum_KeepValue));
-  XCTAssertNotNil(KeepEnum_EnumDescriptor());
-
-  // If compile fails here it is because protoc did not generate
-  // KeepEnumInsideEnum and is probably due to nested enum handling being
-  // broken.
-  XCTAssertTrue(RemoveEnumMessage_KeepEnumInside_IsValidValue(
-      RemoveEnumMessage_KeepEnumInside_KeepValue));
-  XCTAssertNotNil(RemoveEnumMessage_KeepEnumInside_EnumDescriptor());
-}
-
-- (void)testMessageFiltering {
-  // Messages that should be generated.
-  XCTAssertNil([UnittestFilterRoot extensionRegistry]);
-  XCTAssertNotNil([[[Keep alloc] init] autorelease]);
-  XCTAssertNotNil([[[Other alloc] init] autorelease]);
-  XCTAssertNotNil([[[RemoveJustKidding alloc] init] autorelease]);
-  XCTAssertNotNil(
-      [[[RemoveEnumMessage_KeepNestedInside alloc] init] autorelease]);
-
-  // Messages that should not be generated
-  XCTAssertNil(NSClassFromString(@"Remove"));
-  XCTAssertNil(NSClassFromString(@"RemoveEnumMessage"));
-  XCTAssertNil(NSClassFromString(@"RemoveEnumMessage_RemoveNestedInside"));
-
-  // These should all fail compile if protoc is bad.
-  XCTAssertTrue([Other instancesRespondToSelector:@selector(hasA)]);
-  XCTAssertTrue([Other instancesRespondToSelector:@selector(setHasA:)]);
-  XCTAssertTrue([Other instancesRespondToSelector:@selector(a)]);
-  XCTAssertTrue([Other instancesRespondToSelector:@selector(setA:)]);
-
-  // These the compiler should not generate.
-  XCTAssertFalse(
-      [Other instancesRespondToSelector:NSSelectorFromString(@"hasB")]);
-  XCTAssertFalse(
-      [Other instancesRespondToSelector:NSSelectorFromString(@"setHasB:")]);
-  XCTAssertFalse([Other instancesRespondToSelector:NSSelectorFromString(@"b")]);
-  XCTAssertFalse(
-      [Other instancesRespondToSelector:NSSelectorFromString(@"setB:")]);
-
-  // This should fail if protoc filters it.
-  XCTAssertEqual(Other_FieldNumber_A, 1);
-
-  // Make sure the definition at the top of the file is providing the value.
-  XCTAssertEqual(Other_FieldNumber_B, 0);
-}
-
-@end
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
index 4621f90..8942a84 100644
--- a/objectivec/Tests/GPBMessageTests+Runtime.m
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -36,6 +36,7 @@
 
 #import "google/protobuf/MapUnittest.pbobjc.h"
 #import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
 #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
 #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
 
@@ -47,6 +48,14 @@
 // TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime
 // specific.
 
+- (void)testStartupOrdering {
+  // Just have to create a message.  Nothing else uses the classes from
+  // this file, so the first selector invoked on the class will initialize
+  // it, which also initializes the root.
+  TestObjCStartupMessage *message = [TestObjCStartupMessage message];
+  XCTAssertNotNil(message);
+}
+
 - (void)testProto2HasMethodSupport {
   NSArray *names = @[
     @"Int32",
@@ -70,8 +79,8 @@
   ];
 
   // Proto2 gets:
-  //  - has* on all non repeated fields.
-  //  - setHas* on all non repeated fields.
+
+  // Single fields - has*/setHas* is valid.
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
@@ -85,21 +94,28 @@
                   name);
   }
 
-  // Repeated - no has/setHas
+  // Repeated fields
+  //  - no has*/setHas*
+  //  - *Count
 
   for (NSString *name in names) {
-    // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+    // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
     SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasRepeated%@", name]);
+        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
     SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
     XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
                    name);
     XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
                    @"field: %@", name);
+    // build the selector, i.e. - repeatedInt32Array_Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
   }
 
-  // Oneofs - no has/setHas
+  // OneOf fields - no has*/setHas*
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
@@ -112,6 +128,50 @@
     XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
                    @"field: %@", name);
   }
+
+  // map<> fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  NSArray *mapNames = @[
+    @"Int32Int32",
+    @"Int64Int64",
+    @"Uint32Uint32",
+    @"Uint64Uint64",
+    @"Sint32Sint32",
+    @"Sint64Sint64",
+    @"Fixed32Fixed32",
+    @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32",
+    @"Sfixed64Sfixed64",
+    @"Int32Float",
+    @"Int32Double",
+    @"BoolBool",
+    @"StringString",
+    @"StringBytes",
+    @"StringMessage",
+    @"Int32Bytes",
+    @"Int32Enum",
+    @"Int32Message",
+  ];
+
+  for (NSString *name in mapNames) {
+    // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - mapInt32Int32Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
+  }
+
 }
 
 - (void)testProto3HasMethodSupport {
@@ -136,10 +196,10 @@
   ];
 
   // Proto3 gets:
-  //  - has* on non repeated message fields.
-  //  - setHas* on all non repeated message fields.
 
-  // Singlular
+  // Single fields
+  //  - has*/setHas* invalid for primative types.
+  //  - has*/setHas* valid for Message.
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
@@ -147,7 +207,7 @@
         [NSString stringWithFormat:@"hasOptional%@", name]);
     SEL setHasSel = NSSelectorFromString(
         [NSString stringWithFormat:@"setHasOptional%@:", name]);
-    if ([name isEqual:@"Group"] || [name isEqual:@"Message"]) {
+    if ([name isEqual:@"Message"]) {
       // Sub messages/groups are the exception.
       XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@",
                     name);
@@ -161,21 +221,28 @@
     }
   }
 
-  // Repeated - no has/setHas
+  // Repeated fields
+  //  - no has*/setHas*
+  //  - *Count
 
   for (NSString *name in names) {
-    // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+    // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
     SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasRepeated%@", name]);
+        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
     SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
     XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
                    name);
     XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
                    @"field: %@", name);
+    // build the selector, i.e. - repeatedInt32Array_Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                  name);
   }
 
-  // Oneofs - no has/setHas
+  // OneOf fields - no has*/setHas*
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
@@ -188,6 +255,49 @@
     XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
                    @"field: %@", name);
   }
+
+  // map<> fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  NSArray *mapNames = @[
+    @"Int32Int32",
+    @"Int64Int64",
+    @"Uint32Uint32",
+    @"Uint64Uint64",
+    @"Sint32Sint32",
+    @"Sint64Sint64",
+    @"Fixed32Fixed32",
+    @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32",
+    @"Sfixed64Sfixed64",
+    @"Int32Float",
+    @"Int32Double",
+    @"BoolBool",
+    @"StringString",
+    @"StringBytes",
+    @"StringMessage",
+    @"Int32Bytes",
+    @"Int32Enum",
+    @"Int32Message",
+  ];
+
+  for (NSString *name in mapNames) {
+    // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - mapInt32Int32Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
+  }
 }
 
 - (void)testProto2SingleFieldHasBehavior {
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
index 6d5527b..ae4be9e 100644
--- a/objectivec/Tests/GPBMessageTests+Serialization.m
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -36,6 +36,7 @@
 
 #import "google/protobuf/MapProto2Unittest.pbobjc.h"
 #import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
 #import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
 #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
 #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
@@ -166,17 +167,15 @@
       [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
   XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]);
 
-  GPBField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum];
+  GPBUnknownField *field =
+      [unknownFields getField:Message2_FieldNumber_OptionalEnum];
   XCTAssertEqual(field.varintList.count, 1U);
   XCTAssertEqual([field.varintList valueAtIndex:0],
                  (uint64_t)Message3_Enum_Extra3);
 
-  // Repeated in proto3 default to packed, so this will be length delimited
-  // unknown field, and the value (Message3_Enum_Extra3) encodes into one byte.
   field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray];
-  XCTAssertEqual(field.lengthDelimitedList.count, 1U);
-  NSData *expected = DataFromCStr("\x1E");
-  XCTAssertEqualObjects([field.lengthDelimitedList objectAtIndex:0], expected);
+  XCTAssertEqual(field.varintList.count, 1U);
+  XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3);
 
   field = [unknownFields getField:Message2_FieldNumber_OneofEnum];
   XCTAssertEqual(field.varintList.count, 1U);
@@ -678,6 +677,131 @@
 
 //%PDDM-EXPAND-END (2 expansions)
 
+- (void)testPackedUnpackedMessageParsing {
+  // packed is optional, a repeated field should parse when packed or unpacked.
+
+  TestPackedTypes *packedOrig = [TestPackedTypes message];
+  TestUnpackedTypes *unpackedOrig = [TestUnpackedTypes message];
+  [self setPackedFields:packedOrig repeatedCount:4];
+  [self setUnpackedFields:unpackedOrig repeatedCount:4];
+
+  NSData *packedData = [packedOrig data];
+  NSData *unpackedData = [unpackedOrig data];
+  XCTAssertNotNil(packedData);
+  XCTAssertNotNil(unpackedData);
+  XCTAssertNotEqualObjects(packedData, unpackedData,
+                           @"Data should differ (packed vs unpacked) use");
+
+  NSError *error = nil;
+  TestPackedTypes *packedParse =
+      [TestPackedTypes parseFromData:unpackedData error:&error];
+  XCTAssertNotNil(packedParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(packedParse, packedOrig);
+
+  error = nil;
+  TestUnpackedTypes *unpackedParsed =
+      [TestUnpackedTypes parseFromData:packedData error:&error];
+  XCTAssertNotNil(unpackedParsed);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(unpackedParsed, unpackedOrig);
+}
+
+- (void)testPackedUnpackedExtensionParsing {
+  // packed is optional, a repeated extension should parse when packed or
+  // unpacked.
+
+  TestPackedExtensions *packedOrig = [TestPackedExtensions message];
+  TestUnpackedExtensions *unpackedOrig = [TestUnpackedExtensions message];
+  [self setPackedExtensions:packedOrig repeatedCount:kGPBDefaultRepeatCount];
+  [self setUnpackedExtensions:unpackedOrig repeatedCount:kGPBDefaultRepeatCount];
+
+  NSData *packedData = [packedOrig data];
+  NSData *unpackedData = [unpackedOrig data];
+  XCTAssertNotNil(packedData);
+  XCTAssertNotNil(unpackedData);
+  XCTAssertNotEqualObjects(packedData, unpackedData,
+                           @"Data should differ (packed vs unpacked) use");
+
+  NSError *error = nil;
+  TestPackedExtensions *packedParse =
+      [TestPackedExtensions parseFromData:unpackedData
+                        extensionRegistry:[UnittestRoot extensionRegistry]
+                                    error:&error];
+  XCTAssertNotNil(packedParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(packedParse, packedOrig);
+
+  error = nil;
+  TestUnpackedExtensions *unpackedParsed =
+      [TestUnpackedExtensions parseFromData:packedData
+                          extensionRegistry:[UnittestRoot extensionRegistry]
+                                      error:&error];
+  XCTAssertNotNil(unpackedParsed);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(unpackedParsed, unpackedOrig);
+}
+
+- (void)testPackedExtensionVsFieldParsing {
+  // Extensions and fields end up on the wire the same way, so they can parse
+  // each other.
+
+  TestPackedTypes *fieldsOrig = [TestPackedTypes message];
+  TestPackedExtensions *extsOrig = [TestPackedExtensions message];
+  [self setPackedFields:fieldsOrig repeatedCount:kGPBDefaultRepeatCount];
+  [self setPackedExtensions:extsOrig repeatedCount:kGPBDefaultRepeatCount];
+
+  NSData *fieldsData = [fieldsOrig data];
+  NSData *extsData = [extsOrig data];
+  XCTAssertNotNil(fieldsData);
+  XCTAssertNotNil(extsData);
+  XCTAssertEqualObjects(fieldsData, extsData);
+
+  NSError *error = nil;
+  TestPackedTypes *fieldsParse =
+      [TestPackedTypes parseFromData:extsData error:&error];
+  XCTAssertNotNil(fieldsParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(fieldsParse, fieldsOrig);
+
+  error = nil;
+  TestPackedExtensions *extsParse =
+      [TestPackedExtensions parseFromData:fieldsData
+                        extensionRegistry:[UnittestRoot extensionRegistry]
+                                    error:&error];
+  XCTAssertNotNil(extsParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(extsParse, extsOrig);
+}
+
+- (void)testUnpackedExtensionVsFieldParsing {
+  // Extensions and fields end up on the wire the same way, so they can parse
+  // each other.
+
+  TestUnpackedTypes *fieldsOrig = [TestUnpackedTypes message];
+  TestUnpackedExtensions *extsOrig = [TestUnpackedExtensions message];
+  [self setUnpackedFields:fieldsOrig repeatedCount:3];
+  [self setUnpackedExtensions:extsOrig repeatedCount:3];
+
+  NSData *fieldsData = [fieldsOrig data];
+  NSData *extsData = [extsOrig data];
+  XCTAssertNotNil(fieldsData);
+  XCTAssertNotNil(extsData);
+  XCTAssertEqualObjects(fieldsData, extsData);
+
+  TestUnpackedTypes *fieldsParse =
+      [TestUnpackedTypes parseFromData:extsData error:NULL];
+  XCTAssertNotNil(fieldsParse);
+  XCTAssertEqualObjects(fieldsParse, fieldsOrig);
+
+  TestUnpackedExtensions *extsParse =
+      [TestUnpackedExtensions parseFromData:fieldsData
+                          extensionRegistry:[UnittestRoot extensionRegistry]
+                                      error:NULL];
+  XCTAssertNotNil(extsParse);
+  XCTAssertEqualObjects(extsParse, extsOrig);
+}
+
 #pragma mark - Subset from from map_tests.cc
 
 // TEST(GeneratedMapFieldTest, StandardWireFormat)
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
index e0154c1..cd0de8f 100644
--- a/objectivec/Tests/GPBMessageTests.m
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -35,12 +35,11 @@
 #import "GPBArray_PackagePrivate.h"
 #import "GPBDescriptor.h"
 #import "GPBDictionary_PackagePrivate.h"
-#import "GPBField_PackagePrivate.h"
 #import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
 #import "google/protobuf/Unittest.pbobjc.h"
 #import "google/protobuf/UnittestObjc.pbobjc.h"
-#import "google/protobuf/UnittestNameMangling.pbobjc.h"
 
 @interface MessageTests : GPBTestCase
 @end
@@ -420,10 +419,11 @@
 
   GPBUnknownFieldSet *unknownFields =
       [[[GPBUnknownFieldSet alloc] init] autorelease];
-  GPBField *field = [[[GPBField alloc] initWithNumber:2] autorelease];
+  GPBUnknownField *field =
+      [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
   [field addVarint:2];
   [unknownFields addField:field];
-  field = [[[GPBField alloc] initWithNumber:3] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
   [field addVarint:4];
   [unknownFields addField:field];
 
@@ -451,7 +451,7 @@
   GPBFieldDescriptor *fieldDescriptor =
       [descriptor fieldWithName:@"defaultInt32"];
   XCTAssertNotNil(fieldDescriptor);
-  GPBValue defaultValue = [fieldDescriptor defaultValue];
+  GPBGenericValue defaultValue = [fieldDescriptor defaultValue];
   [message setDefaultInt32:defaultValue.valueInt32];
   XCTAssertTrue(message.hasDefaultInt32);
   XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32);
@@ -1554,7 +1554,7 @@
   // The other should not.
   TestAllExtensions *message = [TestAllExtensions message];
   TestAllExtensions *message2 = [TestAllExtensions message];
-  GPBExtensionField *extension = [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension];
   [message setExtension:extension value:[message2 getExtension:extension]];
   XCTAssertEqual([message getExtension:extension],
                  [message2 getExtension:extension]);
@@ -1571,9 +1571,9 @@
 - (void)testCopyWithAutocreatedExtension {
   // Mutable copy shouldn't copy autocreated extensions.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *optionalGroupExtension =
+  GPBExtensionDescriptor *optionalGroupExtension =
       [UnittestRoot optionalGroupExtension];
-  GPBExtensionField *optionalNestedMessageExtesion =
+  GPBExtensionDescriptor *optionalNestedMessageExtesion =
       [UnittestRoot optionalNestedMessageExtension];
   TestAllTypes_OptionalGroup *optionalGroup =
       [message getExtension:optionalGroupExtension];
@@ -1603,7 +1603,7 @@
 - (void)testClearMessageAutocreatedExtension {
   // Call clear should cause it to recreate its autocreated extensions.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *optionalGroupExtension =
+  GPBExtensionDescriptor *optionalGroupExtension =
       [UnittestRoot optionalGroupExtension];
   TestAllTypes_OptionalGroup *optionalGroup =
       [[message getExtension:optionalGroupExtension] retain];
@@ -1620,7 +1620,7 @@
   // Should be able to retain autocreated extension while the creator is
   // dealloced.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *optionalGroupExtension =
+  GPBExtensionDescriptor *optionalGroupExtension =
       [UnittestRoot optionalGroupExtension];
 
   @autoreleasepool {
@@ -1638,7 +1638,7 @@
 - (void)testClearAutocreatedExtension {
   // Clearing autocreated extension should NOT cause it to lose its creator.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *optionalGroupExtension =
+  GPBExtensionDescriptor *optionalGroupExtension =
       [UnittestRoot optionalGroupExtension];
   TestAllTypes_OptionalGroup *optionalGroup =
       [[message getExtension:optionalGroupExtension] retain];
@@ -1651,7 +1651,8 @@
 
   // Clearing autocreated extension should not cause its creator to become
   // visible
-  GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
   TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
   TestAllExtensions *message_lvl3 =
       [message_lvl2 getExtension:recursiveExtension];
@@ -1663,7 +1664,8 @@
   // Setting an extension should cause the extension to appear to its creator.
   // Test this several levels deep.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
   TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
   TestAllExtensions *message_lvl3 =
       [message_lvl2 getExtension:recursiveExtension];
@@ -1686,7 +1688,7 @@
 - (void)testSetAutocreatedExtensionToSelf {
   // Setting extension to itself should cause it to become visible.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionField *optionalGroupExtension =
+  GPBExtensionDescriptor *optionalGroupExtension =
       [UnittestRoot optionalGroupExtension];
   XCTAssertNotNil([message getExtension:optionalGroupExtension]);
   XCTAssertFalse([message hasExtension:optionalGroupExtension]);
@@ -1696,7 +1698,8 @@
 }
 
 - (void)testAutocreatedExtensionMemoryLeaks {
-  GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
 
   // Test for memory leaks with autocreated extensions.
   TestAllExtensions *message;
@@ -1729,7 +1732,8 @@
 }
 
 - (void)testSetExtensionWithAutocreatedValue {
-  GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
 
   TestAllExtensions *message;
   @autoreleasepool {
@@ -1814,9 +1818,9 @@
 }
 
 - (void)testEnumDescriptorFromExtensionDescriptor {
-  GPBExtensionField *extField = [UnittestRoot optionalForeignEnumExtension];
-  GPBExtensionDescriptor *extDescriptor = extField.descriptor;
-  XCTAssertEqual(extDescriptor.type, GPBTypeEnum);
+  GPBExtensionDescriptor *extDescriptor =
+      [UnittestRoot optionalForeignEnumExtension];
+  XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum);
   GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor;
   GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor();
   XCTAssertEqualObjects(enumDescriptor, expectedDescriptor);
@@ -1925,11 +1929,4 @@
                  EnumTestMsg_MyEnum_NegTwo);
 }
 
-- (void)testMutableNameManagling {
-  // These basically confirm that all the expected name mangling happened by not
-  // having compile errors.
-
-  // TODO(thomasvl): Write these, see unittest_name_mangling.proto.
-}
-
 @end
diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h
index 6ae68c3..44c8084 100644
--- a/objectivec/Tests/GPBTestUtilities.h
+++ b/objectivec/Tests/GPBTestUtilities.h
@@ -35,6 +35,8 @@
 @class TestMap;
 @class TestPackedTypes;
 @class TestPackedExtensions;
+@class TestUnpackedTypes;
+@class TestUnpackedExtensions;
 @class GPBExtensionRegistry;
 
 
@@ -55,8 +57,12 @@
            repeatedCount:(uint32_t)count;
 - (void)setPackedFields:(TestPackedTypes *)message
           repeatedCount:(uint32_t)count;
+- (void)setUnpackedFields:(TestUnpackedTypes *)message
+            repeatedCount:(uint32_t)count;
 - (void)setPackedExtensions:(TestPackedExtensions *)message
               repeatedCount:(uint32_t)count;
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
+              repeatedCount:(uint32_t)count;
 - (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count;
 
 - (TestAllTypes *)allSetRepeatedCount:(uint32_t)count;
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
index 6058dfc..3d85c74 100644
--- a/objectivec/Tests/GPBTestUtilities.m
+++ b/objectivec/Tests/GPBTestUtilities.m
@@ -599,6 +599,33 @@
   XCTAssertEqual(count, message.repeatedStringPieceArray.count);
   XCTAssertEqual(count, message.repeatedCordArray.count);
 
+  XCTAssertEqual(count, message.repeatedInt32Array_Count);
+  XCTAssertEqual(count, message.repeatedInt64Array_Count);
+  XCTAssertEqual(count, message.repeatedUint32Array_Count);
+  XCTAssertEqual(count, message.repeatedUint64Array_Count);
+  XCTAssertEqual(count, message.repeatedSint32Array_Count);
+  XCTAssertEqual(count, message.repeatedSint64Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedFloatArray_Count);
+  XCTAssertEqual(count, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(count, message.repeatedBoolArray_Count);
+  XCTAssertEqual(count, message.repeatedStringArray_Count);
+  XCTAssertEqual(count, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(count, message.repeatedCordArray_Count);
+
   for (uint32_t i = 0; i < count; ++i) {
     XCTAssertEqual((int)(201 + i * 100),
                    [message.repeatedInt32Array valueAtIndex:i]);
@@ -1097,6 +1124,72 @@
   }
 }
 
+- (void)setAllTestPackedFields:(TestPackedTypes *)message {
+  // Must match -setAllTestUnpackedFields:
+  [message.packedInt32Array addValue:101];
+  [message.packedInt64Array addValue:102];
+  [message.packedUint32Array addValue:103];
+  [message.packedUint64Array addValue:104];
+  [message.packedSint32Array addValue:105];
+  [message.packedSint64Array addValue:106];
+  [message.packedFixed32Array addValue:107];
+  [message.packedFixed64Array addValue:108];
+  [message.packedSfixed32Array addValue:109];
+  [message.packedSfixed64Array addValue:110];
+  [message.packedFloatArray addValue:111.f];
+  [message.packedDoubleArray addValue:112.];
+  [message.packedBoolArray addValue:YES];
+  [message.packedEnumArray addValue:ForeignEnum_ForeignBar];
+
+  [message.packedInt32Array addValue:201];
+  [message.packedInt64Array addValue:302];
+  [message.packedUint32Array addValue:203];
+  [message.packedUint64Array addValue:204];
+  [message.packedSint32Array addValue:205];
+  [message.packedSint64Array addValue:206];
+  [message.packedFixed32Array addValue:207];
+  [message.packedFixed64Array addValue:208];
+  [message.packedSfixed32Array addValue:209];
+  [message.packedSfixed64Array addValue:210];
+  [message.packedFloatArray addValue:211.f];
+  [message.packedDoubleArray addValue:212.];
+  [message.packedBoolArray addValue:NO];
+  [message.packedEnumArray addValue:ForeignEnum_ForeignBaz];
+}
+
+- (void)setAllTestUnpackedFields:(TestUnpackedTypes *)message {
+  // Must match -setAllTestPackedFields:
+  [message.unpackedInt32Array addValue:101];
+  [message.unpackedInt64Array addValue:102];
+  [message.unpackedUint32Array addValue:103];
+  [message.unpackedUint64Array addValue:104];
+  [message.unpackedSint32Array addValue:105];
+  [message.unpackedSint64Array addValue:106];
+  [message.unpackedFixed32Array addValue:107];
+  [message.unpackedFixed64Array addValue:108];
+  [message.unpackedSfixed32Array addValue:109];
+  [message.unpackedSfixed64Array addValue:110];
+  [message.unpackedFloatArray addValue:111.f];
+  [message.unpackedDoubleArray addValue:112.];
+  [message.unpackedBoolArray addValue:YES];
+  [message.unpackedEnumArray addValue:ForeignEnum_ForeignBar];
+
+  [message.unpackedInt32Array addValue:201];
+  [message.unpackedInt64Array addValue:302];
+  [message.unpackedUint32Array addValue:203];
+  [message.unpackedUint64Array addValue:204];
+  [message.unpackedSint32Array addValue:205];
+  [message.unpackedSint64Array addValue:206];
+  [message.unpackedFixed32Array addValue:207];
+  [message.unpackedFixed64Array addValue:208];
+  [message.unpackedSfixed32Array addValue:209];
+  [message.unpackedSfixed64Array addValue:210];
+  [message.unpackedFloatArray addValue:211.f];
+  [message.unpackedDoubleArray addValue:212.];
+  [message.unpackedBoolArray addValue:NO];
+  [message.unpackedEnumArray addValue:ForeignEnum_ForeignBaz];
+}
+
 - (GPBExtensionRegistry *)extensionRegistry {
   return [UnittestRoot extensionRegistry];
 }
@@ -1189,6 +1282,7 @@
   XCTAssertEqualObjects(message.optionalCord, @"");
 
   // Repeated fields are empty.
+
   XCTAssertEqual(0U, message.repeatedInt32Array.count);
   XCTAssertEqual(0U, message.repeatedInt64Array.count);
   XCTAssertEqual(0U, message.repeatedUint32Array.count);
@@ -1216,6 +1310,33 @@
   XCTAssertEqual(0U, message.repeatedStringPieceArray.count);
   XCTAssertEqual(0U, message.repeatedCordArray.count);
 
+  XCTAssertEqual(0U, message.repeatedInt32Array_Count);
+  XCTAssertEqual(0U, message.repeatedInt64Array_Count);
+  XCTAssertEqual(0U, message.repeatedUint32Array_Count);
+  XCTAssertEqual(0U, message.repeatedUint64Array_Count);
+  XCTAssertEqual(0U, message.repeatedSint32Array_Count);
+  XCTAssertEqual(0U, message.repeatedSint64Array_Count);
+  XCTAssertEqual(0U, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(0U, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(0U, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(0U, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(0U, message.repeatedFloatArray_Count);
+  XCTAssertEqual(0U, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(0U, message.repeatedBoolArray_Count);
+  XCTAssertEqual(0U, message.repeatedStringArray_Count);
+  XCTAssertEqual(0U, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(0U, message.repeatedGroupArray_Count);
+  XCTAssertEqual(0U, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(0U, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(0U, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(0U, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(0U, message.repeatedCordArray_Count);
+
   // hasBlah() should also be NO for all default fields.
   XCTAssertFalse(message.hasDefaultInt32);
   XCTAssertFalse(message.hasDefaultInt64);
@@ -1474,6 +1595,7 @@
   // ModifyRepeatedFields only sets the second repeated element of each
   // field.  In addition to verifying this, we also verify that the first
   // element and size were *not* modified.
+
   XCTAssertEqual(count, message.repeatedInt32Array.count);
   XCTAssertEqual(count, message.repeatedInt64Array.count);
   XCTAssertEqual(count, message.repeatedUint32Array.count);
@@ -1501,6 +1623,33 @@
   XCTAssertEqual(count, message.repeatedStringPieceArray.count);
   XCTAssertEqual(count, message.repeatedCordArray.count);
 
+  XCTAssertEqual(count, message.repeatedInt32Array_Count);
+  XCTAssertEqual(count, message.repeatedInt64Array_Count);
+  XCTAssertEqual(count, message.repeatedUint32Array_Count);
+  XCTAssertEqual(count, message.repeatedUint64Array_Count);
+  XCTAssertEqual(count, message.repeatedSint32Array_Count);
+  XCTAssertEqual(count, message.repeatedSint64Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedFloatArray_Count);
+  XCTAssertEqual(count, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(count, message.repeatedBoolArray_Count);
+  XCTAssertEqual(count, message.repeatedStringArray_Count);
+  XCTAssertEqual(count, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(count, message.repeatedCordArray_Count);
+
   XCTAssertEqual(201, [message.repeatedInt32Array valueAtIndex:0]);
   XCTAssertEqual(202LL, [message.repeatedInt64Array valueAtIndex:0]);
   XCTAssertEqual(203U, [message.repeatedUint32Array valueAtIndex:0]);
@@ -1563,105 +1712,101 @@
 
 - (void)setPackedFields:(TestPackedTypes *)message
           repeatedCount:(uint32_t)count {
-  {
-    GPBInt32Array *scratch = [GPBInt32Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:601 + i * 100];
-    }
-    [message setPackedInt32Array:scratch];
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedInt32Array addValue:601 + i * 100];
   }
-  {
-    GPBInt64Array *scratch = [GPBInt64Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:602 + i * 100];
-    }
-    [message setPackedInt64Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedInt64Array addValue:602 + i * 100];
   }
-  {
-    GPBUInt32Array *scratch = [GPBUInt32Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:603 + i * 100];
-    }
-    [message setPackedUint32Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedUint32Array addValue:603 + i * 100];
   }
-  {
-    GPBUInt64Array *scratch = [GPBUInt64Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:604 + i * 100];
-    }
-    [message setPackedUint64Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedUint64Array addValue:604 + i * 100];
   }
-  {
-    GPBInt32Array *scratch = [GPBInt32Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:605 + i * 100];
-    }
-    [message setPackedSint32Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSint32Array addValue:605 + i * 100];
   }
-  {
-    GPBInt64Array *scratch = [GPBInt64Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:606 + i * 100];
-    }
-    [message setPackedSint64Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSint64Array addValue:606 + i * 100];
   }
-  {
-    GPBUInt32Array *scratch = [GPBUInt32Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:607 + i * 100];
-    }
-    [message setPackedFixed32Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFixed32Array addValue:607 + i * 100];
   }
-  {
-    GPBUInt64Array *scratch = [GPBUInt64Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:608 + i * 100];
-    }
-    [message setPackedFixed64Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFixed64Array addValue:608 + i * 100];
   }
-  {
-    GPBInt32Array *scratch = [GPBInt32Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:609 + i * 100];
-    }
-    [message setPackedSfixed32Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSfixed32Array addValue:609 + i * 100];
   }
-  {
-    GPBInt64Array *scratch = [GPBInt64Array array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:610 + i * 100];
-    }
-    [message setPackedSfixed64Array:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSfixed64Array addValue:610 + i * 100];
   }
-  {
-    GPBFloatArray *scratch = [GPBFloatArray array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:611 + i * 100];
-    }
-    [message setPackedFloatArray:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFloatArray addValue:611 + i * 100];
   }
-  {
-    GPBDoubleArray *scratch = [GPBDoubleArray array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:612 + i * 100];
-    }
-    [message setPackedDoubleArray:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedDoubleArray addValue:612 + i * 100];
   }
-  {
-    GPBBoolArray *scratch = [GPBBoolArray array];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:(i % 2) ? YES : NO];
-    }
-    [message setPackedBoolArray:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedBoolArray addValue:(i % 2) ? YES : NO];
   }
-  {
-    GPBEnumArray *scratch =
-        [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
-    for (uint32_t i = 0; i < count; ++i) {
-      [scratch
-          addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
-    }
-    [message setPackedEnumArray:scratch];
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedEnumArray
+        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+  }
+}
+
+- (void)setUnpackedFields:(TestUnpackedTypes *)message
+            repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedInt32Array addValue:601 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedInt64Array addValue:602 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedUint32Array addValue:603 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedUint64Array addValue:604 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSint32Array addValue:605 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSint64Array addValue:606 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFixed32Array addValue:607 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFixed64Array addValue:608 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSfixed32Array addValue:609 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSfixed64Array addValue:610 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFloatArray addValue:611 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedDoubleArray addValue:612 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedBoolArray addValue:(i % 2) ? YES : NO];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedEnumArray
+        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
   }
 }
 
@@ -1708,6 +1853,9 @@
 
 - (void)setPackedExtensions:(TestPackedExtensions *)message
               repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
   for (uint32_t i = 0; i < count; i++) {
     [message addExtension:[UnittestRoot packedInt32Extension]
                     value:@(601 + i * 100)];
@@ -1741,6 +1889,44 @@
   }
 }
 
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
+                repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; i++) {
+    [message addExtension:[UnittestRoot unpackedInt32Extension]
+                    value:@(601 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedInt64Extension]
+                    value:@(602 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint32Extension]
+                    value:@(603 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint64Extension]
+                    value:@(604 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint32Extension]
+                    value:@(605 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint64Extension]
+                    value:@(606 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed32Extension]
+                    value:@(607 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed64Extension]
+                    value:@(608 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed32Extension]
+                    value:@(609 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed64Extension]
+                    value:@(610 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFloatExtension]
+                    value:@(611 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedDoubleExtension]
+                    value:@(612 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedBoolExtension]
+                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot unpackedEnumExtension]
+                    value:@((i % 2) ? ForeignEnum_ForeignBar
+                         : ForeignEnum_ForeignBaz)];
+  }
+}
+
 - (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
                     repeatedCount:(uint32_t)count{
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]);
@@ -1884,6 +2070,34 @@
   XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]);
   XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]);
 
+  XCTAssertEqualObjects(@(message.repeatedInt32Array_Count), [message valueForKey:@"repeatedInt32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedInt64Array_Count), [message valueForKey:@"repeatedInt64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint32Array_Count), [message valueForKey:@"repeatedUint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint64Array_Count), [message valueForKey:@"repeatedUint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint32Array_Count), [message valueForKey:@"repeatedSint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint64Array_Count), [message valueForKey:@"repeatedSint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count), [message valueForKey:@"repeatedFixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count), [message valueForKey:@"repeatedFixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count), [message valueForKey:@"repeatedSfixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count), [message valueForKey:@"repeatedSfixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFloatArray_Count), [message valueForKey:@"repeatedFloatArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count), [message valueForKey:@"repeatedDoubleArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBoolArray_Count), [message valueForKey:@"repeatedBoolArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedStringArray_Count), [message valueForKey:@"repeatedStringArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBytesArray_Count), [message valueForKey:@"repeatedBytesArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedGroupArray_Count), [message valueForKey:@"repeatedGroupArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count), [message valueForKey:@"repeatedNestedMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count), [message valueForKey:@"repeatedForeignMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count), [message valueForKey:@"repeatedImportMessageArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count), [message valueForKey:@"repeatedNestedEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count), [message valueForKey:@"repeatedForeignEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count), [message valueForKey:@"repeatedImportEnumArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count), [message valueForKey:@"repeatedStringPieceArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedCordArray_Count), [message valueForKey:@"repeatedCordArray_Count"]);
+
   // -----------------------------------------------------------------
 
   XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES);
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
index 2c271bf..0a3fc58 100644
--- a/objectivec/Tests/GPBUnittestProtos.m
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -40,16 +40,15 @@
 #import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m"
 #import "google/protobuf/UnittestEmpty.pbobjc.m"
 #import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m"
-#import "google/protobuf/UnittestFilter.pbobjc.m"
 #import "google/protobuf/UnittestImport.pbobjc.m"
 #import "google/protobuf/UnittestImportLite.pbobjc.m"
 #import "google/protobuf/UnittestImportPublic.pbobjc.m"
 #import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
 #import "google/protobuf/UnittestLite.pbobjc.m"
 #import "google/protobuf/UnittestMset.pbobjc.m"
-#import "google/protobuf/UnittestNameMangling.pbobjc.m"
 #import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
 #import "google/protobuf/UnittestObjc.pbobjc.m"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.m"
 #import "google/protobuf/UnittestOptimizeFor.pbobjc.m"
 #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
 #import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m
index 491bba9..01217ca 100644
--- a/objectivec/Tests/GPBUnknownFieldSetTest.m
+++ b/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -30,7 +30,7 @@
 
 #import "GPBTestUtilities.h"
 
-#import "GPBField_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
 #import "google/protobuf/Unittest.pbobjc.h"
 
@@ -60,7 +60,7 @@
   unknownFields_ = emptyMessage_.unknownFields;
 }
 
-- (GPBField*)getField:(int32_t)number {
+- (GPBUnknownField *)getField:(int32_t)number {
   return [unknownFields_ getField:number];
 }
 
@@ -75,17 +75,17 @@
   [unknownFields_ getTags:tags];
   for (NSUInteger i = 0; i < count; ++i) {
     int32_t tag = tags[i];
-    GPBField* field = [unknownFields_ getField:tag];
+    GPBUnknownField* field = [unknownFields_ getField:tag];
     if (field.varintList.count == 0) {
       // Original field is not a varint, so use a varint.
-      GPBField* varintField =
-          [[[GPBField alloc] initWithNumber:tag] autorelease];
+      GPBUnknownField* varintField =
+          [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
       [varintField addVarint:1];
       [bizarroFields addField:varintField];
     } else {
       // Original field *is* a varint, so use something else.
-      GPBField* fixed32Field =
-          [[[GPBField alloc] initWithNumber:tag] autorelease];
+      GPBUnknownField* fixed32Field =
+          [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
       [fixed32Field addFixed32:1];
       [bizarroFields addField:fixed32Field];
     }
@@ -110,34 +110,34 @@
 
 - (void)testMergeFrom {
   GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
-  GPBField* field = [[[GPBField alloc] initWithNumber:2] autorelease];
+  GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
   [field addVarint:2];
   [set1 addField:field];
-  field = [[[GPBField alloc] initWithNumber:3] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
   [field addVarint:4];
   [set1 addField:field];
 
   GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
-  field = [[[GPBField alloc] initWithNumber:1] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
   [field addVarint:1];
   [set2 addField:field];
-  field = [[[GPBField alloc] initWithNumber:3] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
   [field addVarint:3];
   [set2 addField:field];
 
   GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease];
-  field = [[[GPBField alloc] initWithNumber:1] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
   [field addVarint:1];
   [set3 addField:field];
-  field = [[[GPBField alloc] initWithNumber:3] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
   [field addVarint:4];
   [set3 addField:field];
 
   GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease];
-  field = [[[GPBField alloc] initWithNumber:2] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
   [field addVarint:2];
   [set4 addField:field];
-  field = [[[GPBField alloc] initWithNumber:3] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
   [field addVarint:3];
   [set4 addField:field];
 
@@ -162,7 +162,7 @@
 }
 
 - (void)testClearMessage {
-  TestEmptyMessage* message = [TestEmptyMessage message];
+  TestEmptyMessage *message = [TestEmptyMessage message];
   [message mergeFrom:emptyMessage_];
   [message clear];
   XCTAssertEqual(message.serializedSize, (size_t)0);
@@ -170,8 +170,9 @@
 
 - (void)testParseKnownAndUnknown {
   // Test mixing known and unknown fields when parsing.
-  GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
-  GPBField* field = [[[GPBField alloc] initWithNumber:123456] autorelease];
+  GPBUnknownFieldSet *fields = [[unknownFields_ copy] autorelease];
+  GPBUnknownField *field =
+    [[[GPBUnknownField alloc] initWithNumber:123456] autorelease];
   [field addVarint:654321];
   [fields addField:field];
 
@@ -181,7 +182,7 @@
   [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount];
   XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1);
 
-  GPBField* field2 = [destination.unknownFields getField:123456];
+  GPBUnknownField* field2 = [destination.unknownFields getField:123456];
   XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
   XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]);
 }
@@ -230,7 +231,7 @@
 
 - (void)testLargeVarint {
   GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
-  GPBField* field = [[[GPBField alloc] initWithNumber:1] autorelease];
+  GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
   [field addVarint:0x7FFFFFFFFFFFFFFFL];
   [fields addField:field];
 
@@ -238,19 +239,19 @@
 
   GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease];
   [parsed mergeFromData:data];
-  GPBField* field2 = [parsed getField:1];
+  GPBUnknownField* field2 = [parsed getField:1];
   XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
   XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
 }
 
 - (void)testMergingFields {
-  GPBField* field1 = [[[GPBField alloc] initWithNumber:1] autorelease];
+  GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
   [field1 addVarint:1];
   [field1 addFixed32:2];
   [field1 addFixed64:3];
   [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]];
   [field1 addGroup:[[unknownFields_ copy] autorelease]];
-  GPBField* field2 = [[[GPBField alloc] initWithNumber:2] autorelease];
+  GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
   [field2 mergeFromField:field1];
   XCTAssertEqualObjects(field1, field2);
 }
diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m
index 02de019..ba1fc27 100644
--- a/objectivec/Tests/GPBUtilitiesTests.m
+++ b/objectivec/Tests/GPBUtilitiesTests.m
@@ -47,141 +47,6 @@
 @interface UtilitiesTests : GPBTestCase
 @end
 
-// Support code for testing
-typedef struct {
-  uint32_t _has_storage_[1];
-  BOOL aBool;
-  int32_t aInt32;
-  uint32_t aUInt32;
-  int64_t aInt64;
-  uint64_t aUInt64;
-  float aFloat;
-  double aDouble;
-  id aObject;
-  BOOL _hasTest;
-  BOOL stopper;
-  BOOL shouldNotBeCounted;
-  GPBInt32Array *anArray;
-} ApplyFunctionsTest_Storage;
-
-@interface ApplyFunctionsTest : GPBMessage
-@property(nonatomic, readwrite) BOOL aBool;
-@property(nonatomic, readwrite) int32_t aInt32;
-@property(nonatomic, readwrite) uint32_t aUInt32;
-@property(nonatomic, readwrite) int64_t aInt64;
-@property(nonatomic, readwrite) uint64_t aUInt64;
-@property(nonatomic, readwrite) float aFloat;
-@property(nonatomic, readwrite) double aDouble;
-@property(nonatomic, readwrite, retain) id aObject;
-@property(nonatomic, readwrite) BOOL _hasTest;
-@property(nonatomic, readwrite) BOOL stopper;
-@property(nonatomic, readwrite) BOOL shouldNotBeCounted;
-@property(nonatomic, readwrite, retain) GPBInt32Array *anArray;
-@end
-
-@implementation ApplyFunctionsTest
-
-@dynamic aBool, aInt32, aUInt32, aInt64, aUInt64, aFloat, aDouble, aObject;
-@dynamic _hasTest, stopper, shouldNotBeCounted, anArray;
-
-+ (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
-  if (!descriptor) {
-    static GPBMessageFieldDescription fields[] = {
-#define FIELD_ENTRY(NAME, INDEX)                                 \
-  {                                                              \
-    .name = "a" #NAME, .hasIndex = INDEX, .type = GPBType##NAME, \
-    .offset = offsetof(ApplyFunctionsTest_Storage, a##NAME),     \
-  }
-        FIELD_ENTRY(Bool, 1),
-        FIELD_ENTRY(Int32, 2),
-        FIELD_ENTRY(UInt32, 3),
-        FIELD_ENTRY(Int64, 4),
-        FIELD_ENTRY(UInt64, 5),
-        FIELD_ENTRY(Float, 6),
-        FIELD_ENTRY(Double, 7),
-#undef FIELD_ENTRY
-        {
-         .name = "aObject",
-         .type = GPBTypeString,
-         .hasIndex = 8,
-         .offset = offsetof(ApplyFunctionsTest_Storage, aObject),
-        },
-        {
-         .name = "stopper",
-         .type = GPBTypeBool,
-         .hasIndex = 9,
-         .offset = offsetof(ApplyFunctionsTest_Storage, stopper),
-        },
-        {
-         .name = "shouldNotBeCounted",
-         .type = GPBTypeBool,
-         .hasIndex = 10,
-         .offset = offsetof(ApplyFunctionsTest_Storage, shouldNotBeCounted),
-        },
-        {
-         .name = "anArray",
-         .type = GPBTypeInt32,
-         .hasIndex = 11,
-         .flags = GPBFieldRepeated,
-         .offset = offsetof(ApplyFunctionsTest_Storage, anArray),
-        },
-    };
-    descriptor = [GPBDescriptor
-        allocDescriptorForClass:[self class]
-                      rootClass:Nil
-                           file:nil
-                         fields:fields
-                     fieldCount:sizeof(fields) /
-                                sizeof(GPBMessageFieldDescription)
-                         oneofs:NULL
-                     oneofCount:0
-                          enums:NULL
-                      enumCount:0
-                         ranges:NULL
-                     rangeCount:0
-                    storageSize:sizeof(ApplyFunctionsTest_Storage)
-                     wireFormat:NO];
-  }
-  return descriptor;
-}
-
-@end
-
-typedef struct {
-  int calledBool;
-  int calledInt32;
-  int calledUInt32;
-  int calledInt64;
-  int calledUInt64;
-  int calledFloat;
-  int calledDouble;
-  int calledObject;
-  int hitCount;
-} TestApplyFunctionsContext;
-
-// Really, who needs templates?
-// Macro for testing apply functions. Declares a variety of different functions
-// base on |NAME|.
-#define TEST_APPLY_FUNCTIONS_FUNC(NAME)                          \
-  static BOOL TestApplyFunction##NAME(GPBFieldDescriptor *field, \
-                                      void *voidContext) {       \
-    TestApplyFunctionsContext *context = voidContext;            \
-    if (field->getSel_ == sel_getUid("stopper")) return NO;      \
-    context->called##NAME += 1;                                  \
-    context->hitCount += 1;                                      \
-    return YES;                                                  \
-  }
-
-TEST_APPLY_FUNCTIONS_FUNC(Bool)
-TEST_APPLY_FUNCTIONS_FUNC(Int32)
-TEST_APPLY_FUNCTIONS_FUNC(UInt32)
-TEST_APPLY_FUNCTIONS_FUNC(Int64)
-TEST_APPLY_FUNCTIONS_FUNC(UInt64)
-TEST_APPLY_FUNCTIONS_FUNC(Float)
-TEST_APPLY_FUNCTIONS_FUNC(Double)
-TEST_APPLY_FUNCTIONS_FUNC(Object)
-
 @implementation UtilitiesTests
 
 - (void)testRightShiftFunctions {
@@ -194,61 +59,6 @@
   XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL);
 }
 
-- (void)testMutability {
-  ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
-  XCTAssertEqual(0, [foo_message aInt32]);
-  [foo_message setAInt32:100];
-  XCTAssertEqual(100, [foo_message aInt32]);
-}
-
-- (void)testSerializedSize {
-  ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
-  [foo_message setAInt32:100];
-  size_t size1 = [foo_message serializedSize];
-  [foo_message setAInt64:100];
-  size_t size2 = [foo_message serializedSize];
-
-  // Intentionally doing a pointer comparison.
-  XCTAssertNotEqual(size1, size2);
-}
-
-- (void)testCopying {
-  ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
-  [foo_message setAInt32:100];
-  [foo_message setAObject:@"Happy"];
-  ApplyFunctionsTest *foo = [[foo_message copy] autorelease];
-  XCTAssertNotEqual(foo, foo_message);  // Pointer comparision
-  XCTAssertEqualObjects(foo, foo_message);
-}
-
-- (void)testApplyFunctions {
-  // Covers ApplyFunctionsToProtoVariables and
-  // ApplyFunctionsBasedOnEncodingType.
-  // This test depends on the layout of the ivars to be in the order
-  // declared in the interface. If this is not true, it will fail and will
-  // need to be rewritten to accomodate.
-  TestApplyFunctionsContext context;
-  memset(&context, 0, sizeof(context));
-  GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(TestApplyFunction);
-  ApplyFunctionsTest *msg = [ApplyFunctionsTest message];
-  GPBApplyFunctionsToMessageFields(&foo, msg, &context);
-
-  // Only eight vars should be set.
-  // "stopper" should cause the loop to quit so it and shouldNotBeCounted should
-  // not be counted.
-  // "_hasTest" should be skipped over.
-  // Each of the vars should only be set once.
-  XCTAssertEqual(context.hitCount, 8);
-  XCTAssertEqual(context.calledBool, 1);
-  XCTAssertEqual(context.calledInt32, 1);
-  XCTAssertEqual(context.calledUInt32, 1);
-  XCTAssertEqual(context.calledInt64, 1);
-  XCTAssertEqual(context.calledUInt64, 1);
-  XCTAssertEqual(context.calledFloat, 1);
-  XCTAssertEqual(context.calledDouble, 1);
-  XCTAssertEqual(context.calledObject, 1);
-}
-
 - (void)testGPBDecodeTextFormatName {
   uint8_t decodeData[] = {
     0x6,
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
index fc5c4bd..d722d7b 100644
--- a/objectivec/Tests/GPBWireFormatTests.m
+++ b/objectivec/Tests/GPBWireFormatTests.m
@@ -32,7 +32,7 @@
 
 #import "GPBCodedInputStream.h"
 #import "GPBMessage_PackagePrivate.h"
-#import "GPBField_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
 #import "google/protobuf/Unittest.pbobjc.h"
 #import "google/protobuf/UnittestMset.pbobjc.h"
 
@@ -143,8 +143,8 @@
       setI:123];
   [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]]
       setStr:@"foo"];
-  GPBField* unknownField =
-      [[[GPBField alloc] initWithNumber:kUnknownTypeId] autorelease];
+  GPBUnknownField* unknownField =
+      [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease];
   [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
   GPBUnknownFieldSet* unknownFieldSet =
       [[[GPBUnknownFieldSet alloc] init] autorelease];
@@ -159,9 +159,9 @@
   XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
 
   XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
-  XCTAssertEqual([raw.itemArray[0] typeId],
+  XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId],
                  [TestMessageSetExtension1 messageSetExtension].fieldNumber);
-  XCTAssertEqual([raw.itemArray[1] typeId],
+  XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId],
                  [TestMessageSetExtension2 messageSetExtension].fieldNumber);
   XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
 
@@ -227,7 +227,7 @@
       @"foo");
 
   XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
-  GPBField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
+  GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
   XCTAssertNotNil(unknownField);
   XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
   XCTAssertEqualObjects(unknownField.lengthDelimitedList[0],
diff --git a/objectivec/Tests/unittest_filter.proto b/objectivec/Tests/unittest_filter.proto
deleted file mode 100644
index 1398dfc..0000000
--- a/objectivec/Tests/unittest_filter.proto
+++ /dev/null
@@ -1,71 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2013 Google Inc.  All rights reserved.
-//
-// 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.
-
-syntax = "proto2";
-
-package protobuf_unittest;
-
-
-message Keep {
-}
-
-message Remove {
-}
-
-message RemoveJustKidding {
-}
-
-message Other {
-  optional Keep a = 1;
-  optional Remove b = 2;
-}
-
-enum RemoveEnum {
-  RemoveValue = 1;
-}
-
-enum KeepEnum {
-  KeepValue = 1;
-}
-
-message RemoveEnumMessage {
-  enum KeepEnumInside {
-    KeepValue = 1;
-  }
-
-  enum RemoveEnumInside {
-    RemoveValue = 1;
-  }
-
-  message KeepNestedInside {
-  }
-
-  message RemoveNestedInside {
-  }
-}
diff --git a/objectivec/Tests/unittest_name_mangling.proto b/objectivec/Tests/unittest_name_mangling.proto
deleted file mode 100644
index aadad6d..0000000
--- a/objectivec/Tests/unittest_name_mangling.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc.  All rights reserved.
-//
-// 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.
-
-syntax = "proto2";
-
-option objc_class_prefix = "ABC";
-
-package protobuf_unittest;
-
-// TODO(thomasvl): Add tests for the special cases in name mangling.
-
diff --git a/objectivec/GPBField_PackagePrivate.h b/objectivec/Tests/unittest_objc_startup.proto
similarity index 79%
copy from objectivec/GPBField_PackagePrivate.h
copy to objectivec/Tests/unittest_objc_startup.proto
index 73c1fa8..aee7bd5 100644
--- a/objectivec/GPBField_PackagePrivate.h
+++ b/objectivec/Tests/unittest_objc_startup.proto
@@ -28,22 +28,22 @@
 // (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 <Foundation/Foundation.h>
+syntax = "proto2";
 
-#import "GPBField.h"
+package protobuf_objc_unittest;
 
-@class GPBCodedOutputStream;
+message TestObjCStartupMessage {
+  extensions 1 to max;
+}
 
-@interface GPBField ()
+extend TestObjCStartupMessage {
+  // Singular
+  optional    int32 optional_int32_extension    = 1;
+  repeated    int32 repeated_int32_extension    = 2;
+}
 
-- (instancetype)initWithNumber:(int32_t)number;
-
-- (void)writeToOutput:(GPBCodedOutputStream *)output;
-- (size_t)serializedSize;
-
-- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output;
-- (size_t)serializedSizeAsMessageSetExtension;
-
-- (void)mergeFromField:(GPBField *)other;
-
-@end
+message TestObjCStartupNested {
+  extend TestObjCStartupMessage {
+    optional string nested_string_extension = 3;
+  }
+}
diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m
index 4db73cb..b41102a 100644
--- a/objectivec/google/protobuf/Any.pbobjc.m
+++ b/objectivec/google/protobuf/Any.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBAnyRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -29,16 +32,16 @@
 @dynamic typeURL;
 @dynamic value;
 
-typedef struct GPBAny_Storage {
+typedef struct GPBAny__storage_ {
   uint32_t _has_storage_[1];
   NSString *typeURL;
   NSData *value;
-} GPBAny_Storage;
+} GPBAny__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -46,10 +49,10 @@
         .number = GPBAny_FieldNumber_TypeURL,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBAny_Storage, typeURL),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBAny__storage_, typeURL),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -57,10 +60,10 @@
         .number = GPBAny_FieldNumber_Value,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeData,
-        .offset = offsetof(GPBAny_Storage, value),
+        .dataType = GPBDataTypeBytes,
+        .offset = offsetof(GPBAny__storage_, value),
         .defaultValue.valueData = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
@@ -69,20 +72,23 @@
 #else
     static const char *extraTextFormatInfo = "\001\001\004\241!!\000";
 #endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBAny class]
-                                              rootClass:[GPBAnyRoot class]
-                                                   file:GPBAnyRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBAny_Storage)
-                                             wireFormat:NO
-                                    extraTextFormatInfo:extraTextFormatInfo];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBAny class]
+                                     rootClass:[GPBAnyRoot class]
+                                          file:GPBAnyRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBAny__storage_)
+                                    wireFormat:NO
+                           extraTextFormatInfo:extraTextFormatInfo];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h
index 9e6fc85..061347b 100644
--- a/objectivec/google/protobuf/Api.pbobjc.h
+++ b/objectivec/google/protobuf/Api.pbobjc.h
@@ -45,10 +45,12 @@
 // The methods of this api, in unspecified order.
 // |methodsArray| contains |GPBMethod|
 @property(nonatomic, readwrite, strong) NSMutableArray *methodsArray;
+@property(nonatomic, readonly) NSUInteger methodsArray_Count;
 
 // Any metadata attached to the API.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 // A version string for this api. If specified, must have the form
 // `major-version.minor-version`, as in `1.10`. If the minor version
@@ -113,6 +115,7 @@
 // Any metadata attached to the method.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 @end
 
diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m
index 9416860..c2be94a 100644
--- a/objectivec/google/protobuf/Api.pbobjc.m
+++ b/objectivec/google/protobuf/Api.pbobjc.m
@@ -16,10 +16,8 @@
   // about thread safety and initialization of registry.
   static GPBExtensionRegistry* registry = nil;
   if (!registry) {
+    GPBDebugCheckRuntimeVersion();
     registry = [[GPBExtensionRegistry alloc] init];
-    static GPBExtensionDescription descriptions[] = {
-    };
-    #pragma unused (descriptions)
     [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
     [registry addExtensions:[GPBTypeRoot extensionRegistry]];
   }
@@ -28,11 +26,14 @@
 
 @end
 
+#pragma mark - GPBApiRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -44,24 +45,24 @@
 @implementation GPBApi
 
 @dynamic name;
-@dynamic methodsArray;
-@dynamic optionsArray;
+@dynamic methodsArray, methodsArray_Count;
+@dynamic optionsArray, optionsArray_Count;
 @dynamic version;
 @dynamic hasSourceContext, sourceContext;
 
-typedef struct GPBApi_Storage {
+typedef struct GPBApi__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *methodsArray;
   NSMutableArray *optionsArray;
   NSString *version;
   GPBSourceContext *sourceContext;
-} GPBApi_Storage;
+} GPBApi__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -69,10 +70,10 @@
         .number = GPBApi_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBApi_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBApi__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -80,10 +81,10 @@
         .number = GPBApi_FieldNumber_MethodsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBApi_Storage, methodsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBApi__storage_, methodsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBMethod),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod),
         .fieldOptions = NULL,
       },
       {
@@ -91,10 +92,10 @@
         .number = GPBApi_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBApi_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBApi__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
       {
@@ -102,10 +103,10 @@
         .number = GPBApi_FieldNumber_Version,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBApi_Storage, version),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBApi__storage_, version),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -113,26 +114,29 @@
         .number = GPBApi_FieldNumber_SourceContext,
         .hasIndex = 4,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBApi_Storage, sourceContext),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBApi__storage_, sourceContext),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBApi class]
-                                              rootClass:[GPBApiRoot class]
-                                                   file:GPBApiRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBApi_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBApi class]
+                                     rootClass:[GPBApiRoot class]
+                                          file:GPBApiRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBApi__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -148,9 +152,9 @@
 @dynamic requestStreaming;
 @dynamic responseTypeURL;
 @dynamic responseStreaming;
-@dynamic optionsArray;
+@dynamic optionsArray, optionsArray_Count;
 
-typedef struct GPBMethod_Storage {
+typedef struct GPBMethod__storage_ {
   uint32_t _has_storage_[1];
   BOOL requestStreaming;
   BOOL responseStreaming;
@@ -158,12 +162,12 @@
   NSString *requestTypeURL;
   NSString *responseTypeURL;
   NSMutableArray *optionsArray;
-} GPBMethod_Storage;
+} GPBMethod__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -171,10 +175,10 @@
         .number = GPBMethod_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethod_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethod__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -182,10 +186,10 @@
         .number = GPBMethod_FieldNumber_RequestTypeURL,
         .hasIndex = 1,
         .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethod_Storage, requestTypeURL),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethod__storage_, requestTypeURL),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -193,10 +197,10 @@
         .number = GPBMethod_FieldNumber_RequestStreaming,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMethod_Storage, requestStreaming),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMethod__storage_, requestStreaming),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -204,10 +208,10 @@
         .number = GPBMethod_FieldNumber_ResponseTypeURL,
         .hasIndex = 3,
         .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethod_Storage, responseTypeURL),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethod__storage_, responseTypeURL),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -215,10 +219,10 @@
         .number = GPBMethod_FieldNumber_ResponseStreaming,
         .hasIndex = 4,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMethod_Storage, responseStreaming),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMethod__storage_, responseStreaming),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -226,10 +230,10 @@
         .number = GPBMethod_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBMethod_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBMethod__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
     };
@@ -238,20 +242,23 @@
 #else
     static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000";
 #endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethod class]
-                                              rootClass:[GPBApiRoot class]
-                                                   file:GPBApiRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBMethod_Storage)
-                                             wireFormat:NO
-                                    extraTextFormatInfo:extraTextFormatInfo];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMethod class]
+                                     rootClass:[GPBApiRoot class]
+                                          file:GPBApiRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBMethod__storage_)
+                                    wireFormat:NO
+                           extraTextFormatInfo:extraTextFormatInfo];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h
index 5a53abb..e010653 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.h
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.h
@@ -152,6 +152,7 @@
 
 // |fileArray| contains |GPBFileDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *fileArray;
+@property(nonatomic, readonly) NSUInteger fileArray_Count;
 
 @end
 
@@ -186,26 +187,33 @@
 // Names of files imported by this file.
 // |dependencyArray| contains |NSString|
 @property(nonatomic, readwrite, strong) NSMutableArray *dependencyArray;
+@property(nonatomic, readonly) NSUInteger dependencyArray_Count;
 
 // Indexes of the public imported files in the dependency list above.
 @property(nonatomic, readwrite, strong) GPBInt32Array *publicDependencyArray;
+@property(nonatomic, readonly) NSUInteger publicDependencyArray_Count;
 
 // Indexes of the weak imported files in the dependency list.
 // For Google-internal migration only. Do not use.
 @property(nonatomic, readwrite, strong) GPBInt32Array *weakDependencyArray;
+@property(nonatomic, readonly) NSUInteger weakDependencyArray_Count;
 
 // All top-level definitions in this file.
 // |messageTypeArray| contains |GPBDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *messageTypeArray;
+@property(nonatomic, readonly) NSUInteger messageTypeArray_Count;
 
 // |enumTypeArray| contains |GPBEnumDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray;
+@property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 
 // |serviceArray| contains |GPBServiceDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *serviceArray;
+@property(nonatomic, readonly) NSUInteger serviceArray_Count;
 
 // |extensionArray| contains |GPBFieldDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *extensionArray;
+@property(nonatomic, readonly) NSUInteger extensionArray_Count;
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite, strong) GPBFileOptions *options;
@@ -247,32 +255,40 @@
 
 // |fieldArray| contains |GPBFieldDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *fieldArray;
+@property(nonatomic, readonly) NSUInteger fieldArray_Count;
 
 // |extensionArray| contains |GPBFieldDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *extensionArray;
+@property(nonatomic, readonly) NSUInteger extensionArray_Count;
 
 // |nestedTypeArray| contains |GPBDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *nestedTypeArray;
+@property(nonatomic, readonly) NSUInteger nestedTypeArray_Count;
 
 // |enumTypeArray| contains |GPBEnumDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray;
+@property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 
 // |extensionRangeArray| contains |GPBDescriptorProto_ExtensionRange|
 @property(nonatomic, readwrite, strong) NSMutableArray *extensionRangeArray;
+@property(nonatomic, readonly) NSUInteger extensionRangeArray_Count;
 
 // |oneofDeclArray| contains |GPBOneofDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *oneofDeclArray;
+@property(nonatomic, readonly) NSUInteger oneofDeclArray_Count;
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite, strong) GPBMessageOptions *options;
 
 // |reservedRangeArray| contains |GPBDescriptorProto_ReservedRange|
 @property(nonatomic, readwrite, strong) NSMutableArray *reservedRangeArray;
+@property(nonatomic, readonly) NSUInteger reservedRangeArray_Count;
 
 // Reserved field names, which may not be used by fields in the same message.
 // A given name may only be reserved once.
 // |reservedNameArray| contains |NSString|
 @property(nonatomic, readwrite, strong) NSMutableArray *reservedNameArray;
+@property(nonatomic, readonly) NSUInteger reservedNameArray_Count;
 
 @end
 
@@ -407,6 +423,7 @@
 
 // |valueArray| contains |GPBEnumValueDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *valueArray;
+@property(nonatomic, readonly) NSUInteger valueArray_Count;
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite, strong) GPBEnumOptions *options;
@@ -451,6 +468,7 @@
 
 // |methodArray| contains |GPBMethodDescriptorProto|
 @property(nonatomic, readwrite, strong) NSMutableArray *methodArray;
+@property(nonatomic, readonly) NSUInteger methodArray_Count;
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite, strong) GPBServiceOptions *options;
@@ -617,6 +635,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -693,6 +712,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -782,6 +802,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -810,6 +831,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -832,6 +854,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -854,6 +877,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -876,6 +900,7 @@
 // The parser stores options it doesn't recognize here. See above.
 // |uninterpretedOptionArray| contains |GPBUninterpretedOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 @end
 
@@ -901,6 +926,7 @@
 
 // |nameArray| contains |GPBUninterpretedOption_NamePart|
 @property(nonatomic, readwrite, strong) NSMutableArray *nameArray;
+@property(nonatomic, readonly) NSUInteger nameArray_Count;
 
 // The value of the uninterpreted option, in whatever type the tokenizer
 // identified it as during parsing. Exactly one of these should be set.
@@ -1001,6 +1027,7 @@
 //   be recorded in the future.
 // |locationArray| contains |GPBSourceCodeInfo_Location|
 @property(nonatomic, readwrite, strong) NSMutableArray *locationArray;
+@property(nonatomic, readonly) NSUInteger locationArray_Count;
 
 @end
 
@@ -1040,6 +1067,7 @@
 // this path refers to the whole field declaration (from the beginning
 // of the label to the terminating semicolon).
 @property(nonatomic, readwrite, strong) GPBInt32Array *pathArray;
+@property(nonatomic, readonly) NSUInteger pathArray_Count;
 
 // Always has exactly three or four elements: start line, start column,
 // end line (optional, otherwise assumed same as start line), end column.
@@ -1047,6 +1075,7 @@
 // and column numbers are zero-based -- typically you will want to add
 // 1 to each before displaying to a user.
 @property(nonatomic, readwrite, strong) GPBInt32Array *spanArray;
+@property(nonatomic, readonly) NSUInteger spanArray_Count;
 
 // If this SourceCodeInfo represents a complete declaration, these are any
 // comments appearing before and after the declaration which appear to be
@@ -1103,6 +1132,7 @@
 
 // |leadingDetachedCommentsArray| contains |NSString|
 @property(nonatomic, readwrite, strong) NSMutableArray *leadingDetachedCommentsArray;
+@property(nonatomic, readonly) NSUInteger leadingDetachedCommentsArray_Count;
 
 @end
 
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m
index 7f1bdd4..8c535b9 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.m
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBDescriptorRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBDescriptorRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto2];
   }
@@ -26,17 +29,17 @@
 
 @implementation GPBFileDescriptorSet
 
-@dynamic fileArray;
+@dynamic fileArray, fileArray_Count;
 
-typedef struct GPBFileDescriptorSet_Storage {
+typedef struct GPBFileDescriptorSet__storage_ {
   uint32_t _has_storage_[1];
   NSMutableArray *fileArray;
-} GPBFileDescriptorSet_Storage;
+} GPBFileDescriptorSet__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -44,26 +47,29 @@
         .number = GPBFileDescriptorSet_FieldNumber_FileArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorSet_Storage, fileArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorSet__storage_, fileArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorSet class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBFileDescriptorSet_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorSet class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBFileDescriptorSet__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -76,18 +82,18 @@
 
 @dynamic hasName, name;
 @dynamic hasPackage, package;
-@dynamic dependencyArray;
-@dynamic publicDependencyArray;
-@dynamic weakDependencyArray;
-@dynamic messageTypeArray;
-@dynamic enumTypeArray;
-@dynamic serviceArray;
-@dynamic extensionArray;
+@dynamic dependencyArray, dependencyArray_Count;
+@dynamic publicDependencyArray, publicDependencyArray_Count;
+@dynamic weakDependencyArray, weakDependencyArray_Count;
+@dynamic messageTypeArray, messageTypeArray_Count;
+@dynamic enumTypeArray, enumTypeArray_Count;
+@dynamic serviceArray, serviceArray_Count;
+@dynamic extensionArray, extensionArray_Count;
 @dynamic hasOptions, options;
 @dynamic hasSourceCodeInfo, sourceCodeInfo;
 @dynamic hasSyntax, syntax;
 
-typedef struct GPBFileDescriptorProto_Storage {
+typedef struct GPBFileDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSString *package;
@@ -101,12 +107,12 @@
   GPBInt32Array *publicDependencyArray;
   GPBInt32Array *weakDependencyArray;
   NSString *syntax;
-} GPBFileDescriptorProto_Storage;
+} GPBFileDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -114,10 +120,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -125,10 +131,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_Package,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, package),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, package),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -136,10 +142,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_DependencyArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, dependencyArray),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, dependencyArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -147,10 +153,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_MessageTypeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, messageTypeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, messageTypeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -158,10 +164,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_EnumTypeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, enumTypeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, enumTypeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -169,10 +175,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_ServiceArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, serviceArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, serviceArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -180,10 +186,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_ExtensionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, extensionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, extensionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -191,10 +197,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_Options,
         .hasIndex = 9,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFileOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFileOptions),
         .fieldOptions = NULL,
       },
       {
@@ -202,10 +208,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_SourceCodeInfo,
         .hasIndex = 10,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, sourceCodeInfo),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, sourceCodeInfo),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo),
         .fieldOptions = NULL,
       },
       {
@@ -213,10 +219,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_PublicDependencyArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, publicDependencyArray),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, publicDependencyArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -224,10 +230,10 @@
         .number = GPBFileDescriptorProto_FieldNumber_WeakDependencyArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, weakDependencyArray),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, weakDependencyArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -235,26 +241,29 @@
         .number = GPBFileDescriptorProto_FieldNumber_Syntax,
         .hasIndex = 11,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileDescriptorProto_Storage, syntax),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileDescriptorProto__storage_, syntax),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBFileDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBFileDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -266,17 +275,17 @@
 @implementation GPBDescriptorProto
 
 @dynamic hasName, name;
-@dynamic fieldArray;
-@dynamic extensionArray;
-@dynamic nestedTypeArray;
-@dynamic enumTypeArray;
-@dynamic extensionRangeArray;
-@dynamic oneofDeclArray;
+@dynamic fieldArray, fieldArray_Count;
+@dynamic extensionArray, extensionArray_Count;
+@dynamic nestedTypeArray, nestedTypeArray_Count;
+@dynamic enumTypeArray, enumTypeArray_Count;
+@dynamic extensionRangeArray, extensionRangeArray_Count;
+@dynamic oneofDeclArray, oneofDeclArray_Count;
 @dynamic hasOptions, options;
-@dynamic reservedRangeArray;
-@dynamic reservedNameArray;
+@dynamic reservedRangeArray, reservedRangeArray_Count;
+@dynamic reservedNameArray, reservedNameArray_Count;
 
-typedef struct GPBDescriptorProto_Storage {
+typedef struct GPBDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *fieldArray;
@@ -288,12 +297,12 @@
   NSMutableArray *oneofDeclArray;
   NSMutableArray *reservedRangeArray;
   NSMutableArray *reservedNameArray;
-} GPBDescriptorProto_Storage;
+} GPBDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -301,10 +310,10 @@
         .number = GPBDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -312,10 +321,10 @@
         .number = GPBDescriptorProto_FieldNumber_FieldArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, fieldArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, fieldArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -323,10 +332,10 @@
         .number = GPBDescriptorProto_FieldNumber_NestedTypeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, nestedTypeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, nestedTypeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -334,10 +343,10 @@
         .number = GPBDescriptorProto_FieldNumber_EnumTypeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, enumTypeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, enumTypeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -345,10 +354,10 @@
         .number = GPBDescriptorProto_FieldNumber_ExtensionRangeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, extensionRangeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, extensionRangeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange),
         .fieldOptions = NULL,
       },
       {
@@ -356,10 +365,10 @@
         .number = GPBDescriptorProto_FieldNumber_ExtensionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, extensionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, extensionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -367,10 +376,10 @@
         .number = GPBDescriptorProto_FieldNumber_Options,
         .hasIndex = 7,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBMessageOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMessageOptions),
         .fieldOptions = NULL,
       },
       {
@@ -378,10 +387,10 @@
         .number = GPBDescriptorProto_FieldNumber_OneofDeclArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, oneofDeclArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, oneofDeclArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -389,10 +398,10 @@
         .number = GPBDescriptorProto_FieldNumber_ReservedRangeArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBDescriptorProto_Storage, reservedRangeArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBDescriptorProto__storage_, reservedRangeArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange),
         .fieldOptions = NULL,
       },
       {
@@ -400,26 +409,29 @@
         .number = GPBDescriptorProto_FieldNumber_ReservedNameArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBDescriptorProto_Storage, reservedNameArray),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBDescriptorProto__storage_, reservedNameArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -433,16 +445,16 @@
 @dynamic hasStart, start;
 @dynamic hasEnd, end;
 
-typedef struct GPBDescriptorProto_ExtensionRange_Storage {
+typedef struct GPBDescriptorProto_ExtensionRange__storage_ {
   uint32_t _has_storage_[1];
   int32_t start;
   int32_t end;
-} GPBDescriptorProto_ExtensionRange_Storage;
+} GPBDescriptorProto_ExtensionRange__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -450,10 +462,10 @@
         .number = GPBDescriptorProto_ExtensionRange_FieldNumber_Start,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, start),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, start),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -461,26 +473,29 @@
         .number = GPBDescriptorProto_ExtensionRange_FieldNumber_End,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, end),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, end),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ExtensionRange class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBDescriptorProto_ExtensionRange_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ExtensionRange class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBDescriptorProto_ExtensionRange__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -494,16 +509,16 @@
 @dynamic hasStart, start;
 @dynamic hasEnd, end;
 
-typedef struct GPBDescriptorProto_ReservedRange_Storage {
+typedef struct GPBDescriptorProto_ReservedRange__storage_ {
   uint32_t _has_storage_[1];
   int32_t start;
   int32_t end;
-} GPBDescriptorProto_ReservedRange_Storage;
+} GPBDescriptorProto_ReservedRange__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -511,10 +526,10 @@
         .number = GPBDescriptorProto_ReservedRange_FieldNumber_Start,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, start),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, start),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -522,26 +537,29 @@
         .number = GPBDescriptorProto_ReservedRange_FieldNumber_End,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, end),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, end),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBDescriptorProto_ReservedRange_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBDescriptorProto_ReservedRange__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -562,7 +580,7 @@
 @dynamic hasOneofIndex, oneofIndex;
 @dynamic hasOptions, options;
 
-typedef struct GPBFieldDescriptorProto_Storage {
+typedef struct GPBFieldDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   int32_t number;
   GPBFieldDescriptorProto_Label label;
@@ -573,12 +591,12 @@
   NSString *typeName;
   NSString *defaultValue;
   GPBFieldOptions *options;
-} GPBFieldDescriptorProto_Storage;
+} GPBFieldDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -586,10 +604,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -597,10 +615,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Extendee,
         .hasIndex = 5,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, extendee),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, extendee),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -608,10 +626,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Number,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, number),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, number),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -619,10 +637,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Label,
         .hasIndex = 2,
         .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, label),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, label),
         .defaultValue.valueEnum = GPBFieldDescriptorProto_Label_LabelOptional,
-        .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -630,10 +648,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Type,
         .hasIndex = 3,
         .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, type),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, type),
         .defaultValue.valueEnum = GPBFieldDescriptorProto_Type_TypeDouble,
-        .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -641,10 +659,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_TypeName,
         .hasIndex = 4,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, typeName),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, typeName),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -652,10 +670,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_DefaultValue,
         .hasIndex = 6,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, defaultValue),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, defaultValue),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -663,10 +681,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_Options,
         .hasIndex = 8,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBFieldOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldOptions),
         .fieldOptions = NULL,
       },
       {
@@ -674,10 +692,10 @@
         .number = GPBFieldDescriptorProto_FieldNumber_OneofIndex,
         .hasIndex = 7,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBFieldDescriptorProto_Storage, oneofIndex),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBFieldDescriptorProto__storage_, oneofIndex),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
@@ -685,19 +703,22 @@
       { .enumDescriptorFunc = GPBFieldDescriptorProto_Type_EnumDescriptor },
       { .enumDescriptorFunc = GPBFieldDescriptorProto_Label_EnumDescriptor },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:enums
-                                              enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBFieldDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFieldDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:enums
+                                     enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBFieldDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -798,15 +819,15 @@
 
 @dynamic hasName, name;
 
-typedef struct GPBOneofDescriptorProto_Storage {
+typedef struct GPBOneofDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
-} GPBOneofDescriptorProto_Storage;
+} GPBOneofDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -814,26 +835,29 @@
         .number = GPBOneofDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBOneofDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBOneofDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOneofDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBOneofDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBOneofDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBOneofDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -845,20 +869,20 @@
 @implementation GPBEnumDescriptorProto
 
 @dynamic hasName, name;
-@dynamic valueArray;
+@dynamic valueArray, valueArray_Count;
 @dynamic hasOptions, options;
 
-typedef struct GPBEnumDescriptorProto_Storage {
+typedef struct GPBEnumDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *valueArray;
   GPBEnumOptions *options;
-} GPBEnumDescriptorProto_Storage;
+} GPBEnumDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -866,10 +890,10 @@
         .number = GPBEnumDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBEnumDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBEnumDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -877,10 +901,10 @@
         .number = GPBEnumDescriptorProto_FieldNumber_ValueArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumDescriptorProto_Storage, valueArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumDescriptorProto__storage_, valueArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -888,26 +912,29 @@
         .number = GPBEnumDescriptorProto_FieldNumber_Options,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumOptions),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBEnumDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBEnumDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -922,17 +949,17 @@
 @dynamic hasNumber, number;
 @dynamic hasOptions, options;
 
-typedef struct GPBEnumValueDescriptorProto_Storage {
+typedef struct GPBEnumValueDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   int32_t number;
   NSString *name;
   GPBEnumValueOptions *options;
-} GPBEnumValueDescriptorProto_Storage;
+} GPBEnumValueDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -940,10 +967,10 @@
         .number = GPBEnumValueDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBEnumValueDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBEnumValueDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -951,10 +978,10 @@
         .number = GPBEnumValueDescriptorProto_FieldNumber_Number,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBEnumValueDescriptorProto_Storage, number),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBEnumValueDescriptorProto__storage_, number),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -962,26 +989,29 @@
         .number = GPBEnumValueDescriptorProto_FieldNumber_Options,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumValueDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumValueDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBEnumValueDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumValueDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBEnumValueDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -993,20 +1023,20 @@
 @implementation GPBServiceDescriptorProto
 
 @dynamic hasName, name;
-@dynamic methodArray;
+@dynamic methodArray, methodArray_Count;
 @dynamic hasOptions, options;
 
-typedef struct GPBServiceDescriptorProto_Storage {
+typedef struct GPBServiceDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *methodArray;
   GPBServiceOptions *options;
-} GPBServiceDescriptorProto_Storage;
+} GPBServiceDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1014,10 +1044,10 @@
         .number = GPBServiceDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBServiceDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBServiceDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1025,10 +1055,10 @@
         .number = GPBServiceDescriptorProto_FieldNumber_MethodArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBServiceDescriptorProto_Storage, methodArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBServiceDescriptorProto__storage_, methodArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto),
         .fieldOptions = NULL,
       },
       {
@@ -1036,26 +1066,29 @@
         .number = GPBServiceDescriptorProto_FieldNumber_Options,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBServiceDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBServiceDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBServiceOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBServiceOptions),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBServiceDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBServiceDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBServiceDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1073,7 +1106,7 @@
 @dynamic hasClientStreaming, clientStreaming;
 @dynamic hasServerStreaming, serverStreaming;
 
-typedef struct GPBMethodDescriptorProto_Storage {
+typedef struct GPBMethodDescriptorProto__storage_ {
   uint32_t _has_storage_[1];
   BOOL clientStreaming;
   BOOL serverStreaming;
@@ -1081,12 +1114,12 @@
   NSString *inputType;
   NSString *outputType;
   GPBMethodOptions *options;
-} GPBMethodDescriptorProto_Storage;
+} GPBMethodDescriptorProto__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1094,10 +1127,10 @@
         .number = GPBMethodDescriptorProto_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1105,10 +1138,10 @@
         .number = GPBMethodDescriptorProto_FieldNumber_InputType,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, inputType),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, inputType),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1116,10 +1149,10 @@
         .number = GPBMethodDescriptorProto_FieldNumber_OutputType,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, outputType),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, outputType),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1127,10 +1160,10 @@
         .number = GPBMethodDescriptorProto_FieldNumber_Options,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, options),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, options),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBMethodOptions),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodOptions),
         .fieldOptions = NULL,
       },
       {
@@ -1138,10 +1171,10 @@
         .number = GPBMethodDescriptorProto_FieldNumber_ClientStreaming,
         .hasIndex = 4,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, clientStreaming),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, clientStreaming),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1149,26 +1182,29 @@
         .number = GPBMethodDescriptorProto_FieldNumber_ServerStreaming,
         .hasIndex = 5,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMethodDescriptorProto_Storage, serverStreaming),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMethodDescriptorProto__storage_, serverStreaming),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodDescriptorProto class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBMethodDescriptorProto_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMethodDescriptorProto class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBMethodDescriptorProto__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1193,9 +1229,9 @@
 @dynamic hasCcEnableArenas, ccEnableArenas;
 @dynamic hasObjcClassPrefix, objcClassPrefix;
 @dynamic hasCsharpNamespace, csharpNamespace;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBFileOptions_Storage {
+typedef struct GPBFileOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL javaMultipleFiles;
   BOOL ccGenericServices;
@@ -1212,12 +1248,12 @@
   NSString *objcClassPrefix;
   NSString *csharpNamespace;
   NSMutableArray *uninterpretedOptionArray;
-} GPBFileOptions_Storage;
+} GPBFileOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1225,10 +1261,10 @@
         .number = GPBFileOptions_FieldNumber_JavaPackage,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileOptions_Storage, javaPackage),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileOptions__storage_, javaPackage),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1236,10 +1272,10 @@
         .number = GPBFileOptions_FieldNumber_JavaOuterClassname,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileOptions_Storage, javaOuterClassname),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileOptions__storage_, javaOuterClassname),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1247,10 +1283,10 @@
         .number = GPBFileOptions_FieldNumber_OptimizeFor,
         .hasIndex = 5,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBFileOptions_Storage, optimizeFor),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBFileOptions__storage_, optimizeFor),
         .defaultValue.valueEnum = GPBFileOptions_OptimizeMode_Speed,
-        .typeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -1258,10 +1294,10 @@
         .number = GPBFileOptions_FieldNumber_JavaMultipleFiles,
         .hasIndex = 2,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, javaMultipleFiles),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, javaMultipleFiles),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1269,10 +1305,10 @@
         .number = GPBFileOptions_FieldNumber_GoPackage,
         .hasIndex = 6,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileOptions_Storage, goPackage),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileOptions__storage_, goPackage),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1280,10 +1316,10 @@
         .number = GPBFileOptions_FieldNumber_CcGenericServices,
         .hasIndex = 7,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, ccGenericServices),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, ccGenericServices),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1291,10 +1327,10 @@
         .number = GPBFileOptions_FieldNumber_JavaGenericServices,
         .hasIndex = 8,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, javaGenericServices),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, javaGenericServices),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1302,10 +1338,10 @@
         .number = GPBFileOptions_FieldNumber_PyGenericServices,
         .hasIndex = 9,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, pyGenericServices),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, pyGenericServices),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1313,10 +1349,10 @@
         .number = GPBFileOptions_FieldNumber_JavaGenerateEqualsAndHash,
         .hasIndex = 3,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, javaGenerateEqualsAndHash),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, javaGenerateEqualsAndHash),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1324,10 +1360,10 @@
         .number = GPBFileOptions_FieldNumber_Deprecated,
         .hasIndex = 10,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1335,10 +1371,10 @@
         .number = GPBFileOptions_FieldNumber_JavaStringCheckUtf8,
         .hasIndex = 4,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, javaStringCheckUtf8),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, javaStringCheckUtf8),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1346,10 +1382,10 @@
         .number = GPBFileOptions_FieldNumber_CcEnableArenas,
         .hasIndex = 11,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFileOptions_Storage, ccEnableArenas),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFileOptions__storage_, ccEnableArenas),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1357,10 +1393,10 @@
         .number = GPBFileOptions_FieldNumber_ObjcClassPrefix,
         .hasIndex = 12,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileOptions_Storage, objcClassPrefix),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileOptions__storage_, objcClassPrefix),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1368,10 +1404,10 @@
         .number = GPBFileOptions_FieldNumber_CsharpNamespace,
         .hasIndex = 13,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFileOptions_Storage, csharpNamespace),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFileOptions__storage_, csharpNamespace),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1379,10 +1415,10 @@
         .number = GPBFileOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFileOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFileOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
@@ -1392,19 +1428,22 @@
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:enums
-                                              enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBFileOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFileOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:enums
+                                     enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBFileOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1448,21 +1487,21 @@
 @dynamic hasNoStandardDescriptorAccessor, noStandardDescriptorAccessor;
 @dynamic hasDeprecated, deprecated;
 @dynamic hasMapEntry, mapEntry;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBMessageOptions_Storage {
+typedef struct GPBMessageOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL messageSetWireFormat;
   BOOL noStandardDescriptorAccessor;
   BOOL deprecated;
   BOOL mapEntry;
   NSMutableArray *uninterpretedOptionArray;
-} GPBMessageOptions_Storage;
+} GPBMessageOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1470,10 +1509,10 @@
         .number = GPBMessageOptions_FieldNumber_MessageSetWireFormat,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMessageOptions_Storage, messageSetWireFormat),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMessageOptions__storage_, messageSetWireFormat),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1481,10 +1520,10 @@
         .number = GPBMessageOptions_FieldNumber_NoStandardDescriptorAccessor,
         .hasIndex = 1,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMessageOptions_Storage, noStandardDescriptorAccessor),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMessageOptions__storage_, noStandardDescriptorAccessor),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1492,10 +1531,10 @@
         .number = GPBMessageOptions_FieldNumber_Deprecated,
         .hasIndex = 2,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMessageOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMessageOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1503,10 +1542,10 @@
         .number = GPBMessageOptions_FieldNumber_MapEntry,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMessageOptions_Storage, mapEntry),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMessageOptions__storage_, mapEntry),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1514,29 +1553,32 @@
         .number = GPBMessageOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBMessageOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBMessageOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessageOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBMessageOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMessageOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBMessageOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1553,9 +1595,9 @@
 @dynamic hasLazy, lazy;
 @dynamic hasDeprecated, deprecated;
 @dynamic hasWeak, weak;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBFieldOptions_Storage {
+typedef struct GPBFieldOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL packed;
   BOOL deprecated;
@@ -1564,12 +1606,12 @@
   GPBFieldOptions_CType ctype;
   GPBFieldOptions_JSType jstype;
   NSMutableArray *uninterpretedOptionArray;
-} GPBFieldOptions_Storage;
+} GPBFieldOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1577,10 +1619,10 @@
         .number = GPBFieldOptions_FieldNumber_Ctype,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBFieldOptions_Storage, ctype),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBFieldOptions__storage_, ctype),
         .defaultValue.valueEnum = GPBFieldOptions_CType_String,
-        .typeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -1588,10 +1630,10 @@
         .number = GPBFieldOptions_FieldNumber_Packed,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFieldOptions_Storage, packed),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFieldOptions__storage_, packed),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1599,10 +1641,10 @@
         .number = GPBFieldOptions_FieldNumber_Deprecated,
         .hasIndex = 4,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFieldOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFieldOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1610,10 +1652,10 @@
         .number = GPBFieldOptions_FieldNumber_Lazy,
         .hasIndex = 3,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFieldOptions_Storage, lazy),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFieldOptions__storage_, lazy),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1621,10 +1663,10 @@
         .number = GPBFieldOptions_FieldNumber_Jstype,
         .hasIndex = 2,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBFieldOptions_Storage, jstype),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBFieldOptions__storage_, jstype),
         .defaultValue.valueEnum = GPBFieldOptions_JSType_JsNormal,
-        .typeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -1632,10 +1674,10 @@
         .number = GPBFieldOptions_FieldNumber_Weak,
         .hasIndex = 5,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBFieldOptions_Storage, weak),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBFieldOptions__storage_, weak),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1643,10 +1685,10 @@
         .number = GPBFieldOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBFieldOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBFieldOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
@@ -1657,19 +1699,22 @@
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:enums
-                                              enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBFieldOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFieldOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:enums
+                                     enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBFieldOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1740,19 +1785,19 @@
 
 @dynamic hasAllowAlias, allowAlias;
 @dynamic hasDeprecated, deprecated;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBEnumOptions_Storage {
+typedef struct GPBEnumOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL allowAlias;
   BOOL deprecated;
   NSMutableArray *uninterpretedOptionArray;
-} GPBEnumOptions_Storage;
+} GPBEnumOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1760,10 +1805,10 @@
         .number = GPBEnumOptions_FieldNumber_AllowAlias,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBEnumOptions_Storage, allowAlias),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBEnumOptions__storage_, allowAlias),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1771,10 +1816,10 @@
         .number = GPBEnumOptions_FieldNumber_Deprecated,
         .hasIndex = 1,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBEnumOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBEnumOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1782,29 +1827,32 @@
         .number = GPBEnumOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBEnumOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBEnumOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1816,18 +1864,18 @@
 @implementation GPBEnumValueOptions
 
 @dynamic hasDeprecated, deprecated;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBEnumValueOptions_Storage {
+typedef struct GPBEnumValueOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL deprecated;
   NSMutableArray *uninterpretedOptionArray;
-} GPBEnumValueOptions_Storage;
+} GPBEnumValueOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1835,10 +1883,10 @@
         .number = GPBEnumValueOptions_FieldNumber_Deprecated,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBEnumValueOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBEnumValueOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1846,29 +1894,32 @@
         .number = GPBEnumValueOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumValueOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumValueOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBEnumValueOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumValueOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBEnumValueOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1880,18 +1931,18 @@
 @implementation GPBServiceOptions
 
 @dynamic hasDeprecated, deprecated;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBServiceOptions_Storage {
+typedef struct GPBServiceOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL deprecated;
   NSMutableArray *uninterpretedOptionArray;
-} GPBServiceOptions_Storage;
+} GPBServiceOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1899,10 +1950,10 @@
         .number = GPBServiceOptions_FieldNumber_Deprecated,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBServiceOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBServiceOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1910,29 +1961,32 @@
         .number = GPBServiceOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBServiceOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBServiceOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBServiceOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBServiceOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBServiceOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -1944,18 +1998,18 @@
 @implementation GPBMethodOptions
 
 @dynamic hasDeprecated, deprecated;
-@dynamic uninterpretedOptionArray;
+@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
 
-typedef struct GPBMethodOptions_Storage {
+typedef struct GPBMethodOptions__storage_ {
   uint32_t _has_storage_[1];
   BOOL deprecated;
   NSMutableArray *uninterpretedOptionArray;
-} GPBMethodOptions_Storage;
+} GPBMethodOptions__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -1963,10 +2017,10 @@
         .number = GPBMethodOptions_FieldNumber_Deprecated,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBMethodOptions_Storage, deprecated),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBMethodOptions__storage_, deprecated),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -1974,29 +2028,32 @@
         .number = GPBMethodOptions_FieldNumber_UninterpretedOptionArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBMethodOptions_Storage, uninterpretedOptionArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBMethodOptions__storage_, uninterpretedOptionArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
         .fieldOptions = NULL,
       },
     };
     static GPBExtensionRange ranges[] = {
       { .start = 1000, .end = 536870912 },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodOptions class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:ranges
-                                             rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
-                                            storageSize:sizeof(GPBMethodOptions_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMethodOptions class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:ranges
+                                    rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+                                   storageSize:sizeof(GPBMethodOptions__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -2007,7 +2064,7 @@
 
 @implementation GPBUninterpretedOption
 
-@dynamic nameArray;
+@dynamic nameArray, nameArray_Count;
 @dynamic hasIdentifierValue, identifierValue;
 @dynamic hasPositiveIntValue, positiveIntValue;
 @dynamic hasNegativeIntValue, negativeIntValue;
@@ -2015,7 +2072,7 @@
 @dynamic hasStringValue, stringValue;
 @dynamic hasAggregateValue, aggregateValue;
 
-typedef struct GPBUninterpretedOption_Storage {
+typedef struct GPBUninterpretedOption__storage_ {
   uint32_t _has_storage_[1];
   NSMutableArray *nameArray;
   NSString *identifierValue;
@@ -2024,12 +2081,12 @@
   uint64_t positiveIntValue;
   int64_t negativeIntValue;
   double doubleValue;
-} GPBUninterpretedOption_Storage;
+} GPBUninterpretedOption__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -2037,10 +2094,10 @@
         .number = GPBUninterpretedOption_FieldNumber_NameArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBUninterpretedOption_Storage, nameArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBUninterpretedOption__storage_, nameArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart),
         .fieldOptions = NULL,
       },
       {
@@ -2048,10 +2105,10 @@
         .number = GPBUninterpretedOption_FieldNumber_IdentifierValue,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBUninterpretedOption_Storage, identifierValue),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBUninterpretedOption__storage_, identifierValue),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2059,10 +2116,10 @@
         .number = GPBUninterpretedOption_FieldNumber_PositiveIntValue,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeUInt64,
-        .offset = offsetof(GPBUninterpretedOption_Storage, positiveIntValue),
+        .dataType = GPBDataTypeUInt64,
+        .offset = offsetof(GPBUninterpretedOption__storage_, positiveIntValue),
         .defaultValue.valueUInt64 = 0ULL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2070,10 +2127,10 @@
         .number = GPBUninterpretedOption_FieldNumber_NegativeIntValue,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt64,
-        .offset = offsetof(GPBUninterpretedOption_Storage, negativeIntValue),
+        .dataType = GPBDataTypeInt64,
+        .offset = offsetof(GPBUninterpretedOption__storage_, negativeIntValue),
         .defaultValue.valueInt64 = 0LL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2081,10 +2138,10 @@
         .number = GPBUninterpretedOption_FieldNumber_DoubleValue,
         .hasIndex = 4,
         .flags = GPBFieldOptional,
-        .type = GPBTypeDouble,
-        .offset = offsetof(GPBUninterpretedOption_Storage, doubleValue),
+        .dataType = GPBDataTypeDouble,
+        .offset = offsetof(GPBUninterpretedOption__storage_, doubleValue),
         .defaultValue.valueDouble = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2092,10 +2149,10 @@
         .number = GPBUninterpretedOption_FieldNumber_StringValue,
         .hasIndex = 5,
         .flags = GPBFieldOptional,
-        .type = GPBTypeData,
-        .offset = offsetof(GPBUninterpretedOption_Storage, stringValue),
+        .dataType = GPBDataTypeBytes,
+        .offset = offsetof(GPBUninterpretedOption__storage_, stringValue),
         .defaultValue.valueData = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2103,26 +2160,29 @@
         .number = GPBUninterpretedOption_FieldNumber_AggregateValue,
         .hasIndex = 6,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBUninterpretedOption_Storage, aggregateValue),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBUninterpretedOption__storage_, aggregateValue),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBUninterpretedOption_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBUninterpretedOption__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -2136,16 +2196,16 @@
 @dynamic hasNamePart, namePart;
 @dynamic hasIsExtension, isExtension;
 
-typedef struct GPBUninterpretedOption_NamePart_Storage {
+typedef struct GPBUninterpretedOption_NamePart__storage_ {
   uint32_t _has_storage_[1];
   BOOL isExtension;
   NSString *namePart;
-} GPBUninterpretedOption_NamePart_Storage;
+} GPBUninterpretedOption_NamePart__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -2153,10 +2213,10 @@
         .number = GPBUninterpretedOption_NamePart_FieldNumber_NamePart,
         .hasIndex = 0,
         .flags = GPBFieldRequired,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, namePart),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, namePart),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2164,26 +2224,29 @@
         .number = GPBUninterpretedOption_NamePart_FieldNumber_IsExtension,
         .hasIndex = 1,
         .flags = GPBFieldRequired,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, isExtension),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, isExtension),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption_NamePart class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBUninterpretedOption_NamePart_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption_NamePart class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBUninterpretedOption_NamePart__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -2194,17 +2257,17 @@
 
 @implementation GPBSourceCodeInfo
 
-@dynamic locationArray;
+@dynamic locationArray, locationArray_Count;
 
-typedef struct GPBSourceCodeInfo_Storage {
+typedef struct GPBSourceCodeInfo__storage_ {
   uint32_t _has_storage_[1];
   NSMutableArray *locationArray;
-} GPBSourceCodeInfo_Storage;
+} GPBSourceCodeInfo__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -2212,26 +2275,29 @@
         .number = GPBSourceCodeInfo_FieldNumber_LocationArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBSourceCodeInfo_Storage, locationArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBSourceCodeInfo__storage_, locationArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBSourceCodeInfo_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBSourceCodeInfo__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -2242,25 +2308,25 @@
 
 @implementation GPBSourceCodeInfo_Location
 
-@dynamic pathArray;
-@dynamic spanArray;
+@dynamic pathArray, pathArray_Count;
+@dynamic spanArray, spanArray_Count;
 @dynamic hasLeadingComments, leadingComments;
 @dynamic hasTrailingComments, trailingComments;
-@dynamic leadingDetachedCommentsArray;
+@dynamic leadingDetachedCommentsArray, leadingDetachedCommentsArray_Count;
 
-typedef struct GPBSourceCodeInfo_Location_Storage {
+typedef struct GPBSourceCodeInfo_Location__storage_ {
   uint32_t _has_storage_[1];
   GPBInt32Array *pathArray;
   GPBInt32Array *spanArray;
   NSString *leadingComments;
   NSString *trailingComments;
   NSMutableArray *leadingDetachedCommentsArray;
-} GPBSourceCodeInfo_Location_Storage;
+} GPBSourceCodeInfo_Location__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -2268,10 +2334,10 @@
         .number = GPBSourceCodeInfo_Location_FieldNumber_PathArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated | GPBFieldPacked,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBSourceCodeInfo_Location_Storage, pathArray),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBSourceCodeInfo_Location__storage_, pathArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
       #if GPBOBJC_INCLUDE_FIELD_OPTIONS
         .fieldOptions = "\000\000\000\002\020\001",
       #else
@@ -2283,10 +2349,10 @@
         .number = GPBSourceCodeInfo_Location_FieldNumber_SpanArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated | GPBFieldPacked,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBSourceCodeInfo_Location_Storage, spanArray),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBSourceCodeInfo_Location__storage_, spanArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
       #if GPBOBJC_INCLUDE_FIELD_OPTIONS
         .fieldOptions = "\000\000\000\002\020\001",
       #else
@@ -2298,10 +2364,10 @@
         .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingComments,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingComments),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingComments),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2309,10 +2375,10 @@
         .number = GPBSourceCodeInfo_Location_FieldNumber_TrailingComments,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBSourceCodeInfo_Location_Storage, trailingComments),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBSourceCodeInfo_Location__storage_, trailingComments),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -2320,26 +2386,29 @@
         .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingDetachedCommentsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingDetachedCommentsArray),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingDetachedCommentsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo_Location class]
-                                              rootClass:[GPBDescriptorRoot class]
-                                                   file:GPBDescriptorRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBSourceCodeInfo_Location_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo_Location class]
+                                     rootClass:[GPBDescriptorRoot class]
+                                          file:GPBDescriptorRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBSourceCodeInfo_Location__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m
index 4db030f..e4fd495 100644
--- a/objectivec/google/protobuf/Duration.pbobjc.m
+++ b/objectivec/google/protobuf/Duration.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBDurationRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -29,16 +32,16 @@
 @dynamic seconds;
 @dynamic nanos;
 
-typedef struct GPBDuration_Storage {
+typedef struct GPBDuration__storage_ {
   uint32_t _has_storage_[1];
   int32_t nanos;
   int64_t seconds;
-} GPBDuration_Storage;
+} GPBDuration__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -46,10 +49,10 @@
         .number = GPBDuration_FieldNumber_Seconds,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt64,
-        .offset = offsetof(GPBDuration_Storage, seconds),
+        .dataType = GPBDataTypeInt64,
+        .offset = offsetof(GPBDuration__storage_, seconds),
         .defaultValue.valueInt64 = 0LL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -57,26 +60,29 @@
         .number = GPBDuration_FieldNumber_Nanos,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBDuration_Storage, nanos),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBDuration__storage_, nanos),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDuration class]
-                                              rootClass:[GPBDurationRoot class]
-                                                   file:GPBDurationRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBDuration_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDuration class]
+                                     rootClass:[GPBDurationRoot class]
+                                          file:GPBDurationRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBDuration__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m
index 619fe90..17f0c1a 100644
--- a/objectivec/google/protobuf/Empty.pbobjc.m
+++ b/objectivec/google/protobuf/Empty.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBEmptyRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -27,30 +30,31 @@
 @implementation GPBEmpty
 
 
-typedef struct GPBEmpty_Storage {
+typedef struct GPBEmpty__storage_ {
   uint32_t _has_storage_[0];
-} GPBEmpty_Storage;
+} GPBEmpty__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
-    static GPBMessageFieldDescription fields[] = {
-    };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEmpty class]
-                                              rootClass:[GPBEmptyRoot class]
-                                                   file:GPBEmptyRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBEmpty_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEmpty class]
+                                     rootClass:[GPBEmptyRoot class]
+                                          file:GPBEmptyRoot_FileDescriptor()
+                                        fields:NULL
+                                    fieldCount:0
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBEmpty__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h
index ac6f03d..f9b26fa 100644
--- a/objectivec/google/protobuf/FieldMask.pbobjc.h
+++ b/objectivec/google/protobuf/FieldMask.pbobjc.h
@@ -152,6 +152,7 @@
 // The set of field mask paths.
 // |pathsArray| contains |NSString|
 @property(nonatomic, readwrite, strong) NSMutableArray *pathsArray;
+@property(nonatomic, readonly) NSUInteger pathsArray_Count;
 
 @end
 
diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m
index e37ac6c..f9684f5 100644
--- a/objectivec/google/protobuf/FieldMask.pbobjc.m
+++ b/objectivec/google/protobuf/FieldMask.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBFieldMaskRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -26,17 +29,17 @@
 
 @implementation GPBFieldMask
 
-@dynamic pathsArray;
+@dynamic pathsArray, pathsArray_Count;
 
-typedef struct GPBFieldMask_Storage {
+typedef struct GPBFieldMask__storage_ {
   uint32_t _has_storage_[1];
   NSMutableArray *pathsArray;
-} GPBFieldMask_Storage;
+} GPBFieldMask__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -44,26 +47,29 @@
         .number = GPBFieldMask_FieldNumber_PathsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBFieldMask_Storage, pathsArray),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBFieldMask__storage_, pathsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class]
-                                              rootClass:[GPBFieldMaskRoot class]
-                                                   file:GPBFieldMaskRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBFieldMask_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class]
+                                     rootClass:[GPBFieldMaskRoot class]
+                                          file:GPBFieldMaskRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBFieldMask__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m
index 271f924..ac1827f 100644
--- a/objectivec/google/protobuf/SourceContext.pbobjc.m
+++ b/objectivec/google/protobuf/SourceContext.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBSourceContextRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -28,15 +31,15 @@
 
 @dynamic fileName;
 
-typedef struct GPBSourceContext_Storage {
+typedef struct GPBSourceContext__storage_ {
   uint32_t _has_storage_[1];
   NSString *fileName;
-} GPBSourceContext_Storage;
+} GPBSourceContext__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -44,26 +47,29 @@
         .number = GPBSourceContext_FieldNumber_FileName,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBSourceContext_Storage, fileName),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBSourceContext__storage_, fileName),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class]
-                                              rootClass:[GPBSourceContextRoot class]
-                                                   file:GPBSourceContextRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBSourceContext_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class]
+                                     rootClass:[GPBSourceContextRoot class]
+                                          file:GPBSourceContextRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBSourceContext__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h
index f55af82..4545695 100644
--- a/objectivec/google/protobuf/Struct.pbobjc.h
+++ b/objectivec/google/protobuf/Struct.pbobjc.h
@@ -57,6 +57,7 @@
 // Map of dynamically typed values.
 // |fields| values are |GPBValue|
 @property(nonatomic, readwrite, strong) NSMutableDictionary *fields;
+@property(nonatomic, readonly) NSUInteger fields_Count;
 
 @end
 
@@ -126,6 +127,7 @@
 // Repeated field of dynamically typed values.
 // |valuesArray| contains |GPBValue|
 @property(nonatomic, readwrite, strong) NSMutableArray *valuesArray;
+@property(nonatomic, readonly) NSUInteger valuesArray_Count;
 
 @end
 
diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m
index e5a8b54..14b8f27 100644
--- a/objectivec/google/protobuf/Struct.pbobjc.m
+++ b/objectivec/google/protobuf/Struct.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBStructRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -51,17 +54,17 @@
 
 @implementation GPBStruct
 
-@dynamic fields;
+@dynamic fields, fields_Count;
 
-typedef struct GPBStruct_Storage {
+typedef struct GPBStruct__storage_ {
   uint32_t _has_storage_[1];
   NSMutableDictionary *fields;
-} GPBStruct_Storage;
+} GPBStruct__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -69,26 +72,29 @@
         .number = GPBStruct_FieldNumber_Fields,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldMapKeyString,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBStruct_Storage, fields),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBStruct__storage_, fields),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBValue),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStruct class]
-                                              rootClass:[GPBStructRoot class]
-                                                   file:GPBStructRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBStruct_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBStruct class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBStruct__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -107,7 +113,7 @@
 @dynamic structValue;
 @dynamic listValue;
 
-typedef struct GPBValue_Storage {
+typedef struct GPBValue__storage_ {
   uint32_t _has_storage_[2];
   BOOL boolValue;
   GPBNullValue nullValue;
@@ -115,12 +121,12 @@
   GPBStruct *structValue;
   GPBListValue *listValue;
   double numberValue;
-} GPBValue_Storage;
+} GPBValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageOneofDescription oneofs[] = {
       {
@@ -134,10 +140,10 @@
         .number = GPBValue_FieldNumber_NullValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBValue_Storage, nullValue),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBValue__storage_, nullValue),
         .defaultValue.valueEnum = GPBNullValue_NullValue,
-        .typeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -145,10 +151,10 @@
         .number = GPBValue_FieldNumber_NumberValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeDouble,
-        .offset = offsetof(GPBValue_Storage, numberValue),
+        .dataType = GPBDataTypeDouble,
+        .offset = offsetof(GPBValue__storage_, numberValue),
         .defaultValue.valueDouble = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -156,10 +162,10 @@
         .number = GPBValue_FieldNumber_StringValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBValue_Storage, stringValue),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBValue__storage_, stringValue),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -167,10 +173,10 @@
         .number = GPBValue_FieldNumber_BoolValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBValue_Storage, boolValue),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBValue__storage_, boolValue),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -178,10 +184,10 @@
         .number = GPBValue_FieldNumber_StructValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBValue_Storage, structValue),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBValue__storage_, structValue),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBStruct),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct),
         .fieldOptions = NULL,
       },
       {
@@ -189,26 +195,29 @@
         .number = GPBValue_FieldNumber_ListValue,
         .hasIndex = -1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBValue_Storage, listValue),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBValue__storage_, listValue),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBListValue),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBValue class]
-                                              rootClass:[GPBStructRoot class]
-                                                   file:GPBStructRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:oneofs
-                                             oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription)
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBValue class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:oneofs
+                                    oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription)
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -218,7 +227,7 @@
 int32_t GPBValue_NullValue_RawValue(GPBValue *message) {
   GPBDescriptor *descriptor = [GPBValue descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
-  return GPBGetInt32IvarWithField(message, field);
+  return GPBGetMessageInt32Field(message, field);
 }
 
 void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) {
@@ -236,17 +245,17 @@
 
 @implementation GPBListValue
 
-@dynamic valuesArray;
+@dynamic valuesArray, valuesArray_Count;
 
-typedef struct GPBListValue_Storage {
+typedef struct GPBListValue__storage_ {
   uint32_t _has_storage_[1];
   NSMutableArray *valuesArray;
-} GPBListValue_Storage;
+} GPBListValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -254,26 +263,29 @@
         .number = GPBListValue_FieldNumber_ValuesArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBListValue_Storage, valuesArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBListValue__storage_, valuesArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBValue),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBListValue class]
-                                              rootClass:[GPBStructRoot class]
-                                                   file:GPBStructRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBListValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBListValue class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBListValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m
index 197dff4..a206f15 100644
--- a/objectivec/google/protobuf/Timestamp.pbobjc.m
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBTimestampRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -29,16 +32,16 @@
 @dynamic seconds;
 @dynamic nanos;
 
-typedef struct GPBTimestamp_Storage {
+typedef struct GPBTimestamp__storage_ {
   uint32_t _has_storage_[1];
   int32_t nanos;
   int64_t seconds;
-} GPBTimestamp_Storage;
+} GPBTimestamp__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -46,10 +49,10 @@
         .number = GPBTimestamp_FieldNumber_Seconds,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt64,
-        .offset = offsetof(GPBTimestamp_Storage, seconds),
+        .dataType = GPBDataTypeInt64,
+        .offset = offsetof(GPBTimestamp__storage_, seconds),
         .defaultValue.valueInt64 = 0LL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -57,26 +60,29 @@
         .number = GPBTimestamp_FieldNumber_Nanos,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBTimestamp_Storage, nanos),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBTimestamp__storage_, nanos),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class]
-                                              rootClass:[GPBTimestampRoot class]
-                                                   file:GPBTimestampRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBTimestamp_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class]
+                                     rootClass:[GPBTimestampRoot class]
+                                          file:GPBTimestampRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBTimestamp__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h
index 652a33a..e3b6229 100644
--- a/objectivec/google/protobuf/Type.pbobjc.h
+++ b/objectivec/google/protobuf/Type.pbobjc.h
@@ -132,15 +132,18 @@
 // The list of fields.
 // |fieldsArray| contains |GPBField|
 @property(nonatomic, readwrite, strong) NSMutableArray *fieldsArray;
+@property(nonatomic, readonly) NSUInteger fieldsArray_Count;
 
 // The list of oneof definitions.
 // The list of oneofs declared in this Type
 // |oneofsArray| contains |NSString|
 @property(nonatomic, readwrite, strong) NSMutableArray *oneofsArray;
+@property(nonatomic, readonly) NSUInteger oneofsArray_Count;
 
 // The proto options.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 // The source context.
 @property(nonatomic, readwrite) BOOL hasSourceContext;
@@ -189,6 +192,7 @@
 // The proto options.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 @end
 
@@ -216,10 +220,12 @@
 // Enum value definitions.
 // |enumvalueArray| contains |GPBEnumValue|
 @property(nonatomic, readwrite, strong) NSMutableArray *enumvalueArray;
+@property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
 
 // Proto options for the enum type.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 // The source context.
 @property(nonatomic, readwrite) BOOL hasSourceContext;
@@ -247,6 +253,7 @@
 // Proto options for the enum value.
 // |optionsArray| contains |GPBOption|
 @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray;
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 @end
 
diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m
index 182370c..5a2ce28 100644
--- a/objectivec/google/protobuf/Type.pbobjc.m
+++ b/objectivec/google/protobuf/Type.pbobjc.m
@@ -16,10 +16,8 @@
   // about thread safety and initialization of registry.
   static GPBExtensionRegistry* registry = nil;
   if (!registry) {
+    GPBDebugCheckRuntimeVersion();
     registry = [[GPBExtensionRegistry alloc] init];
-    static GPBExtensionDescription descriptions[] = {
-    };
-    #pragma unused (descriptions)
     [registry addExtensions:[GPBAnyRoot extensionRegistry]];
     [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
   }
@@ -28,11 +26,14 @@
 
 @end
 
+#pragma mark - GPBTypeRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -44,24 +45,24 @@
 @implementation GPBType
 
 @dynamic name;
-@dynamic fieldsArray;
-@dynamic oneofsArray;
-@dynamic optionsArray;
+@dynamic fieldsArray, fieldsArray_Count;
+@dynamic oneofsArray, oneofsArray_Count;
+@dynamic optionsArray, optionsArray_Count;
 @dynamic hasSourceContext, sourceContext;
 
-typedef struct GPBType_Storage {
+typedef struct GPBType__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *fieldsArray;
   NSMutableArray *oneofsArray;
   NSMutableArray *optionsArray;
   GPBSourceContext *sourceContext;
-} GPBType_Storage;
+} GPBType__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -69,10 +70,10 @@
         .number = GPBType_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBType_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBType__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -80,10 +81,10 @@
         .number = GPBType_FieldNumber_FieldsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBType_Storage, fieldsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBType__storage_, fieldsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBField),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBField),
         .fieldOptions = NULL,
       },
       {
@@ -91,10 +92,10 @@
         .number = GPBType_FieldNumber_OneofsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBType_Storage, oneofsArray),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBType__storage_, oneofsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -102,10 +103,10 @@
         .number = GPBType_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBType_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBType__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
       {
@@ -113,26 +114,29 @@
         .number = GPBType_FieldNumber_SourceContext,
         .hasIndex = 4,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBType_Storage, sourceContext),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBType__storage_, sourceContext),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBType class]
-                                              rootClass:[GPBTypeRoot class]
-                                                   file:GPBTypeRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBType_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBType class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBType__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -150,9 +154,9 @@
 @dynamic typeURL;
 @dynamic oneofIndex;
 @dynamic packed;
-@dynamic optionsArray;
+@dynamic optionsArray, optionsArray_Count;
 
-typedef struct GPBField_Storage {
+typedef struct GPBField__storage_ {
   uint32_t _has_storage_[1];
   BOOL packed;
   GPBField_Kind kind;
@@ -162,12 +166,12 @@
   NSString *name;
   NSString *typeURL;
   NSMutableArray *optionsArray;
-} GPBField_Storage;
+} GPBField__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -175,10 +179,10 @@
         .number = GPBField_FieldNumber_Kind,
         .hasIndex = 0,
         .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBField_Storage, kind),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBField__storage_, kind),
         .defaultValue.valueEnum = GPBField_Kind_TypeUnknown,
-        .typeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -186,10 +190,10 @@
         .number = GPBField_FieldNumber_Cardinality,
         .hasIndex = 1,
         .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
-        .type = GPBTypeEnum,
-        .offset = offsetof(GPBField_Storage, cardinality),
+        .dataType = GPBDataTypeEnum,
+        .offset = offsetof(GPBField__storage_, cardinality),
         .defaultValue.valueEnum = GPBField_Cardinality_CardinalityUnknown,
-        .typeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor,
+        .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor,
         .fieldOptions = NULL,
       },
       {
@@ -197,10 +201,10 @@
         .number = GPBField_FieldNumber_Number,
         .hasIndex = 2,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBField_Storage, number),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBField__storage_, number),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -208,10 +212,10 @@
         .number = GPBField_FieldNumber_Name,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBField_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBField__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -219,10 +223,10 @@
         .number = GPBField_FieldNumber_TypeURL,
         .hasIndex = 4,
         .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBField_Storage, typeURL),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBField__storage_, typeURL),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -230,10 +234,10 @@
         .number = GPBField_FieldNumber_OneofIndex,
         .hasIndex = 5,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBField_Storage, oneofIndex),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBField__storage_, oneofIndex),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -241,10 +245,10 @@
         .number = GPBField_FieldNumber_Packed,
         .hasIndex = 6,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBField_Storage, packed),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBField__storage_, packed),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -252,10 +256,10 @@
         .number = GPBField_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBField_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBField__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
     };
@@ -268,20 +272,23 @@
 #else
     static const char *extraTextFormatInfo = "\001\006\004\241!!\000";
 #endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBField class]
-                                              rootClass:[GPBTypeRoot class]
-                                                   file:GPBTypeRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:enums
-                                              enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBField_Storage)
-                                             wireFormat:NO
-                                    extraTextFormatInfo:extraTextFormatInfo];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBField class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:enums
+                                     enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBField__storage_)
+                                    wireFormat:NO
+                           extraTextFormatInfo:extraTextFormatInfo];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -291,7 +298,7 @@
 int32_t GPBField_Kind_RawValue(GPBField *message) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
-  return GPBGetInt32IvarWithField(message, field);
+  return GPBGetMessageInt32Field(message, field);
 }
 
 void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) {
@@ -303,7 +310,7 @@
 int32_t GPBField_Cardinality_RawValue(GPBField *message) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
-  return GPBGetInt32IvarWithField(message, field);
+  return GPBGetMessageInt32Field(message, field);
 }
 
 void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) {
@@ -407,22 +414,22 @@
 @implementation GPBEnum
 
 @dynamic name;
-@dynamic enumvalueArray;
-@dynamic optionsArray;
+@dynamic enumvalueArray, enumvalueArray_Count;
+@dynamic optionsArray, optionsArray_Count;
 @dynamic hasSourceContext, sourceContext;
 
-typedef struct GPBEnum_Storage {
+typedef struct GPBEnum__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   NSMutableArray *enumvalueArray;
   NSMutableArray *optionsArray;
   GPBSourceContext *sourceContext;
-} GPBEnum_Storage;
+} GPBEnum__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -430,10 +437,10 @@
         .number = GPBEnum_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBEnum_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBEnum__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -441,10 +448,10 @@
         .number = GPBEnum_FieldNumber_EnumvalueArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnum_Storage, enumvalueArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnum__storage_, enumvalueArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBEnumValue),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue),
         .fieldOptions = NULL,
       },
       {
@@ -452,10 +459,10 @@
         .number = GPBEnum_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnum_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnum__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
       {
@@ -463,26 +470,29 @@
         .number = GPBEnum_FieldNumber_SourceContext,
         .hasIndex = 3,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnum_Storage, sourceContext),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnum__storage_, sourceContext),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnum class]
-                                              rootClass:[GPBTypeRoot class]
-                                                   file:GPBTypeRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBEnum_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnum class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBEnum__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -495,19 +505,19 @@
 
 @dynamic name;
 @dynamic number;
-@dynamic optionsArray;
+@dynamic optionsArray, optionsArray_Count;
 
-typedef struct GPBEnumValue_Storage {
+typedef struct GPBEnumValue__storage_ {
   uint32_t _has_storage_[1];
   int32_t number;
   NSString *name;
   NSMutableArray *optionsArray;
-} GPBEnumValue_Storage;
+} GPBEnumValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -515,10 +525,10 @@
         .number = GPBEnumValue_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBEnumValue_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBEnumValue__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -526,10 +536,10 @@
         .number = GPBEnumValue_FieldNumber_Number,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBEnumValue_Storage, number),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBEnumValue__storage_, number),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -537,26 +547,29 @@
         .number = GPBEnumValue_FieldNumber_OptionsArray,
         .hasIndex = GPBNoHasBit,
         .flags = GPBFieldRepeated,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBEnumValue_Storage, optionsArray),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBEnumValue__storage_, optionsArray),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBOption),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class]
-                                              rootClass:[GPBTypeRoot class]
-                                                   file:GPBTypeRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBEnumValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBEnumValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -570,16 +583,16 @@
 @dynamic name;
 @dynamic hasValue, value;
 
-typedef struct GPBOption_Storage {
+typedef struct GPBOption__storage_ {
   uint32_t _has_storage_[1];
   NSString *name;
   GPBAny *value;
-} GPBOption_Storage;
+} GPBOption__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -587,10 +600,10 @@
         .number = GPBOption_FieldNumber_Name,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBOption_Storage, name),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBOption__storage_, name),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
       {
@@ -598,26 +611,29 @@
         .number = GPBOption_FieldNumber_Value,
         .hasIndex = 1,
         .flags = GPBFieldOptional,
-        .type = GPBTypeMessage,
-        .offset = offsetof(GPBOption_Storage, value),
+        .dataType = GPBDataTypeMessage,
+        .offset = offsetof(GPBOption__storage_, value),
         .defaultValue.valueMessage = nil,
-        .typeSpecific.className = GPBStringifySymbol(GPBAny),
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBAny),
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOption class]
-                                              rootClass:[GPBTypeRoot class]
-                                                   file:GPBTypeRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBOption_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBOption class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBOption__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m
index 6c34285..0403b46 100644
--- a/objectivec/google/protobuf/Wrappers.pbobjc.m
+++ b/objectivec/google/protobuf/Wrappers.pbobjc.m
@@ -11,11 +11,14 @@
 
 @end
 
+#pragma mark - GPBWrappersRoot_FileDescriptor
+
 static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) {
   // This is called by +initialize so there is no need to worry
   // about thread safety of the singleton.
   static GPBFileDescriptor *descriptor = NULL;
   if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
     descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
                                                      syntax:GPBFileSyntaxProto3];
   }
@@ -28,15 +31,15 @@
 
 @dynamic value;
 
-typedef struct GPBDoubleValue_Storage {
+typedef struct GPBDoubleValue__storage_ {
   uint32_t _has_storage_[1];
   double value;
-} GPBDoubleValue_Storage;
+} GPBDoubleValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -44,26 +47,29 @@
         .number = GPBDoubleValue_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeDouble,
-        .offset = offsetof(GPBDoubleValue_Storage, value),
+        .dataType = GPBDataTypeDouble,
+        .offset = offsetof(GPBDoubleValue__storage_, value),
         .defaultValue.valueDouble = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBDoubleValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBDoubleValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -76,15 +82,15 @@
 
 @dynamic value;
 
-typedef struct GPBFloatValue_Storage {
+typedef struct GPBFloatValue__storage_ {
   uint32_t _has_storage_[1];
   float value;
-} GPBFloatValue_Storage;
+} GPBFloatValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -92,26 +98,29 @@
         .number = GPBFloatValue_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeFloat,
-        .offset = offsetof(GPBFloatValue_Storage, value),
+        .dataType = GPBDataTypeFloat,
+        .offset = offsetof(GPBFloatValue__storage_, value),
         .defaultValue.valueFloat = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBFloatValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBFloatValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -124,15 +133,15 @@
 
 @dynamic value;
 
-typedef struct GPBInt64Value_Storage {
+typedef struct GPBInt64Value__storage_ {
   uint32_t _has_storage_[1];
   int64_t value;
-} GPBInt64Value_Storage;
+} GPBInt64Value__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -140,26 +149,29 @@
         .number = GPBInt64Value_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt64,
-        .offset = offsetof(GPBInt64Value_Storage, value),
+        .dataType = GPBDataTypeInt64,
+        .offset = offsetof(GPBInt64Value__storage_, value),
         .defaultValue.valueInt64 = 0LL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBInt64Value_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBInt64Value__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -172,15 +184,15 @@
 
 @dynamic value;
 
-typedef struct GPBUInt64Value_Storage {
+typedef struct GPBUInt64Value__storage_ {
   uint32_t _has_storage_[1];
   uint64_t value;
-} GPBUInt64Value_Storage;
+} GPBUInt64Value__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -188,26 +200,29 @@
         .number = GPBUInt64Value_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeUInt64,
-        .offset = offsetof(GPBUInt64Value_Storage, value),
+        .dataType = GPBDataTypeUInt64,
+        .offset = offsetof(GPBUInt64Value__storage_, value),
         .defaultValue.valueUInt64 = 0ULL,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBUInt64Value_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBUInt64Value__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -220,15 +235,15 @@
 
 @dynamic value;
 
-typedef struct GPBInt32Value_Storage {
+typedef struct GPBInt32Value__storage_ {
   uint32_t _has_storage_[1];
   int32_t value;
-} GPBInt32Value_Storage;
+} GPBInt32Value__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -236,26 +251,29 @@
         .number = GPBInt32Value_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeInt32,
-        .offset = offsetof(GPBInt32Value_Storage, value),
+        .dataType = GPBDataTypeInt32,
+        .offset = offsetof(GPBInt32Value__storage_, value),
         .defaultValue.valueInt32 = 0,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBInt32Value_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBInt32Value__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -268,15 +286,15 @@
 
 @dynamic value;
 
-typedef struct GPBUInt32Value_Storage {
+typedef struct GPBUInt32Value__storage_ {
   uint32_t _has_storage_[1];
   uint32_t value;
-} GPBUInt32Value_Storage;
+} GPBUInt32Value__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -284,26 +302,29 @@
         .number = GPBUInt32Value_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeUInt32,
-        .offset = offsetof(GPBUInt32Value_Storage, value),
+        .dataType = GPBDataTypeUInt32,
+        .offset = offsetof(GPBUInt32Value__storage_, value),
         .defaultValue.valueUInt32 = 0U,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBUInt32Value_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBUInt32Value__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -316,15 +337,15 @@
 
 @dynamic value;
 
-typedef struct GPBBoolValue_Storage {
+typedef struct GPBBoolValue__storage_ {
   uint32_t _has_storage_[1];
   BOOL value;
-} GPBBoolValue_Storage;
+} GPBBoolValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -332,26 +353,29 @@
         .number = GPBBoolValue_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeBool,
-        .offset = offsetof(GPBBoolValue_Storage, value),
+        .dataType = GPBDataTypeBool,
+        .offset = offsetof(GPBBoolValue__storage_, value),
         .defaultValue.valueBool = NO,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBBoolValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBBoolValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -364,15 +388,15 @@
 
 @dynamic value;
 
-typedef struct GPBStringValue_Storage {
+typedef struct GPBStringValue__storage_ {
   uint32_t _has_storage_[1];
   NSString *value;
-} GPBStringValue_Storage;
+} GPBStringValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -380,26 +404,29 @@
         .number = GPBStringValue_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeString,
-        .offset = offsetof(GPBStringValue_Storage, value),
+        .dataType = GPBDataTypeString,
+        .offset = offsetof(GPBStringValue__storage_, value),
         .defaultValue.valueString = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStringValue class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBStringValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBStringValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBStringValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
@@ -412,15 +439,15 @@
 
 @dynamic value;
 
-typedef struct GPBBytesValue_Storage {
+typedef struct GPBBytesValue__storage_ {
   uint32_t _has_storage_[1];
   NSData *value;
-} GPBBytesValue_Storage;
+} GPBBytesValue__storage_;
 
 // This method is threadsafe because it is initially called
 // in +initialize for each subclass.
 + (GPBDescriptor *)descriptor {
-  static GPBDescriptor *descriptor = NULL;
+  static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
       {
@@ -428,26 +455,29 @@
         .number = GPBBytesValue_FieldNumber_Value,
         .hasIndex = 0,
         .flags = GPBFieldOptional,
-        .type = GPBTypeData,
-        .offset = offsetof(GPBBytesValue_Storage, value),
+        .dataType = GPBDataTypeBytes,
+        .offset = offsetof(GPBBytesValue__storage_, value),
         .defaultValue.valueData = nil,
-        .typeSpecific.className = NULL,
+        .dataTypeSpecific.className = NULL,
         .fieldOptions = NULL,
       },
     };
-    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class]
-                                              rootClass:[GPBWrappersRoot class]
-                                                   file:GPBWrappersRoot_FileDescriptor()
-                                                 fields:fields
-                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
-                                                 oneofs:NULL
-                                             oneofCount:0
-                                                  enums:NULL
-                                              enumCount:0
-                                                 ranges:NULL
-                                             rangeCount:0
-                                            storageSize:sizeof(GPBBytesValue_Storage)
-                                             wireFormat:NO];
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+                                        oneofs:NULL
+                                    oneofCount:0
+                                         enums:NULL
+                                     enumCount:0
+                                        ranges:NULL
+                                    rangeCount:0
+                                   storageSize:sizeof(GPBBytesValue__storage_)
+                                    wireFormat:NO];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
   }
   return descriptor;
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 33894dc..6affcbf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -147,7 +147,7 @@
   google/protobuf/compiler/java/java_names.h                    \
   google/protobuf/compiler/javanano/javanano_generator.h        \
   google/protobuf/compiler/objectivec/objectivec_generator.h    \
-  google/protobuf/compiler/objectivec/objectivec_helpers.h     \
+  google/protobuf/compiler/objectivec/objectivec_helpers.h      \
   google/protobuf/compiler/python/python_generator.h            \
   google/protobuf/compiler/ruby/ruby_generator.h                \
   google/protobuf/compiler/csharp/csharp_generator.h
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index d660969..30a13dd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -55,8 +55,6 @@
       (descriptor->file() != descriptor->enum_type()->file())) {
     (*variables)["property_type"] = "enum " + type;
   }
-  // TODO(thomasvl): Make inclusion of descriptor compile time and output
-  // both of these. Note: Extensions currently have to have the EnumDescription.
   (*variables)["enum_verifier"] = type + "_IsValidValue";
   (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
 
@@ -74,11 +72,9 @@
 
 void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
     io::Printer* printer) const {
-  // TODO(thomasvl): Output the CPP check to use descFunc or validator based
-  // on final compile.
   printer->Print(
       variables_,
-      "  .typeSpecific.enumDescFunc = $enum_desc_func$,\n");
+      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
 }
 
 void EnumFieldGenerator::GenerateCFunctionDeclarations(
@@ -103,7 +99,7 @@
       "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
       "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
       "  GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
-      "  return GPBGetInt32IvarWithField(message, field);\n"
+      "  return GPBGetMessageInt32Field(message, field);\n"
       "}\n"
       "\n"
       "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
@@ -137,11 +133,9 @@
 
 void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
     io::Printer* printer) const {
-  // TODO(thomasvl): Output the CPP check to use descFunc or validator based
-  // on final compile.
   printer->Print(
       variables_,
-      "  .typeSpecific.enumDescFunc = $enum_desc_func$,\n");
+      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 76137c8..4e34839 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -46,24 +46,6 @@
     : method_name_(ExtensionMethodName(descriptor)),
       root_class_and_method_name_(root_class_name + "_" + method_name_),
       descriptor_(descriptor) {
-  // Extensions can be filtered via the method they are accessed off the
-  // file's Root with.
-  if (FilterClass(root_class_and_method_name_)) {
-    filter_reason_ =
-        string("Extension |") + root_class_and_method_name_ + "| was not whitelisted.";
-  } else {
-    // Extensions that add a Message field also require that field be allowed
-    // by the filter, or they aren't usable.
-    ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
-    if (objc_type == OBJECTIVECTYPE_MESSAGE) {
-      const string message_class_name(ClassName(descriptor_->message_type()));
-      if (FilterClass(message_class_name)) {
-        filter_reason_ = string("Extension |") + root_class_and_method_name_ +
-                         "| needs message |" + message_class_name +
-                         "|, which was not whitelisted.";
-      }
-    }
-  }
   if (descriptor->is_map()) {
     // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
     // error cases, so it seems to be ok to use as a back door for errors.
@@ -77,10 +59,6 @@
 ExtensionGenerator::~ExtensionGenerator() {}
 
 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
-  if (IsFiltered()) {
-    printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_);
-    return;
-  }
   map<string, string> vars;
   vars["method_name"] = method_name_;
   SourceLocation location;
@@ -91,15 +69,11 @@
   }
   printer->Print(vars,
                  "$comments$"
-                 "+ (GPBExtensionField*)$method_name$;\n");
+                 "+ (GPBExtensionDescriptor *)$method_name$;\n");
 }
 
 void ExtensionGenerator::GenerateStaticVariablesInitialization(
-    io::Printer* printer, bool* out_generated, bool root) {
-  if (IsFiltered()) {
-    return;
-  }
-  *out_generated = true;
+    io::Printer* printer) {
   map<string, string> vars;
   vars["root_class_and_method_name"] = root_class_and_method_name_;
   vars["extended_type"] = ClassName(descriptor_->containing_type());
@@ -122,14 +96,14 @@
     vars["type"] = "NULL";
   }
 
-  vars["default_name"] = GPBValueFieldName(descriptor_);
+  vars["default_name"] = GPBGenericValueFieldName(descriptor_);
   if (descriptor_->is_repeated()) {
     vars["default"] = "nil";
   } else {
     vars["default"] = DefaultValue(descriptor_);
   }
   string type = GetCapitalizedType(descriptor_);
-  vars["extension_type"] = string("GPBType") + type;
+  vars["extension_type"] = string("GPBDataType") + type;
 
   if (objc_type == OBJECTIVECTYPE_ENUM) {
     vars["enum_desc_func_name"] =
@@ -141,7 +115,7 @@
   printer->Print(vars,
                  "{\n"
                  "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
-                 "  .type = $extension_type$,\n"
+                 "  .dataType = $extension_type$,\n"
                  "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
                  "  .fieldNumber = $number$,\n"
                  "  .defaultValue.$default_name$ = $default$,\n"
@@ -152,9 +126,6 @@
 }
 
 void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
-  if (IsFiltered()) {
-    return;
-  }
   printer->Print(
       "[registry addExtension:$root_class_and_method_name$];\n",
       "root_class_and_method_name", root_class_and_method_name_);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
index 553f088..e361e63 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -52,16 +52,12 @@
   ~ExtensionGenerator();
 
   void GenerateMembersHeader(io::Printer* printer);
-  void GenerateStaticVariablesInitialization(io::Printer* printer,
-                                             bool* out_generated, bool root);
+  void GenerateStaticVariablesInitialization(io::Printer* printer);
   void GenerateRegistrationSource(io::Printer* printer);
 
-  bool IsFiltered() const { return filter_reason_.length() > 0; }
-
  private:
   string method_name_;
   string root_class_and_method_name_;
-  string filter_reason_;
   const FieldDescriptor* descriptor_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index c5f0565..0f96a4e 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -87,18 +87,16 @@
     field_flags.push_back("GPBFieldHasDefaultValue");
   if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
   if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
-  // TODO(thomasvl): Output the CPP check to use descFunc or validator based
-  // on final compile.
     field_flags.push_back("GPBFieldHasEnumDescriptor");
   }
 
   (*variables)["fieldflags"] = BuildFlagsString(field_flags);
 
   (*variables)["default"] = DefaultValue(descriptor);
-  (*variables)["default_name"] = GPBValueFieldName(descriptor);
+  (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
 
-  (*variables)["typeSpecific_name"] = "className";
-  (*variables)["typeSpecific_value"] = "NULL";
+  (*variables)["dataTypeSpecific_name"] = "className";
+  (*variables)["dataTypeSpecific_value"] = "NULL";
 
   string field_options = descriptor->options().SerializeAsString();
   // Must convert to a standard byte order for packing length into
@@ -117,45 +115,6 @@
   (*variables)["storage_attribute"] = "";
 }
 
-// A field generator that writes nothing.
-class EmptyFieldGenerator : public FieldGenerator {
- public:
-  EmptyFieldGenerator(const FieldDescriptor* descriptor, const string& reason)
-      : FieldGenerator(descriptor), reason_(reason) {}
-  virtual ~EmptyFieldGenerator() {}
-
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const {}
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const {
-    string name = FieldName(descriptor_);
-    string type;
-    switch (GetObjectiveCType(descriptor_)) {
-      case OBJECTIVECTYPE_MESSAGE:
-        type = ClassName(descriptor_->message_type()) + " *";
-        break;
-
-      case OBJECTIVECTYPE_ENUM:
-        type = EnumName(descriptor_->enum_type()) + " ";
-        break;
-
-      default:
-        type = string(descriptor_->type_name()) + " ";
-        break;
-    }
-    printer->Print("// Field |$type$$name$| $reason$\n\n", "type", type, "name",
-                   name, "reason", reason_);
-  }
-
-  virtual void GenerateFieldNumberConstant(io::Printer* printer) const {}
-  virtual void GeneratePropertyImplementation(io::Printer* printer) const {}
-  virtual void GenerateFieldDescription(io::Printer* printer) const {}
-
-  virtual bool WantsHasProperty(void) const { return false; }
-
- private:
-  string reason_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EmptyFieldGenerator);
-};
-
 }  // namespace
 
 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
@@ -163,12 +122,7 @@
   if (field->is_repeated()) {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
-        string type = ClassName(field->message_type());
-        if (FilterClass(type)) {
-          string reason =
-              "Filtered by |" + type + "| not being whitelisted.";
-          result = new EmptyFieldGenerator(field, reason);
-        } else if (field->is_map()) {
+        if (field->is_map()) {
           result = new MapFieldGenerator(field);
         } else {
           result = new RepeatedMessageFieldGenerator(field);
@@ -185,14 +139,7 @@
   } else {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
-        string type = ClassName(field->message_type());
-        if (FilterClass(type)) {
-          string reason =
-              "Filtered by |" + type + "| not being whitelisted.";
-          result = new EmptyFieldGenerator(field, reason);
-        } else {
-          result = new MessageFieldGenerator(field);
-        }
+        result = new MessageFieldGenerator(field);
         break;
       }
       case OBJECTIVECTYPE_ENUM:
@@ -249,11 +196,17 @@
       "  .number = $field_number_name$,\n"
       "  .hasIndex = $has_index$,\n"
       "  .flags = $fieldflags$,\n"
-      "  .type = GPBType$field_type$,\n"
-      "  .offset = offsetof($classname$_Storage, $name$),\n"
+      "  .dataType = GPBDataType$field_type$,\n"
+      "  .offset = offsetof($classname$__storage_, $name$),\n"
       "  .defaultValue.$default_name$ = $default$,\n");
 
-  // "  .typeSpecific.value* = [something],"
+  // TODO(thomasvl): It might be useful to add a CPP wrapper to support
+  // compiling away the EnumDescriptors.  To do that, we'd need a #if here
+  // to control setting the descriptor vs. the validator, and above in
+  // SetCommonFieldVariables() we'd want to wrap how we add
+  // GPBFieldHasDefaultValue to the flags.
+
+  // "  .dataTypeSpecific.value* = [something],"
   GenerateFieldDescriptionTypeSpecific(printer);
 
   const string& field_options(variables_.find("fieldoptions")->second);
@@ -280,7 +233,7 @@
     io::Printer* printer) const {
   printer->Print(
       variables_,
-      "  .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n");
+      "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
 }
 
 void FieldGenerator::SetOneofIndexBase(int index_base) {
@@ -410,22 +363,24 @@
 
 void RepeatedFieldGenerator::GeneratePropertyImplementation(
     io::Printer* printer) const {
-  printer->Print(variables_, "@dynamic $name$;\n");
+  printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
 }
 
 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
     io::Printer* printer) const {
 
-  // Repeated fields don't need the has* properties, but this has the same
-  // logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for dealing
-  // with needing Objective C's rules around storage name conventions (init*,
-  // new*, etc.)
+  // Repeated fields don't need the has* properties, but they do expose a
+  // *Count (to check without autocreation).  So for the field property we need
+  // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
+  // dealing with needing Objective C's rules around storage name conventions
+  // (init*, new*, etc.)
 
   printer->Print(
       variables_,
       "$comments$"
       "$array_comment$"
-      "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n");
+      "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n"
+      "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
   if (IsInitName(variables_.find("name")->second)) {
     // 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
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index d04eee8..1955c05 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -54,35 +54,24 @@
 FileGenerator::FileGenerator(const FileDescriptor *file)
     : file_(file),
       root_class_name_(FileClassName(file)),
-      is_filtered_(true),
-      all_extensions_filtered_(true),
       is_public_dep_(false) {
-  // Validate the objc prefix, do this even if the file's contents are filtered
-  // to catch a bad prefix as soon as it is found.
+  // Validate the objc prefix.
   ValidateObjCClassPrefix(file_);
 
   for (int i = 0; i < file_->enum_type_count(); i++) {
     EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
-    // The enums are exposed via C functions, so they will dead strip if
-    // not used.
-    is_filtered_ &= false;
     enum_generators_.push_back(generator);
   }
   for (int i = 0; i < file_->message_type_count(); i++) {
     MessageGenerator *generator =
         new MessageGenerator(root_class_name_, file_->message_type(i));
-    is_filtered_ &= generator->IsFiltered();
-    is_filtered_ &= generator->IsSubContentFiltered();
     message_generators_.push_back(generator);
   }
   for (int i = 0; i < file_->extension_count(); i++) {
     ExtensionGenerator *generator =
         new ExtensionGenerator(root_class_name_, file_->extension(i));
-    is_filtered_ &= generator->IsFiltered();
-    all_extensions_filtered_ &= generator->IsFiltered();
     extension_generators_.push_back(generator);
   }
-  // If there is nothing in the file we filter it.
 }
 
 FileGenerator::~FileGenerator() {
@@ -116,8 +105,7 @@
       "protoc_gen_objc_version",
       SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
 
-  const vector<FileGenerator *> &dependency_generators =
-      DependencyGenerators();
+  const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
   for (vector<FileGenerator *>::const_iterator iter =
            dependency_generators.begin();
        iter != dependency_generators.end(); ++iter) {
@@ -133,19 +121,17 @@
 
   printer->Print("CF_EXTERN_C_BEGIN\n\n");
 
-  if (!IsFiltered()) {
-    set<string> fwd_decls;
-    for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
-         iter != message_generators_.end(); ++iter) {
-      (*iter)->DetermineForwardDeclarations(&fwd_decls);
-    }
-    for (set<string>::const_iterator i(fwd_decls.begin());
-         i != fwd_decls.end(); ++i) {
-      printer->Print("$value$;\n", "value", *i);
-    }
-    if (fwd_decls.begin() != fwd_decls.end()) {
-      printer->Print("\n");
-    }
+  set<string> fwd_decls;
+  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    (*iter)->DetermineForwardDeclarations(&fwd_decls);
+  }
+  for (set<string>::const_iterator i(fwd_decls.begin());
+       i != fwd_decls.end(); ++i) {
+    printer->Print("$value$;\n", "value", *i);
+  }
+  if (fwd_decls.begin() != fwd_decls.end()) {
+    printer->Print("\n");
   }
 
   // need to write out all enums first
@@ -160,36 +146,27 @@
   }
 
   // For extensions to chain together, the Root gets created even if there
-  // are no extensions. So if the entire file isn't filtered away, output it.
-  if (!IsFiltered()) {
-    printer->Print(
-        "\n"
-        "#pragma mark - $root_class_name$\n"
-        "\n"
-        "@interface $root_class_name$ : GPBRootObject\n"
-        "\n"
-        "// The base class provides:\n"
-        "//   + (GPBExtensionRegistry *)extensionRegistry;\n"
-        "// which is an GPBExtensionRegistry that includes all the extensions defined by\n"
-        "// this file and all files that it depends on.\n"
-        "\n"
-        "@end\n"
-        "\n",
-        "root_class_name", root_class_name_);
-  }
+  // are no extensions.
+  printer->Print(
+      "\n"
+      "#pragma mark - $root_class_name$\n"
+      "\n"
+      "@interface $root_class_name$ : GPBRootObject\n"
+      "\n"
+      "// The base class provides:\n"
+      "//   + (GPBExtensionRegistry *)extensionRegistry;\n"
+      "// which is an GPBExtensionRegistry that includes all the extensions defined by\n"
+      "// this file and all files that it depends on.\n"
+      "\n"
+      "@end\n"
+      "\n",
+      "root_class_name", root_class_name_);
 
   if (extension_generators_.size() > 0) {
-    // The dynamic methods block is only needed if there are extensions. If
-    // they are all filtered, output the @interface as a comment so there is
-    // something left in the header for anyone that looks.
-    const char *root_line_prefix = "";
-    if (AreAllExtensionsFiltered()) {
-      root_line_prefix = "// ";
-    }
+    // The dynamic methods block is only needed if there are extensions.
     printer->Print(
-        "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n",
-        "root_class_name", root_class_name_,
-        "root_line_prefix", root_line_prefix);
+        "@interface $root_class_name$ (DynamicMethods)\n",
+        "root_class_name", root_class_name_);
 
     for (vector<ExtensionGenerator *>::iterator iter =
              extension_generators_.begin();
@@ -197,8 +174,7 @@
       (*iter)->GenerateMembersHeader(printer);
     }
 
-    printer->Print("$root_line_prefix$@end\n\n",
-                   "root_line_prefix", root_line_prefix);
+    printer->Print("@end\n\n");
   }  // extension_generators_.size() > 0
 
   for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
@@ -239,136 +215,119 @@
       "// @@protoc_insertion_point(imports)\n"
       "\n");
 
-  if (IsFiltered()) {
-    printer->Print(
-        "// File empty because all messages, extensions and enum have been filtered.\n"
-        "\n"
-        "\n"
-        "// Dummy symbol that will be stripped but will avoid linker warnings about\n"
-        "// no symbols in the .o form compiling this file.\n"
-        "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n"
-        "\n"
-        "// @@protoc_insertion_point(global_scope)\n",
-        "root_class_name", root_class_name_);
-    return;
-  }
-
   printer->Print(
       "#pragma mark - $root_class_name$\n"
       "\n"
       "@implementation $root_class_name$\n\n",
       "root_class_name", root_class_name_);
 
-  bool generated_extensions = false;
-  if (file_->extension_count() + file_->message_type_count() +
-          file_->dependency_count() >
-      0) {
-    ostringstream extensions_stringstream;
+  // Generate the extension initialization structures for the top level and
+  // any nested messages.
+  ostringstream extensions_stringstream;
+  if (file_->extension_count() + file_->message_type_count() > 0) {
+    io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
+    io::Printer extensions_printer(&extensions_outputstream, '$');
+    for (vector<ExtensionGenerator *>::iterator iter =
+             extension_generators_.begin();
+         iter != extension_generators_.end(); ++iter) {
+      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+    }
+    for (vector<MessageGenerator *>::iterator iter =
+             message_generators_.begin();
+         iter != message_generators_.end(); ++iter) {
+      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+    }
+    extensions_stringstream.flush();
+  }
 
-    if (file_->extension_count() + file_->message_type_count() > 0) {
-      io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
-      io::Printer extensions_printer(&extensions_outputstream, '$');
-      extensions_printer.Print(
+  // If there were any extensions or this file has any dependencies, output
+  // a registry to override to create the file specific registry.
+  const string& extensions_str = extensions_stringstream.str();
+  if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+    printer->Print(
+        "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+        "  // This is called by +initialize so there is no need to worry\n"
+        "  // about thread safety and initialization of registry.\n"
+        "  static GPBExtensionRegistry* registry = nil;\n"
+        "  if (!registry) {\n"
+        "    GPBDebugCheckRuntimeVersion();\n"
+        "    registry = [[GPBExtensionRegistry alloc] init];\n");
+
+    printer->Indent();
+    printer->Indent();
+
+    if (extensions_str.length() > 0) {
+      printer->Print(
           "static GPBExtensionDescription descriptions[] = {\n");
-      extensions_printer.Indent();
-      for (vector<ExtensionGenerator *>::iterator iter =
-               extension_generators_.begin();
-           iter != extension_generators_.end(); ++iter) {
-        (*iter)->GenerateStaticVariablesInitialization(
-            &extensions_printer, &generated_extensions, true);
-      }
-      for (vector<MessageGenerator *>::iterator iter =
-               message_generators_.begin();
-           iter != message_generators_.end(); ++iter) {
-        (*iter)->GenerateStaticVariablesInitialization(&extensions_printer,
-                                                       &generated_extensions);
-      }
-      extensions_printer.Outdent();
-      extensions_printer.Print("};\n");
-      if (generated_extensions) {
-        extensions_printer.Print(
-            "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
-            "  GPBExtensionField *extension = [[GPBExtensionField alloc] initWithDescription:&descriptions[i]];\n"
-            "  [registry addExtension:extension];\n"
-            "  [self globallyRegisterExtension:extension];\n"
-            "  [extension release];\n"
-            "}\n");
-      } else {
-        extensions_printer.Print("#pragma unused (descriptions)\n");
-      }
-      const vector<FileGenerator *> &dependency_generators =
-          DependencyGenerators();
-      if (dependency_generators.size()) {
-        for (vector<FileGenerator *>::const_iterator iter =
-                 dependency_generators.begin();
-             iter != dependency_generators.end(); ++iter) {
-          if (!(*iter)->IsFiltered()) {
-            extensions_printer.Print(
-                "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
-                "dependency", (*iter)->RootClassName());
-            generated_extensions = true;
-          }
-        }
-      } else if (!generated_extensions) {
-        extensions_printer.Print("#pragma unused (registry)\n");
-      }
+      printer->Indent();
+      printer->Print(extensions_str.c_str());
+      printer->Outdent();
+      printer->Print(
+          "};\n"
+          "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+          "  GPBExtensionDescriptor *extension =\n"
+          "      [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
+          "  [registry addExtension:extension];\n"
+          "  [self globallyRegisterExtension:extension];\n"
+          "  [extension release];\n"
+          "}\n");
     }
 
-    if (generated_extensions) {
+    const vector<FileGenerator *> &dependency_generators =
+        DependencyGenerators();
+    for (vector<FileGenerator *>::const_iterator iter =
+             dependency_generators.begin();
+         iter != dependency_generators.end(); ++iter) {
       printer->Print(
-          "+ (GPBExtensionRegistry*)extensionRegistry {\n"
-          "  // This is called by +initialize so there is no need to worry\n"
-          "  // about thread safety and initialization of registry.\n"
-          "  static GPBExtensionRegistry* registry = nil;\n"
-          "  if (!registry) {\n"
-          "    registry = [[GPBExtensionRegistry alloc] init];\n");
-
-      printer->Indent();
-      printer->Indent();
-
-      extensions_stringstream.flush();
-      printer->Print(extensions_stringstream.str().c_str());
-      printer->Outdent();
-      printer->Outdent();
-
-      printer->Print(
-          "  }\n"
-          "  return registry;\n"
-          "}\n"
-          "\n");
+          "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+          "dependency", (*iter)->RootClassName());
     }
+
+    printer->Outdent();
+    printer->Outdent();
+
+    printer->Print(
+        "  }\n"
+        "  return registry;\n"
+        "}\n"
+        "\n");
   }
 
   printer->Print("@end\n\n");
 
-
-  string syntax;
-  switch (file_->syntax()) {
-    case FileDescriptor::SYNTAX_UNKNOWN:
-      syntax = "GPBFileSyntaxUnknown";
-      break;
-    case FileDescriptor::SYNTAX_PROTO2:
-      syntax = "GPBFileSyntaxProto2";
-      break;
-    case FileDescriptor::SYNTAX_PROTO3:
-      syntax = "GPBFileSyntaxProto3";
-      break;
+  // File descriptor only needed if there are messages to use it.
+  if (message_generators_.size() > 0) {
+    string syntax;
+    switch (file_->syntax()) {
+      case FileDescriptor::SYNTAX_UNKNOWN:
+        syntax = "GPBFileSyntaxUnknown";
+        break;
+      case FileDescriptor::SYNTAX_PROTO2:
+        syntax = "GPBFileSyntaxProto2";
+        break;
+      case FileDescriptor::SYNTAX_PROTO3:
+        syntax = "GPBFileSyntaxProto3";
+        break;
+    }
+    printer->Print(
+        "#pragma mark - $root_class_name$_FileDescriptor\n"
+        "\n"
+        "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+        "  // This is called by +initialize so there is no need to worry\n"
+        "  // about thread safety of the singleton.\n"
+        "  static GPBFileDescriptor *descriptor = NULL;\n"
+        "  if (!descriptor) {\n"
+        "    GPBDebugCheckRuntimeVersion();\n"
+        "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+        "                                                     syntax:$syntax$];\n"
+        "  }\n"
+        "  return descriptor;\n"
+        "}\n"
+        "\n",
+        "root_class_name", root_class_name_,
+        "package", file_->package(),
+        "syntax", syntax);
   }
-  printer->Print(
-      "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
-      "  // This is called by +initialize so there is no need to worry\n"
-      "  // about thread safety of the singleton.\n"
-      "  static GPBFileDescriptor *descriptor = NULL;\n"
-      "  if (!descriptor) {\n"
-      "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
-      "                                                     syntax:$syntax$];\n"
-      "  }\n"
-      "  return descriptor;\n"
-      "}\n"
-      "\n",
-      "root_class_name", root_class_name_,
-      "package", file_->package(),
-      "syntax", syntax);
 
   for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
        iter != enum_generators_.end(); ++iter) {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index 95d17bf..1bb4f0e 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -64,8 +64,6 @@
   const string& RootClassName() const { return root_class_name_; }
   const string Path() const;
 
-  bool IsFiltered() const { return is_filtered_; }
-  bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; }
   bool IsPublicDependency() const { return is_public_dep_; }
 
  protected:
@@ -84,8 +82,6 @@
   vector<EnumGenerator*> enum_generators_;
   vector<MessageGenerator*> message_generators_;
   vector<ExtensionGenerator*> extension_generators_;
-  bool is_filtered_;
-  bool all_extensions_filtered_;
   bool is_public_dep_;
 
   const vector<FileGenerator*>& DependencyGenerators();
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 1777671..85e438f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -58,10 +58,6 @@
     return false;
   }
 
-  if (!InitializeClassWhitelist(error)) {
-    return false;
-  }
-
   FileGenerator file_generator(file);
 
   string filepath = FilePath(file);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 6d6e595..9b645f0 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -50,8 +50,6 @@
 
 namespace {
 
-hash_set<string> gClassWhitelist;
-
 // islower()/isupper()/tolower()/toupper() change based on locale.
 //
 // src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the
@@ -580,7 +578,7 @@
     case FieldDescriptor::TYPE_STRING:
       return "String";
     case FieldDescriptor::TYPE_BYTES:
-      return "Data";
+      return "Bytes";
     case FieldDescriptor::TYPE_ENUM:
       return "Enum";
     case FieldDescriptor::TYPE_GROUP:
@@ -684,8 +682,9 @@
   }
 }
 
-string GPBValueFieldName(const FieldDescriptor* field) {
-  // Returns the field within the GPBValue union to use for the given field.
+string GPBGenericValueFieldName(const FieldDescriptor* field) {
+  // Returns the field within the GPBGenericValue union to use for the given
+  // field.
   if (field->is_repeated()) {
       return "valueMessage";
   }
@@ -831,60 +830,6 @@
   return final_comments;
 }
 
-bool InitializeClassWhitelist(string* error) {
-  const char* env_var_value = getenv("GPB_OBJC_CLASS_WHITELIST_PATHS");
-  if (env_var_value == NULL) {
-    return true;
-  }
-
-  // The values are joined with ';' in case we ever want to make this a
-  // generator parameter also (instead of env var), and generator parameter
-  // parsing already has meaning for ',' and ':'.
-  vector<string> file_paths = Split(env_var_value, ";", true);
-
-  for (vector<string>::const_iterator i = file_paths.begin();
-       i != file_paths.end(); ++i) {
-    const string& file_path = *i;
-
-    ifstream stream(file_path.c_str(), ifstream::in);
-    if (!stream.good()) {
-      if (error != NULL) {
-        stringstream err_stream;
-        err_stream << endl << file_path << ":0:0: error: Unable to open";
-        *error = err_stream.str();
-        return false;
-      }
-    }
-
-    string input_line;
-    while (stream.good()) {
-      getline(stream, input_line);
-      string trimmed_line(TrimString(input_line));
-      if (trimmed_line.length() == 0) {
-        // Skip empty lines
-        continue;
-      }
-      if (trimmed_line[0] == '/' || trimmed_line[0] == '#') {
-        // Skip comments and potential preprocessor symbols
-        continue;
-      }
-      gClassWhitelist.insert(trimmed_line);
-    }
-  }
-  return true;
-}
-
-bool FilterClass(const string& name) {
-  if (gClassWhitelist.count(name) > 0) {
-    // Whitelisted, don't filter.
-    return false;
-  }
-
-  // If there was no list, default to everything in.
-  // If there was a list, default to everything out.
-  return gClassWhitelist.size() > 0;
-}
-
 void TextFormatDecodeData::AddString(int32 key,
                                      const string& input_for_decode,
                                      const string& desired_output) {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index 1931769..10d51a3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -138,16 +138,13 @@
 bool IsPrimitiveType(const FieldDescriptor* field);
 bool IsReferenceType(const FieldDescriptor* field);
 
-string GPBValueFieldName(const FieldDescriptor* field);
+string GPBGenericValueFieldName(const FieldDescriptor* field);
 string DefaultValue(const FieldDescriptor* field);
 
 string BuildFlagsString(const vector<string>& strings);
 
 string BuildCommentsString(const SourceLocation& location);
 
-bool InitializeClassWhitelist(string* error);
-bool FilterClass(const string& name);
-
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // the input into the the expected output.
 class LIBPROTOC_EXPORT TextFormatDecodeData {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
index b091b77..dc1cef5 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -242,6 +242,14 @@
 }
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
+// TODO(thomasvl): Should probably add some unittests for all the special cases
+// of name mangling (class name, field name, enum names).  Rather than doing
+// this with an ObjC test in the objectivec directory, we should be able to
+// use src/google/protobuf/compiler/importer* (like other tests) to support a
+// virtual file system to feed in protos, once we have the Descriptor tree, the
+// tests could use the helper methods for generating names and validate the
+// right things are happening.
+
 }  // namespace
 }  // namespace objectivec
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 52e583b..32671d4 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -178,49 +178,25 @@
     : root_classname_(root_classname),
       descriptor_(descriptor),
       field_generators_(descriptor),
-      class_name_(ClassName(descriptor_)),
-      sub_content_filtered_(true) {
-  if (FilterClass(class_name_)) {
-    filter_reason_ =
-        string("Message |") + class_name_ + "| was not whitelisted.";
-  }
-  if (!IsFiltered()) {
-    // No need to generate extensions if this message is filtered
-    for (int i = 0; i < descriptor_->extension_count(); i++) {
-      extension_generators_.push_back(
-          new ExtensionGenerator(class_name_, descriptor_->extension(i)));
-    }
-    // No need to generate oneofs if this message is filtered.
-    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-      OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
-      oneof_generators_.push_back(generator);
-    }
+      class_name_(ClassName(descriptor_)) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators_.push_back(
+        new ExtensionGenerator(class_name_, descriptor_->extension(i)));
   }
 
-  // We may have enums of this message that are used even if the message
-  // itself is filtered.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+    oneof_generators_.push_back(generator);
+  }
+
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
-    // The enums are exposed via C functions, so they will dead strip if
-    // not used.
-    sub_content_filtered_ &= false;
     enum_generators_.push_back(generator);
   }
 
-  // We may have nested messages that are used even if the message itself
-  // is filtered.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    const Descriptor* nested_descriptor = descriptor_->nested_type(i);
     MessageGenerator* generator =
-        new MessageGenerator(root_classname_, nested_descriptor);
-    // Don't check map entries for being filtered, as they don't directly
-    // generate anything in Objective C.  In theory, they only should include
-    // references to other toplevel types, but we still make the generators
-    // to be safe.
-    if (!IsMapEntryMessage(nested_descriptor)) {
-      sub_content_filtered_ &= generator->IsFiltered();
-    }
-    sub_content_filtered_ &= generator->IsSubContentFiltered();
+        new MessageGenerator(root_classname_, descriptor_->nested_type(i));
     nested_message_generators_.push_back(generator);
   }
 }
@@ -236,31 +212,26 @@
 }
 
 void MessageGenerator::GenerateStaticVariablesInitialization(
-    io::Printer* printer, bool* out_generated) {
-  if (!IsFiltered()) {
-    // Skip extensions if we are filtered.
-    for (vector<ExtensionGenerator*>::iterator iter =
-             extension_generators_.begin();
-         iter != extension_generators_.end(); ++iter) {
-      (*iter)->GenerateStaticVariablesInitialization(printer, out_generated,
-                                                     false);
-    }
+    io::Printer* printer) {
+  for (vector<ExtensionGenerator*>::iterator iter =
+           extension_generators_.begin();
+       iter != extension_generators_.end(); ++iter) {
+    (*iter)->GenerateStaticVariablesInitialization(printer);
   }
 
-  // Generating sub messages is perfectly fine though.
   for (vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
-    (*iter)->GenerateStaticVariablesInitialization(printer, out_generated);
+    (*iter)->GenerateStaticVariablesInitialization(printer);
   }
 }
 
 void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
-  if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) {
+  if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); 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 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;
       }
@@ -291,12 +262,10 @@
 
 void MessageGenerator::GenerateExtensionRegistrationSource(
     io::Printer* printer) {
-  if (!IsFiltered()) {
-    for (vector<ExtensionGenerator*>::iterator iter =
-             extension_generators_.begin();
-         iter != extension_generators_.end(); ++iter) {
-      (*iter)->GenerateRegistrationSource(printer);
-    }
+  for (vector<ExtensionGenerator*>::iterator iter =
+           extension_generators_.begin();
+       iter != extension_generators_.end(); ++iter) {
+    (*iter)->GenerateRegistrationSource(printer);
   }
 
   for (vector<MessageGenerator*>::iterator iter =
@@ -317,101 +286,84 @@
     return;
   }
 
-  if (IsFiltered()) {
-    printer->Print("// $filter_reason$\n\n",
-                   "filter_reason", filter_reason_);
-  } else {
-    printer->Print(
-        "#pragma mark - $classname$\n"
-        "\n",
-        "classname", class_name_);
+  printer->Print(
+      "#pragma mark - $classname$\n"
+      "\n",
+      "classname", class_name_);
 
-    if (descriptor_->field_count()) {
-      // Even if there are fields, they could be filtered away, so always use
-      // a buffer to confirm we have something.
-      ostringstream fieldnumber_stringstream;
-      {
-        scoped_array<const FieldDescriptor*> sorted_fields(
-            SortFieldsByNumber(descriptor_));
+  if (descriptor_->field_count()) {
+    scoped_array<const FieldDescriptor*> sorted_fields(
+        SortFieldsByNumber(descriptor_));
 
-        io::OstreamOutputStream fieldnumber_outputstream(
-            &fieldnumber_stringstream);
-        io::Printer fieldnumber_printer(&fieldnumber_outputstream, '$');
-        for (int i = 0; i < descriptor_->field_count(); i++) {
-          field_generators_.get(sorted_fields[i])
-              .GenerateFieldNumberConstant(&fieldnumber_printer);
-        }
-        fieldnumber_stringstream.flush();
-      }
-      const string& fieldnumber_str = fieldnumber_stringstream.str();
-      if (fieldnumber_str.length()) {
-        printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
-                       "classname", class_name_);
-        printer->Indent();
-        printer->Print(fieldnumber_str.c_str());
-        printer->Outdent();
-        printer->Print("};\n\n");
-      }
+    printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+                   "classname", class_name_);
+    printer->Indent();
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(sorted_fields[i])
+          .GenerateFieldNumberConstant(printer);
     }
 
+    printer->Outdent();
+    printer->Print("};\n\n");
+  }
+
+  for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+       iter != oneof_generators_.end(); ++iter) {
+    (*iter)->GenerateCaseEnum(printer);
+  }
+
+  string message_comments;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    message_comments = BuildCommentsString(location);
+  } else {
+    message_comments = "";
+  }
+
+  printer->Print(
+      "$comments$@interface $classname$ : GPBMessage\n\n",
+      "classname", class_name_,
+      "comments", message_comments);
+
+  vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() != NULL) {
+      const int oneof_index = field->containing_oneof()->index();
+      if (!seen_oneofs[oneof_index]) {
+        seen_oneofs[oneof_index] = 1;
+        oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+            printer);
+      }
+    }
+    field_generators_.get(field).GeneratePropertyDeclaration(printer);
+  }
+
+  printer->Print("@end\n\n");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateCFunctionDeclarations(printer);
+  }
+
+  if (!oneof_generators_.empty()) {
     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
          iter != oneof_generators_.end(); ++iter) {
-      (*iter)->GenerateCaseEnum(printer);
+      (*iter)->GenerateClearFunctionDeclaration(printer);
     }
+    printer->Print("\n");
+  }
 
-    string message_comments;
-    SourceLocation location;
-    if (descriptor_->GetSourceLocation(&location)) {
-      message_comments = BuildCommentsString(location);
-    } else {
-      message_comments = "";
+  if (descriptor_->extension_count() > 0) {
+    printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+                   "classname", class_name_);
+    for (vector<ExtensionGenerator*>::iterator iter =
+             extension_generators_.begin();
+         iter != extension_generators_.end(); ++iter) {
+      (*iter)->GenerateMembersHeader(printer);
     }
-
-    printer->Print(
-        "$comments$@interface $classname$ : GPBMessage\n\n",
-        "classname", class_name_,
-        "comments", message_comments);
-
-    vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
-      if (field->containing_oneof() != NULL) {
-        const int oneof_index = field->containing_oneof()->index();
-        if (!seen_oneofs[oneof_index]) {
-          seen_oneofs[oneof_index] = 1;
-          oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
-              printer);
-        }
-      }
-      field_generators_.get(field)
-          .GeneratePropertyDeclaration(printer);
-    }
-
     printer->Print("@end\n\n");
-
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(descriptor_->field(i))
-          .GenerateCFunctionDeclarations(printer);
-    }
-
-    if (!oneof_generators_.empty()) {
-      for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
-           iter != oneof_generators_.end(); ++iter) {
-        (*iter)->GenerateClearFunctionDeclaration(printer);
-      }
-      printer->Print("\n");
-    }
-
-    if (descriptor_->extension_count() > 0) {
-      printer->Print("@interface $classname$ (DynamicMethods)\n\n",
-                     "classname", class_name_);
-      for (vector<ExtensionGenerator*>::iterator iter =
-               extension_generators_.begin();
-           iter != extension_generators_.end(); ++iter) {
-        (*iter)->GenerateMembersHeader(printer);
-      }
-      printer->Print("@end\n\n");
-    }
   }
 
   for (vector<MessageGenerator*>::iterator iter =
@@ -422,7 +374,7 @@
 }
 
 void MessageGenerator::GenerateSource(io::Printer* printer) {
-  if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) {
+  if (!IsMapEntryMessage(descriptor_)) {
     printer->Print(
         "#pragma mark - $classname$\n"
         "\n",
@@ -454,6 +406,23 @@
     sort(sorted_extensions.begin(), sorted_extensions.end(),
          ExtensionRangeOrdering());
 
+    // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
+    // follows:
+    // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
+    //    to the field's index in the list of fields.
+    // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
+    //    GPBNoHasBit because repeated fields & map<> fields don't use the has
+    //    bit.
+    // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+    //    index that groups all the elements on of the oneof.
+    // So in has_storage, we need enough bits for the single fields that aren't
+    // in any oneof, and then one int32 for each oneof (to store the field
+    // number).  So we could save a little space by not using the field's index
+    // and instead make a second pass only assigning indexes for the fields
+    // that would need it.  The only savings would come when messages have over
+    // a multiple of 32 fields with some number being repeated or in oneofs to
+    // drop the count below that 32 multiple; so it hasn't seemed worth doing
+    // at the moment.
     size_t num_has_bits = descriptor_->field_count();
     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
     // Tell all the fields the oneof base.
@@ -467,7 +436,7 @@
 
     printer->Print(
         "\n"
-        "typedef struct $classname$_Storage {\n"
+        "typedef struct $classname$__storage_ {\n"
         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
         "classname", class_name_,
         "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
@@ -479,14 +448,14 @@
     }
     printer->Outdent();
 
-    printer->Print("} $classname$_Storage;\n\n", "classname", class_name_);
+    printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
 
 
     printer->Print(
         "// This method is threadsafe because it is initially called\n"
         "// in +initialize for each subclass.\n"
         "+ (GPBDescriptor *)descriptor {\n"
-        "  static GPBDescriptor *descriptor = NULL;\n"
+        "  static GPBDescriptor *descriptor = nil;\n"
         "  if (!descriptor) {\n");
 
     bool has_oneofs = oneof_generators_.size();
@@ -507,30 +476,45 @@
           "    };\n");
     }
 
-    printer->Print(
-        "    static GPBMessageFieldDescription fields[] = {\n");
-    printer->Indent();
-    printer->Indent();
-    printer->Indent();
     TextFormatDecodeData text_format_decode_data;
-    for (int i = 0; i < descriptor_->field_count(); ++i) {
-      const FieldGenerator& field_generator =
-          field_generators_.get(sorted_fields[i]);
-      field_generator.GenerateFieldDescription(printer);
-      if (field_generator.needs_textformat_name_support()) {
-        text_format_decode_data.AddString(sorted_fields[i]->number(),
-                                          field_generator.generated_objc_name(),
-                                          field_generator.raw_field_name());
+    bool has_fields = descriptor_->field_count() > 0;
+    if (has_fields) {
+      // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
+      // wraps the fieldOptions's value of this structure in an CPP gate so
+      // they can be compiled away; but that still results in a const char* in
+      // the structure for a NULL pointer for every message field.  If the
+      // fieldOptions are moved to a separate payload like the TextFormat extra
+      // data is, then it would shrink that static data shrinking the binaries
+      // a little more.
+      // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
+      // structure because primitive types are always zero.  If we add a second
+      // structure and a different initializer, we can avoid the wasted static
+      // storage for every field in a proto3 message.
+      printer->Print(
+          "    static GPBMessageFieldDescription fields[] = {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (int i = 0; i < descriptor_->field_count(); ++i) {
+        const FieldGenerator& field_generator =
+            field_generators_.get(sorted_fields[i]);
+        field_generator.GenerateFieldDescription(printer);
+        if (field_generator.needs_textformat_name_support()) {
+          text_format_decode_data.AddString(sorted_fields[i]->number(),
+                                            field_generator.generated_objc_name(),
+                                            field_generator.raw_field_name());
+        }
       }
+      printer->Outdent();
+      printer->Outdent();
+      printer->Outdent();
+      printer->Print(
+          "    };\n");
     }
-    printer->Outdent();
-    printer->Outdent();
-    printer->Outdent();
 
     bool has_enums = enum_generators_.size();
     if (has_enums) {
       printer->Print(
-          "    };\n"
           "    static GPBMessageEnumDescription enums[] = {\n");
       printer->Indent();
       printer->Indent();
@@ -543,12 +527,13 @@
       printer->Outdent();
       printer->Outdent();
       printer->Outdent();
+      printer->Print(
+          "    };\n");
     }
 
     bool has_extensions = sorted_extensions.size();
     if (has_extensions) {
       printer->Print(
-          "    };\n"
           "    static GPBExtensionRange ranges[] = {\n");
       printer->Indent();
       printer->Indent();
@@ -561,11 +546,16 @@
       printer->Outdent();
       printer->Outdent();
       printer->Outdent();
+      printer->Print(
+          "    };\n");
     }
 
     map<string, string> vars;
     vars["classname"] = class_name_;
     vars["rootclassname"] = root_classname_;
+    vars["fields"] = has_fields ? "fields" : "NULL";
+    vars["fields_count"] =
+        has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
     vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
     vars["oneof_count"] =
         has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
@@ -578,23 +568,23 @@
     vars["wireformat"] =
         descriptor_->options().message_set_wire_format() ? "YES" : "NO";
 
-    printer->Print("    };\n");
     if (text_format_decode_data.num_entries() == 0) {
       printer->Print(
           vars,
-          "    descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
-          "                                              rootClass:[$rootclassname$ class]\n"
-          "                                                   file:$rootclassname$_FileDescriptor()\n"
-          "                                                 fields:fields\n"
-          "                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n"
-          "                                                 oneofs:$oneofs$\n"
-          "                                             oneofCount:$oneof_count$\n"
-          "                                                  enums:$enums$\n"
-          "                                              enumCount:$enum_count$\n"
-          "                                                 ranges:$ranges$\n"
-          "                                             rangeCount:$range_count$\n"
-          "                                            storageSize:sizeof($classname$_Storage)\n"
-          "                                             wireFormat:$wireformat$];\n");
+          "    GPBDescriptor *localDescriptor =\n"
+          "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+          "                                     rootClass:[$rootclassname$ class]\n"
+          "                                          file:$rootclassname$_FileDescriptor()\n"
+          "                                        fields:$fields$\n"
+          "                                    fieldCount:$fields_count$\n"
+          "                                        oneofs:$oneofs$\n"
+          "                                    oneofCount:$oneof_count$\n"
+          "                                         enums:$enums$\n"
+          "                                     enumCount:$enum_count$\n"
+          "                                        ranges:$ranges$\n"
+          "                                    rangeCount:$range_count$\n"
+          "                                   storageSize:sizeof($classname$__storage_)\n"
+          "                                    wireFormat:$wireformat$];\n");
     } else {
       vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
       printer->Print(
@@ -604,26 +594,29 @@
           "#else\n"
           "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
           "#endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
-          "    descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
-          "                                              rootClass:[$rootclassname$ class]\n"
-          "                                                   file:$rootclassname$_FileDescriptor()\n"
-          "                                                 fields:fields\n"
-          "                                             fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n"
-          "                                                 oneofs:$oneofs$\n"
-          "                                             oneofCount:$oneof_count$\n"
-          "                                                  enums:$enums$\n"
-          "                                              enumCount:$enum_count$\n"
-          "                                                 ranges:$ranges$\n"
-          "                                             rangeCount:$range_count$\n"
-          "                                            storageSize:sizeof($classname$_Storage)\n"
-          "                                             wireFormat:$wireformat$\n"
-          "                                    extraTextFormatInfo:extraTextFormatInfo];\n");
+          "    GPBDescriptor *localDescriptor =\n"
+          "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+          "                                     rootClass:[$rootclassname$ class]\n"
+          "                                          file:$rootclassname$_FileDescriptor()\n"
+          "                                        fields:$fields$\n"
+          "                                    fieldCount:$fields_count$\n"
+          "                                        oneofs:$oneofs$\n"
+          "                                    oneofCount:$oneof_count$\n"
+          "                                         enums:$enums$\n"
+          "                                     enumCount:$enum_count$\n"
+          "                                        ranges:$ranges$\n"
+          "                                    rangeCount:$range_count$\n"
+          "                                   storageSize:sizeof($classname$__storage_)\n"
+          "                                    wireFormat:$wireformat$\n"
+          "                           extraTextFormatInfo:extraTextFormatInfo];\n");
       }
       printer->Print(
-        "  }\n"
-        "  return descriptor;\n"
-        "}\n\n"
-        "@end\n\n");
+          "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+          "    descriptor = localDescriptor;\n"
+          "  }\n"
+          "  return descriptor;\n"
+          "}\n\n"
+          "@end\n\n");
 
     for (int i = 0; i < descriptor_->field_count(); i++) {
       field_generators_.get(descriptor_->field(i))
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 8d03c0b..06b536f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -57,20 +57,13 @@
   MessageGenerator(const string& root_classname, const Descriptor* descriptor);
   ~MessageGenerator();
 
-  void GenerateStaticVariablesInitialization(io::Printer* printer,
-                                             bool* out_generated);
+  void GenerateStaticVariablesInitialization(io::Printer* printer);
   void GenerateEnumHeader(io::Printer* printer);
   void GenerateMessageHeader(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
   void GenerateExtensionRegistrationSource(io::Printer* printer);
   void DetermineForwardDeclarations(set<string>* fwd_decls);
 
-  // This only speaks for this message, not sub message/enums.
-  bool IsFiltered() const { return filter_reason_.length() > 0; }
-  // This message being filtered doesn't effect this, instead it covers if
-  // there are any nested messages or enums.
-  bool IsSubContentFiltered() const { return sub_content_filtered_; }
-
  private:
   void GenerateParseFromMethodsHeader(io::Printer* printer);
 
@@ -87,8 +80,6 @@
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
   const string class_name_;
-  string filter_reason_;
-  bool sub_content_filtered_;
   vector<ExtensionGenerator*> extension_generators_;
   vector<EnumGenerator*> enum_generators_;
   vector<MessageGenerator*> nested_message_generators_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index 2e3bdfd..f2ce4e5 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -53,7 +53,7 @@
   (*variables)["group_or_message"] =
       (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
 
-  (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
+  (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
 }
 
 }  // namespace