Răsfoiți Sursa

Merge pull request #8224 from deannagarcia/sync-stage

Integrate from Piper for C++, Java, and Python
deannagarcia 4 ani în urmă
părinte
comite
69694080ff
100 a modificat fișierele cu 2288 adăugiri și 2365 ștergeri
  1. 26 0
      CHANGES.txt
  2. 1 0
      cmake/libprotoc.cmake
  3. 21 24
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  4. 2 0
      java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  5. 32 7
      java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
  6. 210 158
      java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
  7. 12 10
      java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
  8. 6 6
      java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
  9. 14 14
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  10. 1 0
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  11. 2 2
      js/binary/decoder_test.js
  12. 32 9
      python/google/protobuf/descriptor.py
  13. 1 3
      python/google/protobuf/internal/factory_test1.proto
  14. 17 0
      python/google/protobuf/internal/message_factory_test.py
  15. 9 6
      python/google/protobuf/internal/unknown_fields_test.py
  16. 44 19
      python/google/protobuf/message_factory.py
  17. 26 0
      python/google/protobuf/proto_api.h
  18. 114 103
      python/google/protobuf/pyext/message.cc
  19. 46 45
      python/google/protobuf/pyext/message.h
  20. 10 2
      python/google/protobuf/pyext/message_module.cc
  21. 5 1
      python/google/protobuf/pyext/repeated_composite_container.cc
  22. 5 1
      python/google/protobuf/pyext/repeated_scalar_container.cc
  23. 1 14
      python/google/protobuf/service_reflection.py
  24. 4 1
      python/google/protobuf/text_format.py
  25. 1 0
      src/Makefile.am
  26. 24 33
      src/google/protobuf/any.pb.cc
  27. 7 5
      src/google/protobuf/any.pb.h
  28. 1 1
      src/google/protobuf/any_lite.cc
  29. 74 101
      src/google/protobuf/api.pb.cc
  30. 19 15
      src/google/protobuf/api.pb.h
  31. 0 3
      src/google/protobuf/arena.cc
  32. 44 17
      src/google/protobuf/arena.h
  33. 3 3
      src/google/protobuf/arena_impl.h
  34. 12 8
      src/google/protobuf/arenastring.h
  35. 1 0
      src/google/protobuf/arenastring_unittest.cc
  36. 3 3
      src/google/protobuf/compiler/annotation_test_util.cc
  37. 1 1
      src/google/protobuf/compiler/command_line_interface.cc
  38. 16 0
      src/google/protobuf/compiler/cpp/cpp_enum_field.cc
  39. 2 0
      src/google/protobuf/compiler/cpp/cpp_enum_field.h
  40. 6 0
      src/google/protobuf/compiler/cpp/cpp_field.h
  41. 64 178
      src/google/protobuf/compiler/cpp/cpp_file.cc
  42. 0 9
      src/google/protobuf/compiler/cpp/cpp_file.h
  43. 9 7
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  44. 1 18
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  45. 10 0
      src/google/protobuf/compiler/cpp/cpp_map_field.cc
  46. 1 0
      src/google/protobuf/compiler/cpp/cpp_map_field.h
  47. 55 58
      src/google/protobuf/compiler/cpp/cpp_message.cc
  48. 4 0
      src/google/protobuf/compiler/cpp/cpp_message.h
  49. 12 0
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  50. 2 0
      src/google/protobuf/compiler/cpp/cpp_message_field.h
  51. 85 0
      src/google/protobuf/compiler/cpp/cpp_names.h
  52. 2 3
      src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
  53. 16 0
      src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
  54. 2 0
      src/google/protobuf/compiler/cpp/cpp_primitive_field.h
  55. 16 0
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  56. 2 0
      src/google/protobuf/compiler/cpp/cpp_string_field.h
  57. 2 3
      src/google/protobuf/compiler/cpp/metadata_test.cc
  58. 2 2
      src/google/protobuf/compiler/importer.cc
  59. 22 24
      src/google/protobuf/compiler/java/java_enum_field.cc
  60. 21 23
      src/google/protobuf/compiler/java/java_enum_field_lite.cc
  61. 1 1
      src/google/protobuf/compiler/java/java_file.cc
  62. 1 11
      src/google/protobuf/compiler/java/java_helpers.cc
  63. 7 19
      src/google/protobuf/compiler/java/java_helpers.h
  64. 1 0
      src/google/protobuf/compiler/java/java_message.cc
  65. 2 1
      src/google/protobuf/compiler/java/java_name_resolver.cc
  66. 0 12
      src/google/protobuf/compiler/java/java_names.h
  67. 2 3
      src/google/protobuf/compiler/java/java_plugin_unittest.cc
  68. 20 24
      src/google/protobuf/compiler/java/java_primitive_field.cc
  69. 19 23
      src/google/protobuf/compiler/java/java_primitive_field_lite.cc
  70. 1 0
      src/google/protobuf/compiler/java/java_shared_code_generator.cc
  71. 20 25
      src/google/protobuf/compiler/java/java_string_field.cc
  72. 19 24
      src/google/protobuf/compiler/java/java_string_field_lite.cc
  73. 1 1
      src/google/protobuf/compiler/parser_unittest.cc
  74. 80 122
      src/google/protobuf/compiler/plugin.pb.cc
  75. 25 20
      src/google/protobuf/compiler/plugin.pb.h
  76. 5 3
      src/google/protobuf/compiler/python/python_generator.cc
  77. 2 3
      src/google/protobuf/compiler/python/python_plugin_unittest.cc
  78. 22 2
      src/google/protobuf/descriptor.cc
  79. 439 553
      src/google/protobuf/descriptor.pb.cc
  80. 163 135
      src/google/protobuf/descriptor.pb.h
  81. 65 0
      src/google/protobuf/descriptor_unittest.cc
  82. 25 34
      src/google/protobuf/duration.pb.cc
  83. 7 5
      src/google/protobuf/duration.pb.h
  84. 80 145
      src/google/protobuf/dynamic_message.cc
  85. 3 17
      src/google/protobuf/dynamic_message.h
  86. 19 30
      src/google/protobuf/empty.pb.cc
  87. 7 5
      src/google/protobuf/empty.pb.h
  88. 3 6
      src/google/protobuf/extension_set.cc
  89. 12 1
      src/google/protobuf/extension_set.h
  90. 20 31
      src/google/protobuf/field_mask.pb.cc
  91. 7 5
      src/google/protobuf/field_mask.pb.h
  92. 2 5
      src/google/protobuf/generated_message_reflection.cc
  93. 5 6
      src/google/protobuf/generated_message_reflection.h
  94. 8 4
      src/google/protobuf/generated_message_table_driven.h
  95. 5 84
      src/google/protobuf/generated_message_util.cc
  96. 0 58
      src/google/protobuf/generated_message_util.h
  97. 4 4
      src/google/protobuf/has_bits.h
  98. 1 1
      src/google/protobuf/map_type_handler.h
  99. 1 1
      src/google/protobuf/message.cc
  100. 1 1
      src/google/protobuf/message.h

+ 26 - 0
CHANGES.txt

@@ -12,6 +12,22 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
     implementation detail users must not rely on. It should not be used in
     unit tests.
   * Change the signature of Any::PackFrom() to return false on error.
+  * Add fast reflection getter API for strings.
+  * Constant initialize the global message instances
+  * Avoid potential for missed wakeup in UnknownFieldSet
+  * Now Proto3 Oneof fields have "has" methods for checking their presence in
+    C++.
+  * Bugfix for NVCC
+  * Return early in _InternalSerialize for empty maps.
+  * Adding functionality for outputting map key values in proto path logging
+    output (does not affect comparison logic) and stop printing 'value' in the
+    path. The modified print functionality is in the
+    MessageDifferencer::StreamReporter.
+  * Fixes https://github.com/protocolbuffers/protobuf/issues/8129
+  * Ensure that null char symbol, package and file names do not result in a
+    crash.
+  * Constant initialize the global message instances
+  * Pretty print 'max' instead of numeric values in reserved ranges.
 
   Java
   * Avoid possible UnsupportedOperationException when using CodedInputSteam
@@ -19,10 +35,20 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
   * Make Durations.comparator() and Timestamps.comparator() Serializable.
   * Add more detailed error information for dynamic message field type
     validation failure
+  * Removed declarations of functions declared in java_names.h from
+    java_helpers.h.
+  * Now Proto3 Oneof fields have "has" methods for checking their presence in
+    Java.
+  * Annotates Java proto generated *_FIELD_NUMBER constants.
 
   Python
   * Provided an override for the reverse() method that will reverse the internal
     collection directly instead of using the other methods of the BaseContainer.
+  * MessageFactory.CreateProtoype can be overridden to customize class creation.
+
+  Javascript
+  * Generate `getDescriptor` methods with `*` as their `this` type.
+  * Enforce `let/const` for generated messages.
 
 2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
 

+ 1 - 0
cmake/libprotoc.cmake

@@ -93,6 +93,7 @@ set(libprotoc_headers
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_names.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h

+ 21 - 24
java/core/src/main/java/com/google/protobuf/Descriptors.java

@@ -190,7 +190,7 @@ public final class Descriptors {
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof Descriptor && result.getFile() == this) {
+      if (result instanceof Descriptor && result.getFile() == this) {
         return (Descriptor) result;
       } else {
         return null;
@@ -214,7 +214,7 @@ public final class Descriptors {
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof EnumDescriptor && result.getFile() == this) {
+      if (result instanceof EnumDescriptor && result.getFile() == this) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -238,7 +238,7 @@ public final class Descriptors {
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof ServiceDescriptor && result.getFile() == this) {
+      if (result instanceof ServiceDescriptor && result.getFile() == this) {
         return (ServiceDescriptor) result;
       } else {
         return null;
@@ -260,7 +260,7 @@ public final class Descriptors {
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof FieldDescriptor && result.getFile() == this) {
+      if (result instanceof FieldDescriptor && result.getFile() == this) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -338,7 +338,7 @@ public final class Descriptors {
         final Class<?> descriptorOuterClass,
         final String[] dependencyClassNames,
         final String[] dependencyFileNames) {
-      List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> descriptors = new ArrayList<>();
       for (int i = 0; i < dependencyClassNames.length; i++) {
         try {
           Class<?> clazz = descriptorOuterClass.getClassLoader().loadClass(dependencyClassNames[i]);
@@ -507,11 +507,11 @@ public final class Descriptors {
       this.pool = pool;
       this.proto = proto;
       this.dependencies = dependencies.clone();
-      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<String, FileDescriptor>();
+      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<>();
       for (FileDescriptor file : dependencies) {
         nameToFileMap.put(file.getName(), file);
       }
-      List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> publicDependencies = new ArrayList<>();
       for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
         int index = proto.getPublicDependency(i);
         if (index < 0 || index >= proto.getDependencyCount()) {
@@ -758,7 +758,7 @@ public final class Descriptors {
      * y" ranges declared on it.
      */
     public boolean isExtendable() {
-      return proto.getExtensionRangeList().size() != 0;
+      return !proto.getExtensionRangeList().isEmpty();
     }
 
     /**
@@ -772,7 +772,7 @@ public final class Descriptors {
      */
     public FieldDescriptor findFieldByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof FieldDescriptor) {
+      if (result instanceof FieldDescriptor) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -797,7 +797,7 @@ public final class Descriptors {
      */
     public Descriptor findNestedTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof Descriptor) {
+      if (result instanceof Descriptor) {
         return (Descriptor) result;
       } else {
         return null;
@@ -812,7 +812,7 @@ public final class Descriptors {
      */
     public EnumDescriptor findEnumTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumDescriptor) {
+      if (result instanceof EnumDescriptor) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -1701,7 +1701,7 @@ public final class Descriptors {
      */
     public EnumValueDescriptor findValueByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumValueDescriptor) {
+      if (result instanceof EnumValueDescriptor) {
         return (EnumValueDescriptor) result;
       } else {
         return null;
@@ -1785,7 +1785,7 @@ public final class Descriptors {
     private final Descriptor containingType;
     private EnumValueDescriptor[] values;
     private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
-        new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
+        new WeakHashMap<>();
 
     private EnumDescriptor(
         final EnumDescriptorProto proto,
@@ -1991,7 +1991,7 @@ public final class Descriptors {
      */
     public MethodDescriptor findMethodByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof MethodDescriptor) {
+      if (result instanceof MethodDescriptor) {
         return (MethodDescriptor) result;
       } else {
         return null;
@@ -2265,12 +2265,12 @@ public final class Descriptors {
     }
 
     DescriptorPool(final FileDescriptor[] dependencies, boolean allowUnknownDependencies) {
-      this.dependencies = new HashSet<FileDescriptor>();
+      this.dependencies = new HashSet<>();
       this.allowUnknownDependencies = allowUnknownDependencies;
 
-      for (int i = 0; i < dependencies.length; i++) {
-        this.dependencies.add(dependencies[i]);
-        importPublicDependencies(dependencies[i]);
+      for (Descriptors.FileDescriptor dependency : dependencies) {
+        this.dependencies.add(dependency);
+        importPublicDependencies(dependency);
       }
 
       for (final FileDescriptor dependency : this.dependencies) {
@@ -2297,12 +2297,9 @@ public final class Descriptors {
     private final Set<FileDescriptor> dependencies;
     private boolean allowUnknownDependencies;
 
-    private final Map<String, GenericDescriptor> descriptorsByName =
-        new HashMap<String, GenericDescriptor>();
-    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
-        new HashMap<DescriptorIntPair, FieldDescriptor>();
-    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
-        new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+    private final Map<String, GenericDescriptor> descriptorsByName = new HashMap<>();
+    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = new HashMap<>();
+    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = new HashMap<>();
 
     /** Find a generic descriptor by fully-qualified name. */
     GenericDescriptor findSymbol(final String fullName) {

+ 2 - 0
java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java

@@ -266,12 +266,14 @@ public abstract class GeneratedMessageLite<
     memoizedSerializedSize = size;
   }
 
+  @Override
   public void writeTo(CodedOutputStream output) throws IOException {
     Protobuf.getInstance()
         .schemaFor(this)
         .writeTo(this, CodedOutputStreamWriter.forCodedOutput(output));
   }
 
+  @Override
   public int getSerializedSize() {
     if (memoizedSerializedSize == -1) {
       memoizedSerializedSize = Protobuf.getInstance().schemaFor(this).getSerializedSize(this);

+ 32 - 7
java/core/src/main/java/com/google/protobuf/RawMessageInfo.java

@@ -80,14 +80,15 @@ final class RawMessageInfo implements MessageInfo {
    *   <li>[1]: field type with extra bits:
    *       <ul>
    *         <li>v & 0xFF = field type as defined in the FieldType class
-   *         <li>v & 0x100 = is required?
-   *         <li>v & 0x200 = is checkUtf8?
-   *         <li>v & 0x400 = needs isInitialized check?
-   *         <li>v & 0x800 = is map field with proto2 enum value?
+   *         <li>v & 0x0100 = is required?
+   *         <li>v & 0x0200 = is checkUtf8?
+   *         <li>v & 0x0400 = needs isInitialized check?
+   *         <li>v & 0x0800 = is map field with proto2 enum value?
+   *         <li>v & 0x1000 = supports presence checking?
    *       </ul>
    * </ul>
    *
-   * If the file is proto2 and this is a singular field:
+   * If the (singular) field supports presence checking:
    *
    * <ul>
    *   <li>[2]: hasbits offset
@@ -180,8 +181,32 @@ final class RawMessageInfo implements MessageInfo {
     this.defaultInstance = defaultInstance;
     this.info = info;
     this.objects = objects;
-    int position = 0;
-    int value = (int) info.charAt(position++);
+    int value;
+    try {
+      value = (int) info.charAt(0);
+    } catch (ArrayIndexOutOfBoundsException e) {
+      // This is a fix for issues
+      // that error out on a subset of phones on charAt(0) with an index out of bounds exception.
+      char[] infoChars = info.toCharArray();
+      info = new String(infoChars);
+      try {
+        value = (int) info.charAt(0);
+      } catch (ArrayIndexOutOfBoundsException e2) {
+        try {
+          char[] infoChars2 = new char[info.length()];
+          info.getChars(0, info.length(), infoChars2, 0);
+          info = new String(infoChars2);
+          value = (int) info.charAt(0);
+        } catch (ArrayIndexOutOfBoundsException e3) {
+          throw new IllegalStateException(
+              String.format(
+                  "Failed parsing '%s' with charArray.length of %d", info, infoChars.length),
+              e3);
+        }
+      }
+    }
+    int position = 1;
+
     if (value < 0xD800) {
       flags = value;
     } else {

+ 210 - 158
java/core/src/main/java/com/google/protobuf/UnsafeUtil.java

@@ -332,83 +332,18 @@ final class UnsafeUtil {
     return new JvmMemoryAccessor(UNSAFE);
   }
 
-  /** Indicates whether or not unsafe array operations are supported on this platform. */
   private static boolean supportsUnsafeArrayOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("arrayBaseOffset", Class.class);
-      clazz.getMethod("arrayIndexScale", Class.class);
-      clazz.getMethod("getInt", Object.class, long.class);
-      clazz.getMethod("putInt", Object.class, long.class, int.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-      clazz.getMethod("putLong", Object.class, long.class, long.class);
-      clazz.getMethod("getObject", Object.class, long.class);
-      clazz.getMethod("putObject", Object.class, long.class, Object.class);
-      if (Android.isOnAndroidDevice()) {
-        return true;
-      }
-      clazz.getMethod("getByte", Object.class, long.class);
-      clazz.getMethod("putByte", Object.class, long.class, byte.class);
-      clazz.getMethod("getBoolean", Object.class, long.class);
-      clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
-      clazz.getMethod("getFloat", Object.class, long.class);
-      clazz.getMethod("putFloat", Object.class, long.class, float.class);
-      clazz.getMethod("getDouble", Object.class, long.class);
-      clazz.getMethod("putDouble", Object.class, long.class, double.class);
-
-      return true;
-    } catch (Throwable e) {
-      // Because log statements are fairly sparse in this class, this logger is initialized
-      // non-statically. Static initialization adds undue runtime costs to the first client to
-      // initialize this class.
-      Logger.getLogger(UnsafeUtil.class.getName())
-          .log(
-              Level.WARNING,
-              "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeArrayOperations();
   }
 
   private static boolean supportsUnsafeByteBufferOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      // Methods for getting direct buffer address.
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-
-      if (bufferAddressField() == null) {
-        return false;
-      }
-
-      if (Android.isOnAndroidDevice()) {
-        return false;
-      }
-      clazz.getMethod("getByte", long.class);
-      clazz.getMethod("putByte", long.class, byte.class);
-      clazz.getMethod("getInt", long.class);
-      clazz.getMethod("putInt", long.class, int.class);
-      clazz.getMethod("getLong", long.class);
-      clazz.getMethod("putLong", long.class, long.class);
-      clazz.getMethod("copyMemory", long.class, long.class, long.class);
-      clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
-      return true;
-    } catch (Throwable e) {
-      // Because log statements are fairly sparse in this class, this logger is initialized
-      // non-statically. Static initialization adds undue runtime costs to the first client to
-      // initialize this class.
-      Logger.getLogger(UnsafeUtil.class.getName())
-          .log(
-              Level.WARNING,
-              "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeByteBufferOperations();
   }
 
   private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
@@ -553,6 +488,43 @@ final class UnsafeUtil {
       return unsafe.objectFieldOffset(field);
     }
 
+    public final int arrayBaseOffset(Class<?> clazz) {
+      return unsafe.arrayBaseOffset(clazz);
+    }
+
+    public final int arrayIndexScale(Class<?> clazz) {
+      return unsafe.arrayIndexScale(clazz);
+    }
+
+    public abstract Object getStaticObject(Field field);
+
+    // Relative Address Operations ---------------------------------------------
+
+    // Indicates whether the following relative address operations are supported
+    // by this memory accessor.
+    public boolean supportsUnsafeArrayOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("arrayBaseOffset", Class.class);
+        clazz.getMethod("arrayIndexScale", Class.class);
+        clazz.getMethod("getInt", Object.class, long.class);
+        clazz.getMethod("putInt", Object.class, long.class, int.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+        clazz.getMethod("putLong", Object.class, long.class, long.class);
+        clazz.getMethod("getObject", Object.class, long.class);
+        clazz.getMethod("putObject", Object.class, long.class, Object.class);
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
+    }
+
     public abstract byte getByte(Object target, long offset);
 
     public abstract void putByte(Object target, long offset, byte value);
@@ -593,12 +565,29 @@ final class UnsafeUtil {
       unsafe.putObject(target, offset, value);
     }
 
-    public final int arrayBaseOffset(Class<?> clazz) {
-      return unsafe.arrayBaseOffset(clazz);
-    }
+    // Absolute Address Operations --------------------------------------------
 
-    public final int arrayIndexScale(Class<?> clazz) {
-      return unsafe.arrayIndexScale(clazz);
+    // Indicates whether the following absolute address operations are
+    // supported by this memory accessor.
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        // Methods for getting direct buffer address.
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+
+        if (bufferAddressField() == null) {
+          return false;
+        }
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     public abstract byte getByte(long address);
@@ -613,8 +602,6 @@ final class UnsafeUtil {
 
     public abstract void putLong(long address, long value);
 
-    public abstract Object getStaticObject(Field field);
-
     public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
 
     public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
@@ -627,33 +614,32 @@ final class UnsafeUtil {
     }
 
     @Override
-    public byte getByte(long address) {
-      return unsafe.getByte(address);
-    }
-
-    @Override
-    public void putByte(long address, byte value) {
-      unsafe.putByte(address, value);
-    }
-
-    @Override
-    public int getInt(long address) {
-      return unsafe.getInt(address);
+    public Object getStaticObject(Field field) {
+      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
     }
 
     @Override
-    public void putInt(long address, int value) {
-      unsafe.putInt(address, value);
-    }
+    public boolean supportsUnsafeArrayOperations() {
+      if (!super.supportsUnsafeArrayOperations()) {
+        return false;
+      }
 
-    @Override
-    public long getLong(long address) {
-      return unsafe.getLong(address);
-    }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", Object.class, long.class);
+        clazz.getMethod("putByte", Object.class, long.class, byte.class);
+        clazz.getMethod("getBoolean", Object.class, long.class);
+        clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
+        clazz.getMethod("getFloat", Object.class, long.class);
+        clazz.getMethod("putFloat", Object.class, long.class, float.class);
+        clazz.getMethod("getDouble", Object.class, long.class);
+        clazz.getMethod("putDouble", Object.class, long.class, double.class);
 
-    @Override
-    public void putLong(long address, long value) {
-      unsafe.putLong(address, value);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     @Override
@@ -697,55 +683,83 @@ final class UnsafeUtil {
     }
 
     @Override
-    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
-      unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (!super.supportsUnsafeByteBufferOperations()) {
+        return false;
+      }
+
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", long.class);
+        clazz.getMethod("putByte", long.class, byte.class);
+        clazz.getMethod("getInt", long.class);
+        clazz.getMethod("putInt", long.class, int.class);
+        clazz.getMethod("getLong", long.class);
+        clazz.getMethod("putLong", long.class, long.class);
+        clazz.getMethod("copyMemory", long.class, long.class, long.class);
+        clazz.getMethod(
+            "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     @Override
-    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
-      unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
+    public byte getByte(long address) {
+      return unsafe.getByte(address);
     }
 
     @Override
-    public Object getStaticObject(Field field) {
-      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
+    public void putByte(long address, byte value) {
+      unsafe.putByte(address, value);
     }
-  }
-
-  private static final class Android64MemoryAccessor extends MemoryAccessor {
 
-    Android64MemoryAccessor(sun.misc.Unsafe unsafe) {
-      super(unsafe);
+    @Override
+    public int getInt(long address) {
+      return unsafe.getInt(address);
     }
 
     @Override
-    public byte getByte(long address) {
-      throw new UnsupportedOperationException();
+    public void putInt(long address, int value) {
+      unsafe.putInt(address, value);
     }
 
     @Override
-    public void putByte(long address, byte value) {
-      throw new UnsupportedOperationException();
+    public long getLong(long address) {
+      return unsafe.getLong(address);
     }
 
     @Override
-    public int getInt(long address) {
-      throw new UnsupportedOperationException();
+    public void putLong(long address, long value) {
+      unsafe.putLong(address, value);
     }
 
     @Override
-    public void putInt(long address, int value) {
-      throw new UnsupportedOperationException();
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
     }
 
     @Override
-    public long getLong(long address) {
-      throw new UnsupportedOperationException();
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
+    }
+  }
+
+  private static final class Android64MemoryAccessor extends MemoryAccessor {
+
+    Android64MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
     }
 
     @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -805,67 +819,72 @@ final class UnsafeUtil {
     }
 
     @Override
-    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
-      throw new UnsupportedOperationException();
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
     }
 
     @Override
-    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+    public byte getByte(long address) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
-    }
-  }
-
-  private static final class Android32MemoryAccessor extends MemoryAccessor {
-
-    /** Mask used to convert a 64 bit memory address to a 32 bit address. */
-    private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF;
-
-    /** Truncate a {@code long} address into a short {@code int} address. */
-    private static int smallAddress(long address) {
-      return (int) (SMALL_ADDRESS_MASK & address);
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
     }
 
-    Android32MemoryAccessor(sun.misc.Unsafe unsafe) {
-      super(unsafe);
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
     }
 
     @Override
-    public byte getByte(long address) {
+    public void putInt(long address, int value) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public void putByte(long address, byte value) {
+    public long getLong(long address) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public int getInt(long address) {
+    public void putLong(long address, long value) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public void putInt(long address, int value) {
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public long getLong(long address) {
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       throw new UnsupportedOperationException();
     }
+  }
+
+  private static final class Android32MemoryAccessor extends MemoryAccessor {
+
+    /** Mask used to convert a 64 bit memory address to a 32 bit address. */
+    private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF;
+
+    /** Truncate a {@code long} address into a short {@code int} address. */
+    private static int smallAddress(long address) {
+      return (int) (SMALL_ADDRESS_MASK & address);
+    }
+
+    Android32MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
+    }
 
     @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -925,22 +944,48 @@ final class UnsafeUtil {
     }
 
     @Override
-    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+    public void putByte(long address, byte value) {
       throw new UnsupportedOperationException();
     }
 
     @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      throw new UnsupportedOperationException();
     }
   }
 
@@ -981,4 +1026,11 @@ final class UnsafeUtil {
   private static void putBooleanLittleEndian(Object target, long offset, boolean value) {
     putByteLittleEndian(target, offset, (byte) (value ? 1 : 0));
   }
+
+  private static void logMissingMethod(Throwable e) {
+    Logger.getLogger(UnsafeUtil.class.getName())
+        .log(
+            Level.WARNING,
+            "platform method missing - proto runtime falling back to safer methods: " + e);
+  }
 }

+ 12 - 10
java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java

@@ -66,6 +66,11 @@ public class FieldPresenceTest extends TestCase {
     assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName));
   }
 
+  private static void assertHasMethodExisting(Class<?> clazz, String camelName) {
+    assertTrue(hasMethod(clazz, "get" + camelName));
+    assertTrue(hasMethod(clazz, "has" + camelName));
+  }
+
   public void testHasMethod() {
     // Optional non-message fields don't have a hasFoo() method generated.
     assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalInt32");
@@ -87,19 +92,16 @@ public class FieldPresenceTest extends TestCase {
     assertFalse(TestAllTypes.getDefaultInstance().hasOptionalNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
 
-    // oneof fields don't have hasFoo() methods for non-message types.
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofUint32");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofString");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofBytes");
+    // oneof fields support hasFoo() methods for non-message types.
+    assertHasMethodExisting(TestAllTypes.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.class, "OneofBytes");
     assertFalse(TestAllTypes.getDefaultInstance().hasOneofNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage());
 
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofUint32");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofString");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofBytes");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofBytes");
   }
 
   public void testHasMethodForProto3Optional() throws Exception {

+ 6 - 6
java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java

@@ -139,12 +139,12 @@ public final class Proto3MessageLiteInfoFactory implements MessageInfoFactory {
     // the content of the generated buildMessageInfo() method here.
     java.lang.String info =
         "\u0000@\u0001\u0000\u0001D@\u0000\u001f\u0000\u0001\u0000\u0002\u0001\u0003\u0002"
-            + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
-            + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
-            + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
-            + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
-            + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
-            + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
+        + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
+        + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
+        + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
+        + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
+        + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
+        + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
     return new RawMessageInfo(Proto3MessageLite.getDefaultInstance(), info, objects);
   }
 

+ 14 - 14
java/core/src/test/java/com/google/protobuf/TextFormatTest.java

@@ -1507,9 +1507,9 @@ public class TextFormatTest extends TestCase {
             + "  value: -1\n"
             + "}\n";
     TestMap msg = TextFormat.parse(input, TestMap.class);
-    int i1 = msg.getInt32ToInt32Field().get(1);
+    int i1 = msg.getInt32ToInt32FieldMap().get(1);
     TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class);
-    int i2 = msg2.getInt32ToInt32Field().get(1);
+    int i2 = msg2.getInt32ToInt32FieldMap().get(1);
     assertEquals(i1, i2);
   }
 
@@ -1521,10 +1521,10 @@ public class TextFormatTest extends TestCase {
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(2, message.getStringToInt32Field().size());
-    assertEquals(2, message.getInt32ToMessageField().size());
-    assertEquals(10, message.getStringToInt32Field().get("x").intValue());
-    assertEquals(200, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(2, message.getStringToInt32FieldMap().size());
+    assertEquals(2, message.getInt32ToMessageFieldMap().size());
+    assertEquals(10, message.getStringToInt32FieldMap().get("x").intValue());
+    assertEquals(200, message.getInt32ToMessageFieldMap().get(2).getValue());
   }
 
   public void testMapShortFormEmpty() throws Exception {
@@ -1532,8 +1532,8 @@ public class TextFormatTest extends TestCase {
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(0, message.getStringToInt32Field().size());
-    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32FieldMap().size());
+    assertEquals(0, message.getInt32ToMessageFieldMap().size());
   }
 
   public void testMapShortFormTrailingComma() throws Exception {
@@ -1558,8 +1558,8 @@ public class TextFormatTest extends TestCase {
       TestMap.Builder builder = TestMap.newBuilder();
       defaultParser.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
 
     {
@@ -1568,8 +1568,8 @@ public class TextFormatTest extends TestCase {
       TestMap.Builder builder = TestMap.newBuilder();
       parserWithOverwriteForbidden.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
 
     {
@@ -1580,8 +1580,8 @@ public class TextFormatTest extends TestCase {
       TestMap map =
           TestMap.parseFrom(
               builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry());
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
   }
 

+ 1 - 0
java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java

@@ -1697,6 +1697,7 @@ public class JsonFormatTest extends TestCase {
   public void testJsonException() throws Exception {
     InputStream throwingInputStream =
         new InputStream() {
+          @Override
           public int read() throws IOException {
             throw new IOException("12345");
           }

+ 2 - 2
js/binary/decoder_test.js

@@ -315,8 +315,8 @@ describe('binaryDecoderTest', function() {
         // 64-bit extremes, not in dev guide.
         {original: '9223372036854775807', zigzag: '18446744073709551614'},
         {original: '-9223372036854775808', zigzag: '18446744073709551615'},
-        // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh < 0x1FFFFF.
-        // The following used to be broken.
+        // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh <
+        // 0x1FFFFF. The following used to be broken.
         {original: '72000000000', zigzag: '144000000000'},
       ];
       var encoder = new jspb.BinaryEncoder();

+ 32 - 9
python/google/protobuf/descriptor.py

@@ -287,12 +287,26 @@ class Descriptor(_NestedDescriptorBase):
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.Descriptor
 
-    def __new__(cls, name, full_name, filename, containing_type, fields,
-                nested_types, enum_types, extensions, options=None,
-                serialized_options=None,
-                is_extendable=True, extension_ranges=None, oneofs=None,
-                file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
-                syntax=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        filename=None,
+        containing_type=None,
+        fields=None,
+        nested_types=None,
+        enum_types=None,
+        extensions=None,
+        options=None,
+        serialized_options=None,
+        is_extendable=True,
+        extension_ranges=None,
+        oneofs=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        syntax=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()
       return _message.default_pool.FindMessageTypeByName(full_name)
 
@@ -799,9 +813,18 @@ class ServiceDescriptor(_NestedDescriptorBase):
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
 
-    def __new__(cls, name, full_name, index, methods, options=None,
-                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
-                serialized_start=None, serialized_end=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        index=None,
+        methods=None,
+        options=None,
+        serialized_options=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
       return _message.default_pool.FindServiceByName(full_name)
 

+ 1 - 3
python/google/protobuf/internal/factory_test1.proto

@@ -34,7 +34,6 @@ syntax = "proto2";
 
 package google.protobuf.python.internal;
 
-
 enum Factory1Enum {
   FACTORY_1_VALUE_0 = 0;
   FACTORY_1_VALUE_1 = 1;
@@ -67,6 +66,5 @@ message Factory1MethodResponse {
 
 service Factory1Service {
   // Dummy method for this dummy service.
-  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {
-  }
+  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {}
 }

+ 17 - 0
python/google/protobuf/internal/message_factory_test.py

@@ -106,6 +106,23 @@ class MessageFactoryTest(unittest.TestCase):
         'google.protobuf.python.internal.Factory2Message'))
     self.assertTrue(cls is cls2)
 
+  def testCreatePrototypeOverride(self):
+    class MyMessageFactory(message_factory.MessageFactory):
+
+      def CreatePrototype(self, descriptor):
+        cls = super(MyMessageFactory, self).CreatePrototype(descriptor)
+        cls.additional_field = 'Some value'
+        return cls
+
+    db = descriptor_database.DescriptorDatabase()
+    pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    factory = MyMessageFactory()
+    cls = factory.GetPrototype(pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertTrue(hasattr(cls, 'additional_field'))
+
   def testGetMessages(self):
     # performed twice because multiple calls with the same input must be allowed
     for _ in range(2):

+ 9 - 6
python/google/protobuf/internal/unknown_fields_test.py

@@ -40,11 +40,6 @@ try:
 except ImportError:
   import unittest
 import sys
-try:
-  import tracemalloc
-except ImportError:
-  # Requires python 3.4+
-  pass
 from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
@@ -59,6 +54,12 @@ from google.protobuf.internal import type_checkers
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor
 
+try:
+  import tracemalloc  # pylint: disable=g-import-not-at-top
+except ImportError:
+  # Requires python 3.4+
+  pass
+
 
 @testing_refleaks.TestCase
 class UnknownFieldsTest(unittest.TestCase):
@@ -318,14 +319,16 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
     self.assertIn('UnknownFields does not exist.',
                   str(context.exception))
 
-  @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4), 
+  @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4),
                    'tracemalloc requires python 3.4+')
   def testUnknownFieldsNoMemoryLeak(self):
     # Call to UnknownFields must not leak memory
     nb_leaks = 1234
+
     def leaking_function():
       for _ in range(nb_leaks):
         self.empty_message.UnknownFields()
+
     tracemalloc.start()
     snapshot1 = tracemalloc.take_snapshot()
     leaking_function()

+ 44 - 19
python/google/protobuf/message_factory.py

@@ -64,7 +64,7 @@ class MessageFactory(object):
     self._classes = {}
 
   def GetPrototype(self, descriptor):
-    """Builds a proto2 message class based on the passed in descriptor.
+    """Obtains a proto2 message class based on the passed in descriptor.
 
     Passing a descriptor with a fully qualified name matching a previous
     invocation will cause the same class to be returned.
@@ -76,27 +76,52 @@ class MessageFactory(object):
       A class describing the passed in descriptor.
     """
     if descriptor not in self._classes:
-      descriptor_name = descriptor.name
-      if str is bytes:  # PY2
-        descriptor_name = descriptor.name.encode('ascii', 'ignore')
-      result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
-          descriptor_name,
-          (message.Message,),
-          {'DESCRIPTOR': descriptor, '__module__': None})
-      # pylint: disable=protected-access
-      result_class._FACTORY = self
-      # If module not set, it wrongly points to message_factory module.
+      result_class = self.CreatePrototype(descriptor)
+      # The assignment to _classes is redundant for the base implementation, but
+      # might avoid confusion in cases where CreatePrototype gets overridden and
+      # does not call the base implementation.
       self._classes[descriptor] = result_class
-      for field in descriptor.fields:
-        if field.message_type:
-          self.GetPrototype(field.message_type)
-      for extension in result_class.DESCRIPTOR.extensions:
-        if extension.containing_type not in self._classes:
-          self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type]
-        extended_class.RegisterExtension(extension)
+      return result_class
     return self._classes[descriptor]
 
+  def CreatePrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Don't call this function directly, it always creates a new class. Call
+    GetPrototype() instead. This method is meant to be overridden in subblasses
+    to perform additional operations on the newly constructed class.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+    descriptor_name = descriptor.name
+    if str is bytes:  # PY2
+      descriptor_name = descriptor.name.encode('ascii', 'ignore')
+    result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
+        descriptor_name,
+        (message.Message,),
+        {
+            'DESCRIPTOR': descriptor,
+            # If module not set, it wrongly points to message_factory module.
+            '__module__': None,
+        })
+    result_class._FACTORY = self  # pylint: disable=protected-access
+    # Assign in _classes before doing recursive calls to avoid infinite
+    # recursion.
+    self._classes[descriptor] = result_class
+    for field in descriptor.fields:
+      if field.message_type:
+        self.GetPrototype(field.message_type)
+    for extension in result_class.DESCRIPTOR.extensions:
+      if extension.containing_type not in self._classes:
+        self.GetPrototype(extension.containing_type)
+      extended_class = self._classes[extension.containing_type]
+      extended_class.RegisterExtension(extension)
+    return result_class
+
   def GetMessages(self, files):
     """Gets all the messages from a specified file.
 

+ 26 - 0
python/google/protobuf/proto_api.h

@@ -82,6 +82,32 @@ struct PyProto_API {
   // to create Python-compatible message.
   virtual const DescriptorPool* GetDefaultDescriptorPool() const = 0;
   virtual MessageFactory* GetDefaultMessageFactory() const = 0;
+
+  // Allocate a new protocol buffer as a python object for the provided
+  // descriptor. This function works even if no Python module has been imported
+  // for the corresponding protocol buffer class.
+  // The factory is usually null; when provided, it is the MessageFactory which
+  // owns the Python class, and will be used to find and create Extensions for
+  // this message.
+  // When null is returned, a python error has already been set.
+  virtual PyObject* NewMessage(const Descriptor* descriptor,
+                               PyObject* py_message_factory) const = 0;
+
+  // Allocate a new protocol buffer where the underlying object is owned by C++.
+  // The factory must currently be null.  This function works even if no Python
+  // module has been imported for the corresponding protocol buffer class.
+  // When null is returned, a python error has already been set.
+  //
+  // Since this call returns a python object owned by C++, some operations
+  // are risky, and it must be used carefully. In particular:
+  // * Avoid modifying the returned object from the C++ side while there are
+  // existing python references to it or it's subobjects.
+  // * Avoid using python references to this object or any subobjects after the
+  // C++ object has been freed.
+  // * Calling this with the same C++ pointer will result in multiple distinct
+  // python objects referencing the same C++ object.
+  virtual PyObject* NewMessageOwnedExternally(
+      Message* msg, PyObject* py_message_factory) const = 0;
 };
 
 inline const char* PyProtoAPICapsuleName() {

+ 114 - 103
python/google/protobuf/pyext/message.cc

@@ -121,7 +121,7 @@ inline void LowerString(std::string* s) {
     if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
   }
 }
-}
+}  // namespace
 
 // Finalize the creation of the Message class.
 static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
@@ -145,7 +145,7 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
         PyEnumDescriptor_FromDescriptor(enum_descriptor));
     if (enum_type == NULL) {
       return -1;
-     }
+    }
     // Add wrapped enum type to message class.
     ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
         EnumTypeWrapper_class, enum_type.get(), NULL));
@@ -195,8 +195,7 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
   return 0;
 }
 
-static PyObject* New(PyTypeObject* type,
-                     PyObject* args, PyObject* kwargs) {
+static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
   static char *kwlist[] = {"name", "bases", "dict", 0};
   PyObject *bases, *dict;
   const char* name;
@@ -219,41 +218,20 @@ static PyObject* New(PyTypeObject* type,
   }
 
   // Check dict['DESCRIPTOR']
-  PyObject* descriptor_or_name = PyDict_GetItem(dict, kDESCRIPTOR);
-  if (descriptor_or_name == nullptr) {
+  PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+  if (py_descriptor == nullptr) {
     PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
-    return NULL;
+    return nullptr;
   }
-
-  Py_ssize_t name_size;
-  char* full_name;
-  const Descriptor* message_descriptor;
-  PyObject* py_descriptor;
-
-  if (PyObject_TypeCheck(descriptor_or_name, &PyMessageDescriptor_Type)) {
-    py_descriptor = descriptor_or_name;
-    message_descriptor = PyMessageDescriptor_AsDescriptor(py_descriptor);
-    if (message_descriptor == nullptr) {
-      return nullptr;
-    }
-  } else {
-    if (PyString_AsStringAndSize(descriptor_or_name, &full_name, &name_size) <
-        0) {
-      return nullptr;
-    }
-    message_descriptor =
-        GetDefaultDescriptorPool()->pool->FindMessageTypeByName(
-            StringParam(full_name, name_size));
-    if (message_descriptor == nullptr) {
-      PyErr_Format(PyExc_KeyError,
-                   "Can not find message descriptor %s "
-                   "from pool",
-                   full_name);
-      return nullptr;
-    }
-    py_descriptor = PyMessageDescriptor_FromDescriptor(message_descriptor);
-    // reset the dict['DESCRIPTOR'] to py_descriptor.
-    PyDict_SetItem(dict, kDESCRIPTOR, py_descriptor);
+  if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) {
+    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+                 py_descriptor->ob_type->tp_name);
+    return nullptr;
+  }
+  const Descriptor* message_descriptor =
+      PyMessageDescriptor_AsDescriptor(py_descriptor);
+  if (message_descriptor == nullptr) {
+    return nullptr;
   }
 
   // Messages have no __dict__
@@ -603,15 +581,15 @@ bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) {
       OutOfRangeError(arg);
     }  // Otherwise propagate existing error.
     return false;
-    }
-    if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
-      OutOfRangeError(arg);
-      return false;
-    }
+  }
+  if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
+    OutOfRangeError(arg);
+    return false;
+  }
   return true;
 }
 
-template<class T>
+template <class T>
 bool CheckAndGetInteger(PyObject* arg, T* value) {
   // The fast path.
 #if PY_MAJOR_VERSION < 3
@@ -631,10 +609,10 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
   // an integer and can be used as an ordinal number".
   // This definition includes everything that implements numbers.Integral
   // and shouldn't cast the net too wide.
-    if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
-      FormatTypeError(arg, "int, long");
-      return false;
-    }
+  if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
+    FormatTypeError(arg, "int, long");
+    return false;
+  }
 
   // Now we have an integral number so we can safely use PyLong_ functions.
   // We need to treat the signed and unsigned cases differently in case arg is
@@ -651,7 +629,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       ulong_result = PyLong_AsUnsignedLongLong(casted);
       Py_DECREF(casted);
     }
@@ -676,7 +654,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       long_result = PyLong_AsLongLong(casted);
       Py_DECREF(casted);
     }
@@ -702,7 +680,7 @@ bool CheckAndGetDouble(PyObject* arg, double* value) {
   if (PROTOBUF_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) {
     FormatTypeError(arg, "int, long, float");
     return false;
-    }
+  }
   return true;
 }
 
@@ -928,9 +906,9 @@ int AssureWritable(CMessage* self) {
   // Toplevel messages are always mutable.
   GOOGLE_DCHECK(self->parent);
 
-  if (AssureWritable(self->parent) == -1)
+  if (AssureWritable(self->parent) == -1) {
     return -1;
-
+  }
   // If this message is part of a oneof, there might be a field to release in
   // the parent.
   if (MaybeReleaseOverlappingOneofField(self->parent,
@@ -1279,32 +1257,41 @@ CMessage* NewEmptyMessage(CMessageClass* type) {
 
 // The __new__ method of Message classes.
 // Creates a new C++ message and takes ownership.
-static PyObject* New(PyTypeObject* cls,
-                     PyObject* unused_args, PyObject* unused_kwargs) {
-  CMessageClass* type = CheckMessageClass(cls);
-  if (type == NULL) {
-    return NULL;
-  }
+static CMessage* NewCMessage(CMessageClass* type) {
   // Retrieve the message descriptor and the default instance (=prototype).
   const Descriptor* message_descriptor = type->message_descriptor;
-  if (message_descriptor == NULL) {
-    return NULL;
+  if (message_descriptor == nullptr) {
+    // This would be very unexpected since the CMessageClass has already
+    // been checked.
+    PyErr_Format(PyExc_TypeError,
+                 "CMessageClass object '%s' has no descriptor.",
+                 Py_TYPE(type)->tp_name);
+    return nullptr;
   }
   const Message* prototype =
       type->py_message_factory->message_factory->GetPrototype(
           message_descriptor);
-  if (prototype == NULL) {
+  if (prototype == nullptr) {
     PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
-    return NULL;
+    return nullptr;
   }
 
   CMessage* self = NewEmptyMessage(type);
-  if (self == NULL) {
-    return NULL;
+  if (self == nullptr) {
+    return nullptr;
   }
   self->message = prototype->New();
   self->parent = nullptr;  // This message owns its data.
-  return reinterpret_cast<PyObject*>(self);
+  return self;
+}
+
+static PyObject* New(PyTypeObject* cls, PyObject* unused_args,
+                     PyObject* unused_kwargs) {
+  CMessageClass* type = CheckMessageClass(cls);
+  if (type == nullptr) {
+    return nullptr;
+  }
+  return reinterpret_cast<PyObject*>(NewCMessage(type));
 }
 
 // The __init__ method of Message classes.
@@ -2866,28 +2853,57 @@ Message* PyMessage_GetMutableMessagePointer(PyObject* msg) {
   return cmsg->message;
 }
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory) {
+  PyMessageFactory* factory = nullptr;
+  if (py_message_factory == nullptr) {
+    factory = GetDescriptorPool_FromPool(descriptor->file()->pool())
+                  ->py_message_factory;
+  } else if (PyObject_TypeCheck(py_message_factory, &PyMessageFactory_Type)) {
+    factory = reinterpret_cast<PyMessageFactory*>(py_message_factory);
+  } else {
+    PyErr_SetString(PyExc_TypeError, "Expected a MessageFactory");
+    return nullptr;
+  }
+  auto* message_class =
+      message_factory::GetOrCreateMessageClass(factory, descriptor);
+  if (message_class == nullptr) {
+    return nullptr;
+  }
+
+  CMessage* self = cmessage::NewCMessage(message_class);
+  Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
+  return self->AsPyObject();
+}
+
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory) {
-  if (message_factory) {
+                                              PyObject* py_message_factory) {
+  if (py_message_factory) {
     PyErr_SetString(PyExc_NotImplementedError,
                     "Default message_factory=NULL is the only supported value");
-    return NULL;
+    return nullptr;
   }
   if (message->GetReflection()->GetMessageFactory() !=
       MessageFactory::generated_factory()) {
     PyErr_SetString(PyExc_TypeError,
                     "Message pointer was not created from the default factory");
-    return NULL;
+    return nullptr;
   }
 
   CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
       GetDefaultDescriptorPool()->py_message_factory, message->GetDescriptor());
+  if (message_class == nullptr) {
+    return nullptr;
+  }
 
   CMessage* self = cmessage::NewEmptyMessage(message_class);
-  if (self == NULL) {
-    return NULL;
-  }
   Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
   self->message = message;
   Py_INCREF(Py_None);
   self->parent = reinterpret_cast<CMessage*>(Py_None);
@@ -2954,9 +2970,9 @@ bool InitProto2MessageModule(PyObject *m) {
       return false;
     }
 
-    PyModule_AddObject(m, "RepeatedScalarContainer",
-                       reinterpret_cast<PyObject*>(
-                           &RepeatedScalarContainer_Type));
+    PyModule_AddObject(
+        m, "RepeatedScalarContainer",
+        reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type));
 
     if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
       return false;
@@ -2964,8 +2980,7 @@ bool InitProto2MessageModule(PyObject *m) {
 
     PyModule_AddObject(
         m, "RepeatedCompositeContainer",
-        reinterpret_cast<PyObject*>(
-            &RepeatedCompositeContainer_Type));
+        reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type));
 
     // Register them as MutableSequence.
 #if PY_MAJOR_VERSION >= 3
@@ -2998,16 +3013,14 @@ bool InitProto2MessageModule(PyObject *m) {
   }
 
   PyModule_AddObject(m, "UnknownFieldSet",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFields_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFields_Type));
 
   if (PyType_Ready(&PyUnknownFieldRef_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(m, "UnknownField",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFieldRef_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFieldRef_Type));
 
   // Initialize Map container types.
   if (!InitMapContainers()) {
@@ -3023,9 +3036,8 @@ bool InitProto2MessageModule(PyObject *m) {
   if (PyType_Ready(&ExtensionDict_Type) < 0) {
     return false;
   }
-  PyModule_AddObject(
-      m, "ExtensionDict",
-      reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+  PyModule_AddObject(m, "ExtensionDict",
+                     reinterpret_cast<PyObject*>(&ExtensionDict_Type));
   if (PyType_Ready(&ExtensionIterator_Type) < 0) {
     return false;
   }
@@ -3039,25 +3051,24 @@ bool InitProto2MessageModule(PyObject *m) {
   PyModule_AddObject(m, "default_pool",
                      reinterpret_cast<PyObject*>(GetDefaultDescriptorPool()));
 
-  PyModule_AddObject(m, "DescriptorPool", reinterpret_cast<PyObject*>(
-      &PyDescriptorPool_Type));
-
-  PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
-      &PyMessageDescriptor_Type));
-  PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
-      &PyFieldDescriptor_Type));
-  PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumDescriptor_Type));
-  PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumValueDescriptor_Type));
-  PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
-      &PyFileDescriptor_Type));
-  PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
-      &PyOneofDescriptor_Type));
-  PyModule_AddObject(m, "ServiceDescriptor", reinterpret_cast<PyObject*>(
-      &PyServiceDescriptor_Type));
-  PyModule_AddObject(m, "MethodDescriptor", reinterpret_cast<PyObject*>(
-      &PyMethodDescriptor_Type));
+  PyModule_AddObject(m, "DescriptorPool",
+                     reinterpret_cast<PyObject*>(&PyDescriptorPool_Type));
+  PyModule_AddObject(m, "Descriptor",
+                     reinterpret_cast<PyObject*>(&PyMessageDescriptor_Type));
+  PyModule_AddObject(m, "FieldDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFieldDescriptor_Type));
+  PyModule_AddObject(m, "EnumDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumDescriptor_Type));
+  PyModule_AddObject(m, "EnumValueDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumValueDescriptor_Type));
+  PyModule_AddObject(m, "FileDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFileDescriptor_Type));
+  PyModule_AddObject(m, "OneofDescriptor",
+                     reinterpret_cast<PyObject*>(&PyOneofDescriptor_Type));
+  PyModule_AddObject(m, "ServiceDescriptor",
+                     reinterpret_cast<PyObject*>(&PyServiceDescriptor_Type));
+  PyModule_AddObject(m, "MethodDescriptor",
+                     reinterpret_cast<PyObject*>(&PyMethodDescriptor_Type));
 
   PyObject* enum_type_wrapper = PyImport_ImportModule(
       "google.protobuf.internal.enum_type_wrapper");

+ 46 - 45
python/google/protobuf/pyext/message.h

@@ -282,51 +282,50 @@ PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg);
 /* Is 64bit */
 #define IS_64BIT (SIZEOF_LONG == 8)
 
-#define FIELD_IS_REPEATED(field_descriptor)                 \
-    ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
-
-#define GOOGLE_CHECK_GET_INT32(arg, value, err)                        \
-    int32 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
-
-#define GOOGLE_CHECK_GET_INT64(arg, value, err)                        \
-    int64 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
-
-#define GOOGLE_CHECK_GET_UINT32(arg, value, err)                       \
-    uint32 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
-
-#define GOOGLE_CHECK_GET_UINT64(arg, value, err)                       \
-    uint64 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
-
-#define GOOGLE_CHECK_GET_FLOAT(arg, value, err)                        \
-    float value;                                            \
-    if (!CheckAndGetFloat(arg, &value)) {                   \
-      return err;                                          \
-    }                                                       \
-
-#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err)                       \
-    double value;                                           \
-    if (!CheckAndGetDouble(arg, &value)) {                  \
-      return err;                                          \
-    }
-
-#define GOOGLE_CHECK_GET_BOOL(arg, value, err)                         \
-    bool value;                                             \
-    if (!CheckAndGetBool(arg, &value)) {                    \
-      return err;                                          \
-    }
+#define FIELD_IS_REPEATED(field_descriptor) \
+  ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
 
+#define GOOGLE_CHECK_GET_INT32(arg, value, err)  \
+  int32 value;                            \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
+
+#define GOOGLE_CHECK_GET_INT64(arg, value, err)  \
+  int64 value;                            \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
+
+#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \
+  uint32 value;                           \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
+
+#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \
+  uint64 value;                           \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
+
+#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \
+  float value;                           \
+  if (!CheckAndGetFloat(arg, &value)) {  \
+    return err;                          \
+  }
+
+#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \
+  double value;                           \
+  if (!CheckAndGetDouble(arg, &value)) {  \
+    return err;                           \
+  }
+
+#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \
+  bool value;                           \
+  if (!CheckAndGetBool(arg, &value)) {  \
+    return err;                         \
+  }
 
 #define FULL_MODULE_NAME "google.protobuf.pyext._message"
 
@@ -353,10 +352,12 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
 
 extern PyObject* PickleError_class;
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory);
 const Message* PyMessage_GetMessagePointer(PyObject* msg);
 Message* PyMessage_GetMutableMessagePointer(PyObject* msg);
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory);
+                                              PyObject* py_message_factory);
 
 bool InitProto2MessageModule(PyObject *m);
 

+ 10 - 2
python/google/protobuf/pyext/message_module.cc

@@ -30,13 +30,12 @@
 
 #include <Python.h>
 
+#include <google/protobuf/message_lite.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/proto_api.h>
 
-#include <google/protobuf/message_lite.h>
-
 namespace {
 
 // C++ API.  Clients get at this via proto_api.h
@@ -55,6 +54,15 @@ struct ApiImplementation : google::protobuf::python::PyProto_API {
     return google::protobuf::python::GetDefaultDescriptorPool()
         ->py_message_factory->message_factory;
   }
+  PyObject* NewMessage(const google::protobuf::Descriptor* descriptor,
+                       PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_New(descriptor, py_message_factory);
+  }
+  PyObject* NewMessageOwnedExternally(
+      google::protobuf::Message* msg, PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_NewMessageOwnedExternally(
+        msg, py_message_factory);
+  }
 };
 
 }  // namespace

+ 5 - 1
python/google/protobuf/pyext/repeated_composite_container.cc

@@ -567,7 +567,11 @@ PyTypeObject RepeatedCompositeContainer_Type = {
     sizeof(RepeatedCompositeContainer),         // tp_basicsize
     0,                                          //  tp_itemsize
     repeated_composite_container::Dealloc,      //  tp_dealloc
-    0,                                          //  tp_print, in Python >=3.8: Py_ssize_t tp_vectorcall_offset
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                          //  tp_vectorcall_offset
+#else
+    nullptr,                                    //  tp_print
+#endif
     nullptr,                                    //  tp_getattr
     nullptr,                                    //  tp_setattr
     nullptr,                                    //  tp_compare

+ 5 - 1
python/google/protobuf/pyext/repeated_scalar_container.cc

@@ -753,7 +753,11 @@ PyTypeObject RepeatedScalarContainer_Type = {
     sizeof(RepeatedScalarContainer),         // tp_basicsize
     0,                                       //  tp_itemsize
     repeated_scalar_container::Dealloc,      //  tp_dealloc
-    0,                                       //  tp_print, in Python >=3.8: Py_ssize_t tp_vectorcall_offset
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                       //  tp_vectorcall_offset
+#else
+    nullptr,                                 //  tp_print
+#endif
     nullptr,                                 //  tp_getattr
     nullptr,                                 //  tp_setattr
     nullptr,                                 //  tp_compare

+ 1 - 14
python/google/protobuf/service_reflection.py

@@ -38,12 +38,6 @@ compiler at compile-time.
 
 __author__ = 'petar@google.com (Petar Petrov)'
 
-from google.protobuf.internal import api_implementation
-
-if api_implementation.Type() == 'cpp':
-  # pylint: disable=g-import-not-at-top
-  from google.protobuf.pyext import _message
-
 
 class GeneratedServiceType(type):
 
@@ -84,10 +78,6 @@ class GeneratedServiceType(type):
       return
 
     descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceType._DESCRIPTOR_KEY] = descriptor
-
     service_builder = _ServiceBuilder(descriptor)
     service_builder.BuildService(cls)
     cls.DESCRIPTOR = descriptor
@@ -113,16 +103,13 @@ class GeneratedServiceStubType(GeneratedServiceType):
         dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
         describing this protocol service type.
     """
-    descriptor = dictionary.get(cls._DESCRIPTOR_KEY)
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] = descriptor
     super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
     # Don't do anything if this class doesn't have a descriptor. This happens
     # when a service stub is subclassed.
     if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
       return
 
+    descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
     service_stub_builder = _ServiceStubBuilder(descriptor)
     service_stub_builder.BuildServiceStub(cls)
 

+ 4 - 1
python/google/protobuf/text_format.py

@@ -541,7 +541,7 @@ class _Printer(object):
         # For groups, use the capitalized name.
         out.write(field.message_type.name)
       else:
-        out.write(field.name)
+          out.write(field.name)
 
     if (self.force_colon or
         field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE):
@@ -902,6 +902,8 @@ class _Parser(object):
       # pylint: disable=protected-access
       field = message.Extensions._FindExtensionByName(name)
       # pylint: enable=protected-access
+
+
       if not field:
         if self.allow_unknown_extension:
           field = None
@@ -988,6 +990,7 @@ class _Parser(object):
     if not tokenizer.TryConsume(','):
       tokenizer.TryConsume(';')
 
+
   def _ConsumeAnyTypeUrl(self, tokenizer):
     """Consumes a google.protobuf.Any type URL and returns the type name."""
     # Consume "type.googleapis.com/".

+ 1 - 0
src/Makefile.am

@@ -341,6 +341,7 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/cpp/cpp_message_field.cc            \
   google/protobuf/compiler/cpp/cpp_message_field.h             \
   google/protobuf/compiler/cpp/cpp_message_layout_helper.h     \
+  google/protobuf/compiler/cpp/cpp_names.h                     \
   google/protobuf/compiler/cpp/cpp_options.h                   \
   google/protobuf/compiler/cpp/cpp_padding_optimizer.cc        \
   google/protobuf/compiler/cpp/cpp_padding_optimizer.h         \

+ 24 - 33
src/google/protobuf/any.pb.cc

@@ -17,24 +17,21 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class AnyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Any> _instance;
-} _Any_default_instance_;
+constexpr Any::Any(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , _any_metadata_(&type_url_, &value_){}
+struct AnyDefaultTypeInternal {
+  constexpr AnyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~AnyDefaultTypeInternal() {}
+  union {
+    Any _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Any_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Any();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
@@ -64,18 +61,18 @@ const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_
   "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
   "ypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fany_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fany_2eproto_sccs[1] = {
-  &scc_info_Any_google_2fprotobuf_2fany_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 212,
-  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, descriptor_table_google_2fprotobuf_2fany_2eproto_sccs, descriptor_table_google_2fprotobuf_2fany_2eproto_deps, 1, 0,
+  false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 
+  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fany_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
+  file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto);
+  return descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
@@ -126,9 +123,8 @@ Any::Any(const Any& from)
 }
 
 void Any::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Any::~Any() {
@@ -152,11 +148,6 @@ void Any::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Any::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Any& Any::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Any::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Any)

+ 7 - 5
src/google/protobuf/any.pb.h

@@ -53,9 +53,10 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Any;
-class AnyDefaultTypeInternal;
+struct AnyDefaultTypeInternal;
 PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL :
  public:
   inline Any() : Any(nullptr) {}
   virtual ~Any();
+  explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Any(const Any& from);
   Any(Any&& from) noexcept
@@ -99,8 +101,9 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Any& default_instance();
-
+  static const Any& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Any* internal_default_instance() {
     return reinterpret_cast<const Any*>(
                &_Any_default_instance_);
@@ -199,8 +202,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fany_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 1 - 1
src/google/protobuf/any_lite.cc

@@ -79,7 +79,7 @@ bool AnyMetadata::InternalIs(StringPiece type_name) const {
 
 bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
                      std::string* full_type_name) {
-  size_t pos = type_url.find_last_of("/");
+  size_t pos = type_url.find_last_of('/');
   if (pos == std::string::npos || pos + 1 == type_url.size()) {
     return false;
   }

+ 74 - 101
src/google/protobuf/api.pb.cc

@@ -16,68 +16,59 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto;
 PROTOBUF_NAMESPACE_OPEN
-class ApiDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Api> _instance;
-} _Api_default_instance_;
-class MethodDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Method> _instance;
-} _Method_default_instance_;
-class MixinDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Mixin> _instance;
-} _Mixin_default_instance_;
+constexpr Api::Api(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : methods_()
+  , options_()
+  , mixins_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , version_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct ApiDefaultTypeInternal {
+  constexpr ApiDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ApiDefaultTypeInternal() {}
+  union {
+    Api _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ApiDefaultTypeInternal _Api_default_instance_;
+constexpr Method::Method(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , response_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_streaming_(false)
+  , response_streaming_(false)
+  , syntax_(0)
+{}
+struct MethodDefaultTypeInternal {
+  constexpr MethodDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodDefaultTypeInternal() {}
+  union {
+    Method _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MethodDefaultTypeInternal _Method_default_instance_;
+constexpr Mixin::Mixin(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , root_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct MixinDefaultTypeInternal {
+  constexpr MixinDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MixinDefaultTypeInternal() {}
+  union {
+    Mixin _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Api_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Api();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<4> scc_info_Api_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 4, 0, InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
-      &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,}};
-
-static void InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Method_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Method();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Mixin();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
@@ -152,18 +143,18 @@ static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
   &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs[3] = {
-  &scc_info_Api_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 751,
-  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 3, 2,
+  false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 
+  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 2, 3,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fapi_2eproto, 3, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
+  file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
+  return descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
@@ -224,13 +215,12 @@ Api::Api(const Api& from)
 }
 
 void Api::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Api::~Api() {
@@ -255,11 +245,6 @@ void Api::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Api::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Api& Api::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Api::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
@@ -636,14 +621,13 @@ Method::Method(const Method& from)
 }
 
 void Method::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&request_streaming_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&request_streaming_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
 }
 
 Method::~Method() {
@@ -668,11 +652,6 @@ void Method::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Method::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Method& Method::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Method::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
@@ -1022,9 +1001,8 @@ Mixin::Mixin(const Mixin& from)
 }
 
 void Mixin::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Mixin::~Mixin() {
@@ -1048,11 +1026,6 @@ void Mixin::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Mixin::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Mixin& Mixin::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Mixin::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)

+ 19 - 15
src/google/protobuf/api.pb.h

@@ -55,15 +55,16 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Api;
-class ApiDefaultTypeInternal;
+struct ApiDefaultTypeInternal;
 PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_;
 class Method;
-class MethodDefaultTypeInternal;
+struct MethodDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_;
 class Mixin;
-class MixinDefaultTypeInternal;
+struct MixinDefaultTypeInternal;
 PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -80,6 +81,7 @@ class PROTOBUF_EXPORT Api PROTOBUF_FINAL :
  public:
   inline Api() : Api(nullptr) {}
   virtual ~Api();
+  explicit constexpr Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Api(const Api& from);
   Api(Api&& from) noexcept
@@ -109,8 +111,9 @@ class PROTOBUF_EXPORT Api PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Api& default_instance();
-
+  static const Api& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Api* internal_default_instance() {
     return reinterpret_cast<const Api*>(
                &_Api_default_instance_);
@@ -176,8 +179,7 @@ class PROTOBUF_EXPORT Api PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -332,6 +334,7 @@ class PROTOBUF_EXPORT Method PROTOBUF_FINAL :
  public:
   inline Method() : Method(nullptr) {}
   virtual ~Method();
+  explicit constexpr Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Method(const Method& from);
   Method(Method&& from) noexcept
@@ -361,8 +364,9 @@ class PROTOBUF_EXPORT Method PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Method& default_instance();
-
+  static const Method& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Method* internal_default_instance() {
     return reinterpret_cast<const Method*>(
                &_Method_default_instance_);
@@ -428,8 +432,7 @@ class PROTOBUF_EXPORT Method PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -564,6 +567,7 @@ class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL :
  public:
   inline Mixin() : Mixin(nullptr) {}
   virtual ~Mixin();
+  explicit constexpr Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Mixin(const Mixin& from);
   Mixin(Mixin&& from) noexcept
@@ -593,8 +597,9 @@ class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Mixin& default_instance();
-
+  static const Mixin& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Mixin* internal_default_instance() {
     return reinterpret_cast<const Mixin*>(
                &_Mixin_default_instance_);
@@ -660,8 +665,7 @@ class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 0 - 3
src/google/protobuf/arena.cc

@@ -46,9 +46,6 @@
 
 #include <google/protobuf/port_def.inc>
 
-static const size_t kMinCleanupListElements = 8;
-static const size_t kMaxCleanupListElements = 64;  // 1kB on 64-bit.
-
 namespace google {
 namespace protobuf {
 namespace internal {

+ 44 - 17
src/google/protobuf/arena.h

@@ -313,17 +313,9 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   // if the object were allocated on the heap (except that the underlying memory
   // is obtained from the arena).
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* Create(Arena* arena, Args&&... args) {
-    if (arena == NULL) {
-      return new T(std::forward<Args>(args)...);
-    } else {
-      auto destructor =
-          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
-                                     T>::destructor;
-      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
-                                          RTTI_TYPE_ID(T)))
-          T(std::forward<Args>(args)...);
-    }
+  PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
+    return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
+                             std::forward<Args>(args)...);
   }
 
   // Create an array of object type T on the arena *without* invoking the
@@ -333,7 +325,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   // (when compiled as C++11) that T is trivially default-constructible and
   // trivially destructible.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
                                                size_t num_elements) {
     static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value,
                   "CreateArray requires a trivially constructible type");
@@ -477,7 +469,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   struct has_get_arena : InternalHelper<T>::has_get_arena {};
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
                                                          Args&&... args) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
@@ -493,7 +485,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   // slightly different.  When the arena pointer is nullptr, it calls T()
   // instead of T(nullptr).
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena) {
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
         "CreateMessage can only construct types that are ArenaConstructable");
@@ -506,7 +498,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
 
   // Allocate and also optionally call collector with the allocated type info
   // when allocation recording is enabled.
-  PROTOBUF_ALWAYS_INLINE void* AllocateInternal(size_t size, size_t align,
+  PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
                                                 void (*destructor)(void*),
                                                 const std::type_info* type) {
     // Monitor allocation if needed.
@@ -557,7 +549,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   // Just allocate the required size for the given type assuming the
   // type has a trivial constructor.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) {
+  PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
     GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
         << "Requested size is too large to fit into size_t.";
     // We count on compiler to realize that if sizeof(T) is a multiple of
@@ -568,7 +560,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   }
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
+  PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
     return InternalHelper<T>::Construct(
         AllocateInternal(sizeof(T), alignof(T),
                          internal::ObjectDestructor<
@@ -611,6 +603,40 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
     arena->OwnDestructor(ptr);
   }
 
+  // These implement Create(). The second parameter has type 'true_type' if T is
+  // a subtype of Message and 'false_type' otherwise.
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      T* result =
+          new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                       RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+      result->SetOwningArena(arena);
+      return result;
+    }
+  }
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                          RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+    }
+  }
+
   // These implement Own(), which registers an object for deletion (destructor
   // call and operator delete()). The second parameter has type 'true_type' if T
   // is a subtype of Message and 'false_type' otherwise. Collapsing
@@ -620,6 +646,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
   PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
     if (object != NULL) {
       impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
+      object->SetOwningArena(this);
     }
   }
   template <typename T>

+ 3 - 3
src/google/protobuf/arena_impl.h

@@ -296,7 +296,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
   // semantics is necessary to allow callers to program functions that only
   // have fallback function calls in tail position. This substantially improves
   // code for the happy path.
-  PROTOBUF_ALWAYS_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
+  PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
     SerialArena* a;
     if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(tag_and_id_, &a))) {
       return a->MaybeAllocateAligned(n, out);
@@ -362,7 +362,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
     hint_.store(serial, std::memory_order_release);
   }
 
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(uint64 lifecycle_id,
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(uint64 lifecycle_id,
                                                  SerialArena** arena) {
     if (GetSerialArenaFromThreadCache(lifecycle_id, arena)) return true;
     if (lifecycle_id & kRecordAllocs) return false;
@@ -378,7 +378,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
     return false;
   }
 
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFromThreadCache(
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
       uint64 lifecycle_id, SerialArena** arena) {
     // If this thread already owns a block in this arena then try to use that.
     // This fast path optimizes the case where multiple threads allocate from

+ 12 - 8
src/google/protobuf/arenastring.h

@@ -51,6 +51,9 @@ namespace google {
 namespace protobuf {
 namespace internal {
 
+template <typename T>
+class ExplicitlyConstructed;
+
 // Lazy string instance to support string fields with non-empty default.
 // These are initialized on the first call to .get().
 class PROTOBUF_EXPORT LazyString {
@@ -88,8 +91,8 @@ template <typename T>
 class TaggedPtr {
  public:
   TaggedPtr() = default;
-  explicit constexpr TaggedPtr(const std::string* ptr)
-      : ptr_(const_cast<std::string*>(ptr)) {}
+  explicit constexpr TaggedPtr(const ExplicitlyConstructed<std::string>* ptr)
+      : ptr_(const_cast<ExplicitlyConstructed<std::string>*>(ptr)) {}
 
   void SetTagged(T* p) {
     Set(p);
@@ -171,7 +174,8 @@ static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
 // requires the String tag to be 0 so we can avoid the mask before comparing.)
 struct PROTOBUF_EXPORT ArenaStringPtr {
   ArenaStringPtr() = default;
-  explicit constexpr ArenaStringPtr(const std::string* default_value)
+  explicit constexpr ArenaStringPtr(
+      const ExplicitlyConstructed<std::string>* default_value)
       : tagged_ptr_(default_value) {}
 
   // Some methods below are overloaded on a `default_value` and on tags.
@@ -191,11 +195,11 @@ struct PROTOBUF_EXPORT ArenaStringPtr {
   void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
 
   // Basic accessors.
-  const std::string& Get() const PROTOBUF_ALWAYS_INLINE {
+  const std::string& Get() const PROTOBUF_NDEBUG_INLINE {
     // Unconditionally mask away the tag.
     return *tagged_ptr_.Get();
   }
-  const std::string* GetPointer() const PROTOBUF_ALWAYS_INLINE {
+  const std::string* GetPointer() const PROTOBUF_NDEBUG_INLINE {
     // Unconditionally mask away the tag.
     return tagged_ptr_.Get();
   }
@@ -224,7 +228,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr {
   // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
   // 'unsafe' if called directly.
   inline void Swap(ArenaStringPtr* other, const std::string* default_value,
-                   Arena* arena) PROTOBUF_ALWAYS_INLINE;
+                   Arena* arena) PROTOBUF_NDEBUG_INLINE;
 
   // Frees storage (if not on an arena).
   void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
@@ -329,8 +333,8 @@ inline void ArenaStringPtr::Swap(ArenaStringPtr* other,
     this_ptr->swap(*other_ptr);
   }
 #else
-  (void) default_value;
-  (void) arena;
+  (void)default_value;
+  (void)arena;
   std::swap(tagged_ptr_, other->tagged_ptr_);
 #endif
 }

+ 1 - 0
src/google/protobuf/arenastring_unittest.cc

@@ -41,6 +41,7 @@
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/strutil.h>
 

+ 3 - 3
src/google/protobuf/compiler/annotation_test_util.cc

@@ -31,15 +31,15 @@
 #include <google/protobuf/compiler/annotation_test_util.h>
 
 #include <memory>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 

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

@@ -234,7 +234,7 @@ bool IsInstalledProtoPath(const std::string& path) {
 // Add the paths where google/protobuf/descriptor.proto and other well-known
 // type protos are installed.
 void AddDefaultProtoPaths(
-    std::vector<std::pair<std::string, std::string> >* paths) {
+    std::vector<std::pair<std::string, std::string>>* paths) {
   // TODO(xiaofeng): The code currently only checks relative paths of where
   // the protoc binary is installed. We probably should make it handle more
   // cases than that.

+ 16 - 0
src/google/protobuf/compiler/cpp/cpp_enum_field.cc

@@ -156,6 +156,12 @@ void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
       "));\n");
 }
 
+void EnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)\n");
+}
+
 // ===================================================================
 
 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
@@ -484,6 +490,16 @@ void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
   format("}\n");
 }
 
+void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/cpp/cpp_enum_field.h

@@ -60,6 +60,7 @@ class EnumFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -100,6 +101,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
   void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);

+ 6 - 0
src/google/protobuf/compiler/cpp/cpp_field.h

@@ -164,6 +164,12 @@ class FieldGenerator {
     return false;
   }
 
+  // Generate initialization code for private members declared by
+  // GeneratePrivateMembers(), specifically for the constexpr constructor.
+  // These go into the constructor's initializer list and must follow that
+  // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
+  virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
+
   // Generate lines to serialize this field directly to the array "target",
   // which are placed within the message's SerializeWithCachedSizesToArray()
   // method. This must also advance "target" past the written bytes.

+ 64 - 178
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -38,6 +38,7 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
@@ -52,6 +53,7 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
+// Must be last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -138,13 +140,6 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
   for (int i = 0; i < file->weak_dependency_count(); ++i) {
     weak_deps_.insert(file->weak_dependency(i));
   }
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
-      sccs_.push_back(GetSCC(message_generators_[i]->descriptor_));
-    }
-  }
-
-  std::sort(sccs_.begin(), sccs_.end(), CompareSortKeys<SCC>);
 }
 
 FileGenerator::~FileGenerator() = default;
@@ -426,6 +421,10 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
       format("#include \"$1$.proto.h\"\n", basename);
     }
   }
+  if (HasCordFields(file_, options_)) {
+    format(
+        "#include \"third_party/absl/strings/internal/string_constant.h\"\n");
+  }
 
   format("// @@protoc_insertion_point(includes)\n");
   IncludeFile("net/proto2/public/port_def.inc", printer);
@@ -441,13 +440,28 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx,
                                                   io::Printer* printer) {
   Formatter format(printer, variables_);
   MessageGenerator* generator = message_generators_[idx].get();
+  generator->GenerateConstexprConstructor(printer);
+  // Use a union to disable the destructor of the _instance member.
+  // We can constant initialize, but the object will still have a non-trivial
+  // destructor that we need to elide.
   format(
-      "class $1$ {\n"
-      " public:\n"
-      "  ::$proto_ns$::internal::ExplicitlyConstructed<$2$> _instance;\n",
+      "struct $1$ {\n"
+      "  constexpr $1$()\n"
+      "    : _instance(::$proto_ns$::internal::ConstantInitialized{}) {}\n"
+      "  ~$1$() {}\n"
+      "  union {\n"
+      "    $2$ _instance;\n"
+      "  };\n"
+      "};\n",
       DefaultInstanceType(generator->descriptor_, options_),
       generator->classname_);
-  format("} $1$;\n", DefaultInstanceName(generator->descriptor_, options_));
+  // NO_DESTROY is not necessary for correctness. The empty destructor is
+  // enough. However, the empty destructor fails to be elided in some
+  // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
+  // there just to improve performance and binary size in these builds.
+  format("PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY $1$ $2$;\n",
+         DefaultInstanceType(generator->descriptor_, options_),
+         DefaultInstanceName(generator->descriptor_, options_));
 
   if (options_.lite_implicit_weak_fields) {
     format("$1$* $2$ = &$3$;\n",
@@ -461,8 +475,6 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx,
 // another .pb.cc file.
 struct FileGenerator::CrossFileReferences {
   // Populated if we are referencing from messages or files.
-  std::unordered_set<const SCC*> strong_sccs;
-  std::unordered_set<const SCC*> weak_sccs;
   std::unordered_set<const Descriptor*> weak_default_instances;
 
   // Only if we are referencing from files.
@@ -474,16 +486,10 @@ void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field,
                                                    CrossFileReferences* refs) {
   const Descriptor* msg = field->message_type();
   if (msg == nullptr) return;
-  const SCC* scc = GetSCC(msg);
 
   if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
       IsWeak(field, options_)) {
-    refs->weak_sccs.insert(scc);
     refs->weak_default_instances.insert(msg);
-  } else {
-    refs->strong_sccs.insert(scc);
-    // We don't need to declare default instances, because it is declared in the
-    // .proto.h file we imported.
   }
 }
 
@@ -510,35 +516,6 @@ void FileGenerator::GenerateInternalForwardDeclarations(
     const CrossFileReferences& refs, io::Printer* printer) {
   Formatter format(printer, variables_);
 
-  for (auto scc : Sorted(refs.strong_sccs)) {
-    format("extern $1$ ::$proto_ns$::internal::SCCInfo<$2$> $3$;\n",
-           FileDllExport(scc->GetFile(), options_), scc->children.size(),
-           SccInfoSymbol(scc, options_));
-  }
-
-  for (auto scc : Sorted(refs.weak_sccs)) {
-    // We do things a little bit differently for proto1-style weak fields versus
-    // lite implicit weak fields, even though they are trying to accomplish
-    // similar things. We need to support implicit weak fields on iOS, and the
-    // Apple linker only supports weak definitions, not weak declarations. For
-    // that reason we need a pointer type which we can weakly define to be null.
-    // However, code size considerations prevent us from using the same approach
-    // for proto1-style weak fields.
-    if (options_.lite_implicit_weak_fields) {
-      format("extern ::$proto_ns$::internal::SCCInfo<$1$> $2$;\n",
-             scc->children.size(), SccInfoSymbol(scc, options_));
-      format(
-          "__attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$>*\n"
-          "    $2$ = nullptr;\n",
-          scc->children.size(), SccInfoPtrSymbol(scc, options_));
-    } else {
-      format(
-          "extern __attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$> "
-          "$2$;\n",
-          scc->children.size(), SccInfoSymbol(scc, options_));
-    }
-  }
-
   {
     NamespaceOpener ns(format);
     for (auto instance : Sorted(refs.weak_default_instances)) {
@@ -569,24 +546,13 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
   Formatter format(printer, variables_);
   GenerateSourceIncludes(printer);
 
-  // Generate weak declarations. We do this for the whole strongly-connected
-  // component (SCC), because we have a single InitDefaults* function for the
-  // SCC.
   CrossFileReferences refs;
-  for (const Descriptor* message :
-       scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
-           ->descriptors) {
-    ForEachField(message, [this, &refs](const FieldDescriptor* field) {
-      GetCrossFileReferencesForField(field, &refs);
-    });
-  }
+  ForEachField(message_generators_[idx]->descriptor_,
+               [this, &refs](const FieldDescriptor* field) {
+                 GetCrossFileReferencesForField(field, &refs);
+               });
   GenerateInternalForwardDeclarations(refs, printer);
 
-  if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
-    GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), refs,
-                       printer);
-  }
-
   {  // package namespace
     NamespaceOpener ns(Namespace(file_, options_), format);
 
@@ -668,11 +634,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
   {
     GenerateTables(printer);
 
-    // Now generate the InitDefaults for each SCC.
-    for (auto scc : sccs_) {
-      GenerateInitForSCC(scc, refs, printer);
-    }
-
     if (HasDescriptorMethods(file_, options_)) {
       // Define the code to initialize reflection. This code uses a global
       // constructor to register reflection data with the runtime pre-main.
@@ -872,32 +833,22 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
       refs.strong_reflection_files.size() + refs.weak_reflection_files.size();
 
   // Build array of DescriptorTable deps.
-  format(
-      "static const ::$proto_ns$::internal::DescriptorTable*const "
-      "$desc_table$_deps[$1$] = {\n",
-      std::max(num_deps, 1));
-
-  for (auto dep : Sorted(refs.strong_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
-  }
-  for (auto dep : Sorted(refs.weak_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
-  }
-
-  format("};\n");
+  if (num_deps > 0) {
+    format(
+        "static const ::$proto_ns$::internal::DescriptorTable*const "
+        "$desc_table$_deps[$1$] = {\n",
+        num_deps);
 
-  // Build array of SCCs from this file.
-  format(
-      "static ::$proto_ns$::internal::SCCInfoBase*const "
-      "$desc_table$_sccs[$1$] = {\n",
-      std::max<int>(sccs_.size(), 1));
+    for (auto dep : Sorted(refs.strong_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
+    for (auto dep : Sorted(refs.weak_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
 
-  for (auto scc : sccs_) {
-    format("  &$1$.base,\n", SccInfoSymbol(scc, options_));
+    format("};\n");
   }
 
-  format("};\n");
-
   // The DescriptorTable itself.
   // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);"
   // however this might cause a tsan failure in superroot b/148382879,
@@ -906,14 +857,27 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
   format(
       "static ::$proto_ns$::internal::once_flag $desc_table$_once;\n"
       "const ::$proto_ns$::internal::DescriptorTable $desc_table$ = {\n"
-      "  false, $1$, $2$, \"$filename$\", $3$,\n"
-      "  &$desc_table$_once, $desc_table$_sccs, $desc_table$_deps, $4$, $5$,\n"
+      "  false, $1$, $2$, $3$, \"$filename$\", \n"
+      "  &$desc_table$_once, $4$, $5$, $6$,\n"
       "  schemas, file_default_instances, $tablename$::offsets,\n"
-      "  $file_level_metadata$, $6$, $file_level_enum_descriptors$, "
+      "  $file_level_metadata$, $file_level_enum_descriptors$, "
       "$file_level_service_descriptors$,\n"
-      "};\n\n",
-      eager ? "true" : "false", protodef_name, file_data.size(), sccs_.size(),
-      num_deps, message_generators_.size());
+      "};\n"
+      // This function exists to be marked as weak.
+      // It can significantly speed up compilation by breaking up the SCC.
+      // Without the weak attribute all the messages in the file, including all
+      // the vtables and everything they use become part of the same SCC.
+      // By adding a weak function here we break the connection from the
+      // individual vtables back into the descriptor table.
+      "PROTOBUF_ATTRIBUTE_WEAK ::$proto_ns$::Metadata\n"
+      "$desc_table$_metadata_getter(int index) {\n"
+      "  ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
+      "  return $desc_table$.file_level_metadata[index];\n"
+      "}\n"
+      "\n",
+      eager ? "true" : "false", file_data.size(), protodef_name,
+      num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps,
+      message_generators_.size());
 
   // For descriptor.proto we want to avoid doing any dynamic initialization,
   // because in some situations that would otherwise pull in a lot of
@@ -929,86 +893,6 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
   }
 }
 
-void FileGenerator::GenerateInitForSCC(const SCC* scc,
-                                       const CrossFileReferences& refs,
-                                       io::Printer* printer) {
-  Formatter format(printer, variables_);
-  // We use static and not anonymous namespace because symbol names are
-  // substantially shorter.
-  format("static void InitDefaults$1$() {\n", SccInfoSymbol(scc, options_));
-
-  if (options_.opensource_runtime) {
-    format("  GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n");
-  }
-
-  format.Indent();
-
-  // First construct all the necessary default instances.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
-      continue;
-    }
-    format(
-        "{\n"
-        "  void* ptr = &$1$;\n"
-        "  new (ptr) $2$();\n",
-        QualifiedDefaultInstanceName(message_generators_[i]->descriptor_,
-                                     options_),
-        QualifiedClassName(message_generators_[i]->descriptor_, options_));
-    if (options_.opensource_runtime &&
-        !IsMapEntryMessage(message_generators_[i]->descriptor_)) {
-      format(
-          "  "
-          "::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);"
-          "\n");
-    }
-    format("}\n");
-  }
-  format.Outdent();
-  format("}\n\n");
-
-  // If we are using lite implicit weak fields then we need to distinguish
-  // between regular SCC dependencies and ones that we need to reference weakly
-  // through an extra pointer indirection.
-  std::vector<const SCC*> regular_sccs;
-  std::vector<const SCC*> implicit_weak_sccs;
-  for (const SCC* child : scc->children) {
-    if (options_.lite_implicit_weak_fields &&
-        refs.weak_sccs.find(child) != refs.weak_sccs.end()) {
-      implicit_weak_sccs.push_back(child);
-    } else {
-      regular_sccs.push_back(child);
-    }
-  }
-
-  format(
-      "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$> $2$ =\n"
-      "    "
-      "{{ATOMIC_VAR_INIT(::$proto_ns$::internal::SCCInfoBase::kUninitialized), "
-      "$3$, $4$, InitDefaults$2$}, {",
-      scc->children.size(),  // 1
-      SccInfoSymbol(scc, options_), regular_sccs.size(),
-      implicit_weak_sccs.size());
-  for (const SCC* child : regular_sccs) {
-    format("\n      &$1$.base,", SccInfoSymbol(child, options_));
-  }
-  for (const SCC* child : implicit_weak_sccs) {
-    format(
-        "\n      reinterpret_cast<::$proto_ns$::internal::SCCInfoBase**>("
-        "\n          &$1$),",
-        SccInfoPtrSymbol(child, options_));
-  }
-  format("}};\n\n");
-
-  if (options_.lite_implicit_weak_fields) {
-    format(
-        "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$>*\n"
-        "    $2$ = &$3$;\n\n",
-        scc->children.size(), SccInfoPtrSymbol(scc, options_),
-        SccInfoSymbol(scc, options_));
-  }
-}
-
 void FileGenerator::GenerateTables(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (options_.table_driven_parsing) {
@@ -1138,7 +1022,7 @@ class FileGenerator::ForwardDeclarations {
       const Descriptor* class_desc = p.second;
       format(
           "class ${1$$2$$}$;\n"
-          "class $3$;\n"
+          "struct $3$;\n"
           "$dllexport_decl $extern $3$ $4$;\n",
           class_desc, classname, DefaultInstanceType(class_desc, options),
           DefaultInstanceName(class_desc, options));
@@ -1409,7 +1293,9 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
   if (HasDescriptorMethods(file_, options_)) {
     format(
         "extern $dllexport_decl $const ::$proto_ns$::internal::DescriptorTable "
-        "$desc_table$;\n");
+        "$desc_table$;\n"
+        "$dllexport_decl $::$proto_ns$::Metadata "
+        "$desc_table$_metadata_getter(int index);\n");
   }
 }
 

+ 0 - 9
src/google/protobuf/compiler/cpp/cpp_file.h

@@ -162,14 +162,6 @@ class FileGenerator {
   // generally a breaking change so we prefer the #undef approach.
   void GenerateMacroUndefs(io::Printer* printer);
 
-  bool IsSCCRepresentative(const Descriptor* d) {
-    return GetSCCRepresentative(d) == d;
-  }
-  const Descriptor* GetSCCRepresentative(const Descriptor* d) {
-    return GetSCC(d)->GetRepresentative();
-  }
-  const SCC* GetSCC(const Descriptor* d) { return scc_analyzer_.GetSCC(d); }
-
   bool IsDepWeak(const FileDescriptor* dep) const {
     if (weak_deps_.count(dep) != 0) {
       GOOGLE_CHECK(!options_.opensource_runtime);
@@ -179,7 +171,6 @@ class FileGenerator {
   }
 
   std::set<const FileDescriptor*> weak_deps_;
-  std::vector<const SCC*> sccs_;
 
   const FileDescriptor* file_;
   const Options options_;

+ 9 - 7
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -44,6 +44,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/compiler/scc.h>
@@ -521,6 +522,14 @@ std::string FieldMessageTypeName(const FieldDescriptor* field,
   return QualifiedClassName(field->message_type(), options);
 }
 
+std::string StripProto(const std::string& filename) {
+  /*
+   * TODO(github/georgthegreat) remove this proxy method
+   * once Google's internal codebase will become ready
+   */
+  return compiler::StripProto(filename);
+}
+
 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
   switch (type) {
     case FieldDescriptor::CPPTYPE_INT32:
@@ -1147,11 +1156,6 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
     const Descriptor* descriptor = scc->descriptors[i];
     if (descriptor->extension_range_count() > 0) {
       result.contains_extension = true;
-      // Extensions are found by looking up default_instance and extension
-      // number in a map. So you'd maybe expect here
-      // result.constructor_requires_initialization = true;
-      // However the extension registration mechanism already makes sure
-      // the default will be initialized.
     }
     for (int i = 0; i < descriptor->field_count(); i++) {
       const FieldDescriptor* field = descriptor->field(i);
@@ -1161,7 +1165,6 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
       switch (field->type()) {
         case FieldDescriptor::TYPE_STRING:
         case FieldDescriptor::TYPE_BYTES: {
-          result.constructor_requires_initialization = true;
           if (field->options().ctype() == FieldOptions::CORD) {
             result.contains_cord = true;
           }
@@ -1169,7 +1172,6 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
         }
         case FieldDescriptor::TYPE_GROUP:
         case FieldDescriptor::TYPE_MESSAGE: {
-          result.constructor_requires_initialization = true;
           const SCC* child = analyzer_.GetSCC(field->message_type());
           if (child != scc) {
             MessageAnalysis analysis = GetSCCAnalysis(child);

+ 1 - 18
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -539,7 +539,6 @@ struct MessageAnalysis {
   bool contains_cord;
   bool contains_extension;
   bool contains_required;
-  bool constructor_requires_initialization;
 };
 
 // This class is used in FileGenerator, to ensure linear instead of
@@ -577,16 +576,6 @@ class PROTOC_EXPORT MessageSCCAnalyzer {
   std::map<const SCC*, MessageAnalysis> analysis_cache_;
 };
 
-inline std::string SccInfoSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
-inline std::string SccInfoPtrSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_ptr_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
 void ListAllFields(const Descriptor* d,
                    std::vector<const FieldDescriptor*>* fields);
 void ListAllFields(const FileDescriptor* d,
@@ -881,13 +870,7 @@ void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
                         const Options& options,
                         MessageSCCAnalyzer* scc_analyzer, io::Printer* printer);
 
-inline std::string StripProto(const std::string& filename) {
-  /*
-   * TODO(github/georgthegreat) remove this proxy method
-   * once Google's internal codebase will become ready
-   */
-  return compiler::StripProto(filename);
-}
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
 
 }  // namespace cpp
 }  // namespace compiler

+ 10 - 0
src/google/protobuf/compiler/cpp/cpp_map_field.cc

@@ -290,6 +290,16 @@ void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const {
       "}\n");
 }
 
+void MapFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
+  } else {
+    format("$name$_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 1 - 0
src/google/protobuf/compiler/cpp/cpp_map_field.h

@@ -57,6 +57,7 @@ class MapFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);

+ 55 - 58
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -241,9 +241,9 @@ bool HasHasMethod(const FieldDescriptor* field) {
     return true;
   }
   // For message types without true field presence, only fields with a message
-  // type have a has_$name$() method.
+  // type or inside an one-of have a has_$name$() method.
   return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-         field->has_optional_keyword();
+         field->has_optional_keyword() || field->real_containing_oneof();
 }
 
 // Collects map entry message type information.
@@ -296,21 +296,6 @@ bool ShouldMarkClearAsFinal(const Descriptor* descriptor,
          options.opensource_runtime;
 }
 
-bool ShouldMarkIsInitializedAsFinal(const Descriptor* descriptor,
-                                    const Options& options) {
-  static std::set<std::string> exclusions{
-  };
-
-  const std::string name = ClassName(descriptor, true);
-  return exclusions.find(name) == exclusions.end() ||
-         options.opensource_runtime;
-}
-
-bool ShouldMarkNewAsFinal(const Descriptor* descriptor,
-                          const Options& options) {
-  return true;
-}
-
 // Returns true to make the message serialize in order, decided by the following
 // factors in the order of precedence.
 // --options().message_set_wire_format() == true
@@ -582,8 +567,6 @@ MessageGenerator::MessageGenerator(
   // Variables that apply to this class
   variables_["classname"] = classname_;
   variables_["classtype"] = QualifiedClassName(descriptor_, options);
-  variables_["scc_info"] =
-      SccInfoSymbol(scc_analyzer_->GetSCC(descriptor_), options_);
   variables_["full_name"] = descriptor_->full_name();
   variables_["superclass"] = SuperClassName(descriptor_, options_);
 
@@ -1024,6 +1007,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
         "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
         "SuperType;\n"
         "  $classname$();\n"
+        "  explicit constexpr $classname$(\n"
+        "      ::$proto_ns$::internal::ConstantInitialized);\n"
         "  explicit $classname$(::$proto_ns$::Arena* arena);\n"
         "  void MergeFrom(const $classname$& other);\n"
         "  static const $classname$* internal_default_instance() { return "
@@ -1041,7 +1026,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
             " }\n",
             descriptor_->field(0)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check == VERIFY);
+        GOOGLE_CHECK_EQ(utf8_check, VERIFY);
         format(
             "  static bool ValidateKey(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1070,7 +1055,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
             " }\n",
             descriptor_->field(1)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check == VERIFY);
+        GOOGLE_CHECK_EQ(utf8_check, VERIFY);
         format(
             "  static bool ValidateValue(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1118,6 +1103,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   format(
       "inline $classname$() : $classname$(nullptr) {}\n"
       "virtual ~$classname$();\n"
+      "explicit constexpr "
+      "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
       "\n"
       "$classname$(const $classname$& from);\n"
       "$classname$($classname$&& from) noexcept\n"
@@ -1189,8 +1176,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   }
 
   format(
-      "static const $classname$& default_instance();\n"
-      "\n");
+      "static const $classname$& default_instance() {\n"
+      "  return *internal_default_instance();\n"
+      "}\n");
 
   // Generate enum values for every field in oneofs. One list is generated for
   // each oneof with an additional *_NOT_SET value.
@@ -1288,9 +1276,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
         "                            std::string* full_type_name);\n");
   }
 
-  format.Set("new_final",
-             ShouldMarkNewAsFinal(descriptor_, options_) ? "final" : "");
-
   format(
       "friend void swap($classname$& a, $classname$& b) {\n"
       "  a.Swap(&b);\n"
@@ -1313,11 +1298,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
       "\n"
       "// implements Message ----------------------------------------------\n"
       "\n"
-      "inline $classname$* New() const$ new_final$ {\n"
+      "inline $classname$* New() const final {\n"
       "  return CreateMaybeMessage<$classname$>(nullptr);\n"
       "}\n"
       "\n"
-      "$classname$* New(::$proto_ns$::Arena* arena) const$ new_final$ {\n"
+      "$classname$* New(::$proto_ns$::Arena* arena) const final {\n"
       "  return CreateMaybeMessage<$classname$>(arena);\n"
       "}\n");
 
@@ -1340,15 +1325,12 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
 
     format.Set("clear_final",
                ShouldMarkClearAsFinal(descriptor_, options_) ? "final" : "");
-    format.Set(
-        "is_initialized_final",
-        ShouldMarkIsInitializedAsFinal(descriptor_, options_) ? "final" : "");
 
     format(
         "void CopyFrom(const $classname$& from);\n"
         "void MergeFrom(const $classname$& from);\n"
         "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear()$ clear_final$;\n"
-        "bool IsInitialized() const$ is_initialized_final$;\n"
+        "bool IsInitialized() const final;\n"
         "\n"
         "size_t ByteSizeLong() const final;\n"
         "const char* _InternalParse(const char* ptr, "
@@ -1400,8 +1382,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
         "::$proto_ns$::Metadata GetMetadata() const final;\n"
         "private:\n"
         "static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-        "  ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n"
-        "  return ::$desc_table$.file_level_metadata[kIndexInFileMessages];\n"
+        "  return ::$desc_table$_metadata_getter(kIndexInFileMessages);\n"
         "}\n"
         "\n"
         "public:\n"
@@ -1540,13 +1521,14 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   // For each oneof generate a union
   for (auto oneof : OneOfRange(descriptor_)) {
     std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true);
+    format("union $1$Union {\n", camel_oneof_name);
+    format.Indent();
     format(
-        "union $1$Union {\n"
         // explicit empty constructor is needed when union contains
         // ArenaStringPtr members for string fields.
-        "  $1$Union() {}\n",
+        "constexpr $1$Union() : _constinit_{} {}\n"
+        "  ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
         camel_oneof_name);
-    format.Indent();
     for (auto field : FieldRange(oneof)) {
       if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GeneratePrivateMembers(printer);
@@ -2328,12 +2310,6 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
   Formatter format(printer, variables_);
 
   format("void $classname$::SharedCtor() {\n");
-  if (scc_analyzer_->GetSCCAnalysis(scc_analyzer_->GetSCC(descriptor_))
-          .constructor_requires_initialization) {
-    format("  ::$proto_ns$::internal::InitSCC(&$scc_info$.base);\n");
-  }
-
-  format.Indent();
 
   std::vector<bool> processed(optimized_order_.size(), false);
   GenerateConstructorBody(printer, processed, false);
@@ -2342,7 +2318,6 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
     format("clear_has_$1$();\n", oneof->name());
   }
 
-  format.Outdent();
   format("}\n\n");
 }
 
@@ -2413,12 +2388,6 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
       }
     }
   }
-  if (num_weak_fields_) {
-    // _this is the object being destructed (we are inside a static method
-    // here).
-    format("_this->_weak_field_map_.ClearAll();\n");
-    need_registration = true;
-  }
 
   format.Outdent();
   format("}\n");
@@ -2438,6 +2407,42 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
   }
 }
 
+void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
+  Formatter format(printer, variables_);
+
+  format(
+      "constexpr $classname$::$classname$(\n"
+      "  ::$proto_ns$::internal::ConstantInitialized)");
+  format.Indent();
+  const char* field_sep = ":";
+  const auto put_sep = [&] {
+    format("\n$1$ ", field_sep);
+    field_sep = ",";
+  };
+
+  if (!IsMapEntryMessage(descriptor_)) {
+    // Process non-oneof fields first.
+    for (auto field : optimized_order_) {
+      auto& gen = field_generators_.get(field);
+      put_sep();
+      gen.GenerateConstinitInitializer(printer);
+    }
+
+    if (IsAnyMessage(descriptor_, options_)) {
+      put_sep();
+      format("_any_metadata_(&type_url_, &value_)");
+    }
+
+    if (descriptor_->real_oneof_decl_count() != 0) {
+      put_sep();
+      format("_oneof_case_{}");
+    }
+  }
+
+  format.Outdent();
+  format("{}\n");
+}
+
 void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
                                                std::vector<bool> processed,
                                                bool copy_constructor) const {
@@ -2664,14 +2669,6 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
       "void $classname$::SetCachedSize(int size) const {\n"
       "  _cached_size_.Set(size);\n"
       "}\n");
-
-  format(
-      "const $classname$& $classname$::default_instance() {\n"
-      "  "
-      "::$proto_ns$::internal::InitSCC(&::$scc_info$.base)"
-      ";\n"
-      "  return *internal_default_instance();\n"
-      "}\n\n");
 }
 
 void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {

+ 4 - 0
src/google/protobuf/compiler/cpp/cpp_message.h

@@ -124,6 +124,10 @@ class MessageGenerator {
   // Generate the arena-specific destructor code.
   void GenerateArenaDestructorCode(io::Printer* printer);
 
+  // Generate the constexpr constructor for constant initialization of the
+  // default instance.
+  void GenerateConstexprConstructor(io::Printer* printer);
+
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateOneofClear(io::Printer* printer);

+ 12 - 0
src/google/protobuf/compiler/cpp/cpp_message_field.cc

@@ -466,6 +466,12 @@ void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
       "    *$field_member$);\n");
 }
 
+void MessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_(nullptr)");
+}
+
 // ===================================================================
 
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
@@ -809,6 +815,12 @@ void RepeatedMessageFieldGenerator::GenerateByteSize(
       "}\n");
 }
 
+void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/cpp/cpp_message_field.h

@@ -68,6 +68,7 @@ class MessageFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  protected:
   const bool implicit_weak_field_;
@@ -117,6 +118,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const {}
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   const bool implicit_weak_field_;

+ 85 - 0
src/google/protobuf/compiler/cpp/cpp_names.h

@@ -0,0 +1,85 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+
+namespace compiler {
+namespace cpp {
+
+// Returns the unqualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the non-qualified version would be:
+//   Baz_Qux
+std::string ClassName(const Descriptor* descriptor);
+std::string ClassName(const EnumDescriptor* enum_descriptor);
+
+// Returns the fully qualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the qualified ClassName for Qux would be:
+//   ::foo::bar::Baz_Qux
+std::string QualifiedClassName(const Descriptor* d);
+std::string QualifiedClassName(const EnumDescriptor* d);
+std::string QualifiedExtensionName(const FieldDescriptor* d);
+
+// Get the (unqualified) name that should be used for this field in C++ code.
+// The name is coerced to lower-case to emulate proto1 behavior.  People
+// should be using lowercase-with-underscores style for proto field names
+// anyway, so normally this just returns field->name().
+std::string FieldName(const FieldDescriptor* field);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__

+ 2 - 3
src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc

@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 

+ 16 - 0
src/google/protobuf/compiler/cpp/cpp_primitive_field.cc

@@ -217,6 +217,12 @@ void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
   }
 }
 
+void PrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)");
+}
+
 // ===================================================================
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
@@ -470,6 +476,16 @@ void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
   format("}\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/cpp/cpp_primitive_field.h

@@ -61,6 +61,7 @@ class PrimitiveFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
@@ -99,6 +100,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);

+ 16 - 0
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -399,6 +399,16 @@ void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
       "    this->_internal_$name$());\n");
 }
 
+void StringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (descriptor_->default_value_string().empty()) {
+    format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)");
+  } else {
+    format("$name$_(nullptr)");
+  }
+}
+
 // ===================================================================
 
 StringOneofFieldGenerator::StringOneofFieldGenerator(
@@ -818,6 +828,12 @@ void RepeatedStringFieldGenerator::GenerateByteSize(
       "}\n");
 }
 
+void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/cpp/cpp_string_field.h

@@ -65,6 +65,7 @@ class StringFieldGenerator : public FieldGenerator {
   void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
@@ -107,6 +108,7 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);

+ 2 - 3
src/google/protobuf/compiler/cpp/metadata_test.cc

@@ -30,14 +30,13 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/annotation_test_util.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 

+ 2 - 2
src/google/protobuf/compiler/importer.cc

@@ -497,8 +497,8 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
   } while (ret != 0 && errno == EINTR);
 #if defined(_WIN32)
   if (ret == 0 && sb.st_mode & S_IFDIR) {
-      last_error_message_ = "Input file is a directory.";
-      return NULL;
+    last_error_message_ = "Input file is a directory.";
+    return NULL;
   }
 #else
   if (ret == 0 && S_ISDIR(sb.st_mode)) {

+ 22 - 24
src/google/protobuf/compiler/java/java_enum_field.cc

@@ -154,7 +154,7 @@ int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
 
 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -171,7 +171,7 @@ void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -203,7 +203,7 @@ void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_ = $default_number$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -287,7 +287,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
 
 void ImmutableEnumFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -305,7 +305,7 @@ void ImmutableEnumFieldGenerator::GenerateMergingCode(
 
 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -389,15 +389,14 @@ ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -426,16 +425,15 @@ void ImmutableEnumOneofFieldGenerator::GenerateMembers(
 
 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(

+ 21 - 23
src/google/protobuf/compiler/java/java_enum_field_lite.cc

@@ -142,7 +142,7 @@ int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
 
 void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -160,7 +160,7 @@ void ImmutableEnumFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -214,7 +214,7 @@ void ImmutableEnumFieldLiteGenerator::GenerateMembers(
 
 void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -316,16 +316,15 @@ ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {}
 void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -393,16 +392,15 @@ void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
 
 void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(

+ 1 - 1
src/google/protobuf/compiler/java/java_file.cc

@@ -387,7 +387,6 @@ void FileGenerator::Generate(io::Printer* printer) {
   printer->Print("}\n");
 }
 
-
 void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
     io::Printer* printer) {
   printer->Print(
@@ -676,6 +675,7 @@ void FileGenerator::GenerateSiblings(
   }
 }
 
+
 bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor,
                                             bool immutable_api) {
   return true;

+ 1 - 11
src/google/protobuf/compiler/java/java_helpers.cc

@@ -41,6 +41,7 @@
 
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -89,17 +90,6 @@ const std::unordered_set<std::string>* kReservedNames =
         "transient",  "try",          "void",      "volatile",   "while",
     });
 
-// Names that should be avoided as field names in Kotlin.
-// All Kotlin hard keywords are in this list.
-const std::unordered_set<std::string>* kKotlinForbiddenNames =
-    new std::unordered_set<std::string>({
-        "as",    "as?",   "break", "class",  "continue",  "do",     "else",
-        "false", "for",   "fun",   "if",     "in",        "!in",    "interface",
-        "is",    "!is",   "null",  "object", "package",   "return", "super",
-        "this",  "throw", "true",  "try",    "typealias", "typeof", "val",
-        "var",   "when",  "while",
-    });
-
 bool IsForbidden(const std::string& field_name) {
   for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
     if (field_name == kForbiddenWordList[i]) {

+ 7 - 19
src/google/protobuf/compiler/java/java_helpers.h

@@ -103,21 +103,11 @@ std::string UniqueFileScopeIdentifier(const Descriptor* descriptor);
 std::string FileClassName(const FileDescriptor* file, bool immutable = true);
 
 // Returns the file's Java package name.
-std::string FileJavaPackage(const FileDescriptor* file);
 std::string FileJavaPackage(const FileDescriptor* file, bool immutable);
 
 // Returns output directory for the given package name.
 std::string JavaPackageToDir(std::string package_name);
 
-// TODO(xiaofeng): the following methods are kept for they are exposed
-// publicly in //net/proto2/compiler/java/public/names.h. They return
-// immutable names only and should be removed after mutable API is
-// integrated into google3.
-std::string ClassName(const Descriptor* descriptor);
-std::string ClassName(const EnumDescriptor* descriptor);
-std::string ClassName(const ServiceDescriptor* descriptor);
-std::string ClassName(const FileDescriptor* descriptor);
-
 // Comma-separate list of option-specified interfaces implemented by the
 // Message, to follow the "implements" declaration of the Message definition.
 std::string ExtraMessageInterfaces(const Descriptor* descriptor);
@@ -357,24 +347,22 @@ inline bool IsProto2(const FileDescriptor* descriptor) {
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
-inline bool SupportFieldPresence(const FieldDescriptor* descriptor) {
-  // Note that while proto3 oneofs do conceptually support present, we return
-  // false for them because they do not offer a public hazzer. Therefore this
-  // method could be named HasHazzer().
-  return !descriptor->is_repeated() &&
-         (descriptor->message_type() || descriptor->has_optional_keyword() ||
-          IsProto2(descriptor->file()));
-}
-
 inline bool IsRealOneof(const FieldDescriptor* descriptor) {
   return descriptor->containing_oneof() &&
          !descriptor->containing_oneof()->is_synthetic();
 }
 
+inline bool HasHazzer(const FieldDescriptor* descriptor) {
+  return !descriptor->is_repeated() &&
+         (descriptor->message_type() || descriptor->has_optional_keyword() ||
+          IsProto2(descriptor->file()) || IsRealOneof(descriptor));
+}
+
 inline bool HasHasbit(const FieldDescriptor* descriptor) {
   // Note that currently message fields inside oneofs have hasbits. This is
   // surprising, as the oneof case should avoid any need for a hasbit. But if
   // you change this method to remove hasbits for oneofs, a few tests fail.
+  // TODO(b/124347790): remove hasbits for oneofs
   return !descriptor->is_repeated() &&
          (descriptor->has_optional_keyword() || IsProto2(descriptor->file()));
 }

+ 1 - 0
src/google/protobuf/compiler/java/java_message.cc

@@ -491,6 +491,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
     printer->Print("public static final int $constant_name$ = $number$;\n",
                    "constant_name", FieldConstantName(descriptor_->field(i)),
                    "number", StrCat(descriptor_->field(i)->number()));
+    printer->Annotate("constant_name", descriptor_->field(i));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
   }

+ 2 - 1
src/google/protobuf/compiler/java/java_name_resolver.cc

@@ -33,8 +33,9 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_names.h>
+#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/stubs/substitute.h>
 
 namespace google {

+ 0 - 12
src/google/protobuf/compiler/java/java_names.h

@@ -93,18 +93,6 @@ std::string FileJavaPackage(const FileDescriptor* descriptor);
 //   Capitalized camel case name field name.
 std::string CapitalizedFieldName(const FieldDescriptor* descriptor);
 
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Primitive Java type name for the field.
-const char* PrimitiveTypeName(const FieldDescriptor* descriptor);
-
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Boes primitive Java type name for the field.
-const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor);
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 3
src/google/protobuf/compiler/java/java_plugin_unittest.cc

@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/java/java_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 

+ 20 - 24
src/google/protobuf/compiler/java/java_primitive_field.cc

@@ -204,7 +204,7 @@ int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
 
 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -217,7 +217,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -241,7 +241,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -318,7 +318,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
 
 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -333,7 +333,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
 
 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     if (IsDefaultValueJavaDefault(descriptor_)) {
       printer->Print(variables_,
                      "if ($get_has_field_bit_from_local$) {\n"
@@ -497,16 +497,14 @@ ImmutablePrimitiveOneofFieldGenerator::
 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -522,15 +520,13 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
 
 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,

+ 19 - 23
src/google/protobuf/compiler/java/java_primitive_field_lite.cc

@@ -193,7 +193,7 @@ int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -213,7 +213,7 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
   }
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -259,7 +259,7 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -345,16 +345,14 @@ ImmutablePrimitiveOneofFieldLiteGenerator::
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -395,16 +393,14 @@ void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo(
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,

+ 1 - 0
src/google/protobuf/compiler/java/java_shared_code_generator.cc

@@ -36,6 +36,7 @@
 
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>

+ 20 - 25
src/google/protobuf/compiler/java/java_string_field.cc

@@ -188,7 +188,7 @@ int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
 // UnmodifiableLazyStringList.
 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -207,7 +207,7 @@ void ImmutableStringFieldGenerator::GenerateMembers(
   printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -266,7 +266,7 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
   printer->Print(variables_,
                  "private java.lang.Object $name$_ $default_init$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -384,7 +384,7 @@ void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
 
 void ImmutableStringFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     // Allow a slight breach of abstraction here in order to avoid forcing
     // all string fields to Strings when copying fields from a Message.
     printer->Print(variables_,
@@ -404,7 +404,7 @@ void ImmutableStringFieldGenerator::GenerateMergingCode(
 
 void ImmutableStringFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -484,16 +484,13 @@ ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
 void ImmutableStringOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -551,16 +548,14 @@ void ImmutableStringOneofFieldGenerator::GenerateMembers(
 
 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(

+ 19 - 24
src/google/protobuf/compiler/java/java_string_field_lite.cc

@@ -157,7 +157,7 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
 //     shouldn't be necessary or used on devices.
 void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -176,7 +176,7 @@ void ImmutableStringFieldLiteGenerator::GenerateMembers(
   printer->Print(variables_, "private java.lang.String $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -238,7 +238,7 @@ void ImmutableStringFieldLiteGenerator::GenerateMembers(
 
 void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -337,17 +337,14 @@ ImmutableStringOneofFieldLiteGenerator::
 void ImmutableStringOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -418,16 +415,14 @@ void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo(
 
 void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(

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

@@ -2184,7 +2184,7 @@ void SortMessages(FileDescriptorProto* file_descriptor_proto) {
 void StripFieldTypeName(DescriptorProto* proto) {
   for (int i = 0; i < proto->field_size(); ++i) {
     std::string type_name = proto->field(i).type_name();
-    std::string::size_type pos = type_name.find_last_of(".");
+    std::string::size_type pos = type_name.find_last_of('.');
     if (pos != std::string::npos) {
       proto->mutable_field(i)->mutable_type_name()->assign(
           type_name.begin() + pos + 1, type_name.end());

+ 80 - 122
src/google/protobuf/compiler/plugin.pb.cc

@@ -16,86 +16,69 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
-class VersionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Version> _instance;
-} _Version_default_instance_;
-class CodeGeneratorRequestDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorRequest> _instance;
-} _CodeGeneratorRequest_default_instance_;
-class CodeGeneratorResponse_FileDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> _instance;
-} _CodeGeneratorResponse_File_default_instance_;
-class CodeGeneratorResponseDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse> _instance;
-} _CodeGeneratorResponse_default_instance_;
+constexpr Version::Version(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : suffix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , major_(0)
+  , minor_(0)
+  , patch_(0){}
+struct VersionDefaultTypeInternal {
+  constexpr VersionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~VersionDefaultTypeInternal() {}
+  union {
+    Version _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY VersionDefaultTypeInternal _Version_default_instance_;
+constexpr CodeGeneratorRequest::CodeGeneratorRequest(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_to_generate_()
+  , proto_file_()
+  , parameter_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , compiler_version_(nullptr){}
+struct CodeGeneratorRequestDefaultTypeInternal {
+  constexpr CodeGeneratorRequestDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorRequestDefaultTypeInternal() {}
+  union {
+    CodeGeneratorRequest _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+constexpr CodeGeneratorResponse_File::CodeGeneratorResponse_File(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , insertion_point_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , generated_code_info_(nullptr){}
+struct CodeGeneratorResponse_FileDefaultTypeInternal {
+  constexpr CodeGeneratorResponse_FileDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponse_FileDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse_File _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+constexpr CodeGeneratorResponse::CodeGeneratorResponse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_()
+  , error_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , supported_features_(PROTOBUF_ULONGLONG(0)){}
+struct CodeGeneratorResponseDefaultTypeInternal {
+  constexpr CodeGeneratorResponseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponseDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::Version();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
@@ -191,19 +174,18 @@ const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2epro
 static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
   &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs[4] = {
-  &scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 773,
-  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 4, 1,
+  false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 
+  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+  return descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
@@ -272,12 +254,11 @@ Version::Version(const Version& from)
 }
 
 void Version::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
-      reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+    reinterpret_cast<char*>(&major_)) + sizeof(patch_));
 }
 
 Version::~Version() {
@@ -300,11 +281,6 @@ void Version::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Version::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Version& Version::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Version::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
@@ -607,9 +583,8 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
 }
 
 void CodeGeneratorRequest::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  compiler_version_ = nullptr;
+parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+compiler_version_ = nullptr;
 }
 
 CodeGeneratorRequest::~CodeGeneratorRequest() {
@@ -633,11 +608,6 @@ void CodeGeneratorRequest::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void CodeGeneratorRequest::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorRequest::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
@@ -969,11 +939,10 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon
 }
 
 void CodeGeneratorResponse_File::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  generated_code_info_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+generated_code_info_ = nullptr;
 }
 
 CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
@@ -999,11 +968,6 @@ void CodeGeneratorResponse_File::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Aren
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse_File::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -1310,9 +1274,8 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
 }
 
 void CodeGeneratorResponse::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  supported_features_ = PROTOBUF_ULONGLONG(0);
+error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+supported_features_ = PROTOBUF_ULONGLONG(0);
 }
 
 CodeGeneratorResponse::~CodeGeneratorResponse() {
@@ -1335,11 +1298,6 @@ void CodeGeneratorResponse::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void CodeGeneratorResponse::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)

+ 25 - 20
src/google/protobuf/compiler/plugin.pb.h

@@ -61,19 +61,20 @@ struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 class CodeGeneratorRequest;
-class CodeGeneratorRequestDefaultTypeInternal;
+struct CodeGeneratorRequestDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
 class CodeGeneratorResponse;
-class CodeGeneratorResponseDefaultTypeInternal;
+struct CodeGeneratorResponseDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 class CodeGeneratorResponse_File;
-class CodeGeneratorResponse_FileDefaultTypeInternal;
+struct CodeGeneratorResponse_FileDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
 class Version;
-class VersionDefaultTypeInternal;
+struct VersionDefaultTypeInternal;
 PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
@@ -116,6 +117,7 @@ class PROTOC_EXPORT Version PROTOBUF_FINAL :
  public:
   inline Version() : Version(nullptr) {}
   virtual ~Version();
+  explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Version(const Version& from);
   Version(Version&& from) noexcept
@@ -152,8 +154,9 @@ class PROTOC_EXPORT Version PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Version& default_instance();
-
+  static const Version& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Version* internal_default_instance() {
     return reinterpret_cast<const Version*>(
                &_Version_default_instance_);
@@ -219,8 +222,7 @@ class PROTOC_EXPORT Version PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -316,6 +318,7 @@ class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL :
  public:
   inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {}
   virtual ~CodeGeneratorRequest();
+  explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorRequest(const CodeGeneratorRequest& from);
   CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
@@ -352,8 +355,9 @@ class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorRequest& default_instance();
-
+  static const CodeGeneratorRequest& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorRequest* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorRequest*>(
                &_CodeGeneratorRequest_default_instance_);
@@ -419,8 +423,7 @@ class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -537,6 +540,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL :
  public:
   inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {}
   virtual ~CodeGeneratorResponse_File();
+  explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
   CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
@@ -573,8 +577,9 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorResponse_File& default_instance();
-
+  static const CodeGeneratorResponse_File& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse_File* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse_File*>(
                &_CodeGeneratorResponse_File_default_instance_);
@@ -640,8 +645,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -756,6 +760,7 @@ class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL :
  public:
   inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {}
   virtual ~CodeGeneratorResponse();
+  explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse(const CodeGeneratorResponse& from);
   CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
@@ -792,8 +797,9 @@ class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorResponse& default_instance();
-
+  static const CodeGeneratorResponse& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse*>(
                &_CodeGeneratorResponse_default_instance_);
@@ -859,8 +865,7 @@ class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 5 - 3
src/google/protobuf/compiler/python/python_generator.cc

@@ -69,6 +69,7 @@ namespace python {
 
 namespace {
 
+
 // Returns the Python module name expected for a given .proto filename.
 std::string ModuleName(const std::string& filename) {
   std::string basename = StripProto(filename);
@@ -312,7 +313,6 @@ bool Generator::Generate(const FileDescriptor* file,
     }
   }
 
-
   // Completely serialize all Generate() calls on this instance.  The
   // thread-safety constraints of the CodeGenerator interface aren't clear so
   // just be as conservative as possible.  It's easier to relax this later if
@@ -675,7 +675,8 @@ void Generator::PrintDescriptorKeyAndModuleName(
     const ServiceDescriptor& descriptor) const {
   std::string name = ModuleLevelServiceDescriptorName(descriptor);
   if (!pure_python_workable_) {
-    name = "'" + descriptor.full_name() + "'";
+    name = "_descriptor.ServiceDescriptor(full_name='" +
+           descriptor.full_name() + "')";
   }
   printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key",
                   kDescriptorKey, "descriptor_name", name);
@@ -872,7 +873,8 @@ void Generator::PrintMessage(const Descriptor& message_descriptor,
   if (pure_python_workable_) {
     m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
   } else {
-    m["descriptor_name"] = "'" + message_descriptor.full_name() + "'";
+    m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
+                           message_descriptor.full_name() + "')";
   }
   printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n");
   std::string module_name = ModuleName(file_->name());

+ 2 - 3
src/google/protobuf/compiler/python/python_plugin_unittest.cc

@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/compiler/python/python_generator.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>

+ 22 - 2
src/google/protobuf/descriptor.cc

@@ -1090,7 +1090,7 @@ inline void DescriptorPool::Tables::FindAllExtensions(
 
 bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
                                        Symbol symbol) {
-  if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
+  if (InsertIfNotPresent(&symbols_by_name_, full_name, symbol)) {
     symbols_after_checkpoint_.push_back(full_name.c_str());
     return true;
   } else {
@@ -1106,7 +1106,7 @@ bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
 }
 
 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
-  if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
+  if (InsertIfNotPresent(&files_by_name_, file->name(), file)) {
     files_after_checkpoint_.push_back(file->name().c_str());
     return true;
   } else {
@@ -2626,6 +2626,8 @@ void Descriptor::DebugString(int depth, std::string* contents,
       const Descriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start + 1) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end > FieldDescriptor::kMaxNumber) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end - 1);
@@ -2829,6 +2831,8 @@ void EnumDescriptor::DebugString(
       const EnumDescriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end == INT_MAX) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end);
@@ -4019,6 +4023,11 @@ bool DescriptorBuilder::AddSymbol(const std::string& full_name,
   // Use its file as the parent instead.
   if (parent == nullptr) parent = file_;
 
+  if (full_name.find('\0') != std::string::npos) {
+    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + full_name + "\" contains null character.");
+    return false;
+  }
   if (tables_->AddSymbol(full_name, symbol)) {
     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
       // This is only possible if there was already an error adding something of
@@ -4059,6 +4068,11 @@ bool DescriptorBuilder::AddSymbol(const std::string& full_name,
 void DescriptorBuilder::AddPackage(const std::string& name,
                                    const Message& proto,
                                    const FileDescriptor* file) {
+  if (name.find('\0') != std::string::npos) {
+    AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + name + "\" contains null character.");
+    return;
+  }
   if (tables_->AddSymbol(name, Symbol(file))) {
     // Success.  Also add parent package, if any.
     std::string::size_type dot_pos = name.find_last_of('.');
@@ -4372,6 +4386,12 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl(
   }
   result->pool_ = pool_;
 
+  if (result->name().find('\0') != std::string::npos) {
+    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + result->name() + "\" contains null character.");
+    return nullptr;
+  }
+
   // Add to tables.
   if (!tables_->AddFile(result)) {
     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,

Fișier diff suprimat deoarece este prea mare
+ 439 - 553
src/google/protobuf/descriptor.pb.cc


+ 163 - 135
src/google/protobuf/descriptor.pb.h

@@ -54,87 +54,88 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class DescriptorProto;
-class DescriptorProtoDefaultTypeInternal;
+struct DescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
 class DescriptorProto_ExtensionRange;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal;
+struct DescriptorProto_ExtensionRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
 class DescriptorProto_ReservedRange;
-class DescriptorProto_ReservedRangeDefaultTypeInternal;
+struct DescriptorProto_ReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
 class EnumDescriptorProto;
-class EnumDescriptorProtoDefaultTypeInternal;
+struct EnumDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
 class EnumDescriptorProto_EnumReservedRange;
-class EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
+struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
 class EnumOptions;
-class EnumOptionsDefaultTypeInternal;
+struct EnumOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
 class EnumValueDescriptorProto;
-class EnumValueDescriptorProtoDefaultTypeInternal;
+struct EnumValueDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
 class EnumValueOptions;
-class EnumValueOptionsDefaultTypeInternal;
+struct EnumValueOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
 class ExtensionRangeOptions;
-class ExtensionRangeOptionsDefaultTypeInternal;
+struct ExtensionRangeOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
 class FieldDescriptorProto;
-class FieldDescriptorProtoDefaultTypeInternal;
+struct FieldDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
 class FieldOptions;
-class FieldOptionsDefaultTypeInternal;
+struct FieldOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
 class FileDescriptorProto;
-class FileDescriptorProtoDefaultTypeInternal;
+struct FileDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
 class FileDescriptorSet;
-class FileDescriptorSetDefaultTypeInternal;
+struct FileDescriptorSetDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
 class FileOptions;
-class FileOptionsDefaultTypeInternal;
+struct FileOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
 class GeneratedCodeInfo;
-class GeneratedCodeInfoDefaultTypeInternal;
+struct GeneratedCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 class GeneratedCodeInfo_Annotation;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal;
+struct GeneratedCodeInfo_AnnotationDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
 class MessageOptions;
-class MessageOptionsDefaultTypeInternal;
+struct MessageOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
 class MethodDescriptorProto;
-class MethodDescriptorProtoDefaultTypeInternal;
+struct MethodDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
 class MethodOptions;
-class MethodOptionsDefaultTypeInternal;
+struct MethodOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
 class OneofDescriptorProto;
-class OneofDescriptorProtoDefaultTypeInternal;
+struct OneofDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
 class OneofOptions;
-class OneofOptionsDefaultTypeInternal;
+struct OneofOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
 class ServiceDescriptorProto;
-class ServiceDescriptorProtoDefaultTypeInternal;
+struct ServiceDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
 class ServiceOptions;
-class ServiceOptionsDefaultTypeInternal;
+struct ServiceOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
 class SourceCodeInfo;
-class SourceCodeInfoDefaultTypeInternal;
+struct SourceCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
 class SourceCodeInfo_Location;
-class SourceCodeInfo_LocationDefaultTypeInternal;
+struct SourceCodeInfo_LocationDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
 class UninterpretedOption;
-class UninterpretedOptionDefaultTypeInternal;
+struct UninterpretedOptionDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
 class UninterpretedOption_NamePart;
-class UninterpretedOption_NamePartDefaultTypeInternal;
+struct UninterpretedOption_NamePartDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -334,6 +335,7 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
  public:
   inline FileDescriptorSet() : FileDescriptorSet(nullptr) {}
   virtual ~FileDescriptorSet();
+  explicit constexpr FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorSet(const FileDescriptorSet& from);
   FileDescriptorSet(FileDescriptorSet&& from) noexcept
@@ -370,8 +372,9 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileDescriptorSet& default_instance();
-
+  static const FileDescriptorSet& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorSet* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorSet*>(
                &_FileDescriptorSet_default_instance_);
@@ -437,8 +440,7 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -486,6 +488,7 @@ class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL :
  public:
   inline FileDescriptorProto() : FileDescriptorProto(nullptr) {}
   virtual ~FileDescriptorProto();
+  explicit constexpr FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorProto(const FileDescriptorProto& from);
   FileDescriptorProto(FileDescriptorProto&& from) noexcept
@@ -522,8 +525,9 @@ class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileDescriptorProto& default_instance();
-
+  static const FileDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorProto*>(
                &_FileDescriptorProto_default_instance_);
@@ -589,8 +593,7 @@ class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -879,6 +882,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL :
  public:
   inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {}
   virtual ~DescriptorProto_ExtensionRange();
+  explicit constexpr DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
   DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept
@@ -915,8 +919,9 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto_ExtensionRange& default_instance();
-
+  static const DescriptorProto_ExtensionRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ExtensionRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ExtensionRange*>(
                &_DescriptorProto_ExtensionRange_default_instance_);
@@ -982,8 +987,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1062,6 +1066,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL :
  public:
   inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {}
   virtual ~DescriptorProto_ReservedRange();
+  explicit constexpr DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
   DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept
@@ -1098,8 +1103,9 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto_ReservedRange& default_instance();
-
+  static const DescriptorProto_ReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ReservedRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ReservedRange*>(
                &_DescriptorProto_ReservedRange_default_instance_);
@@ -1165,8 +1171,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1225,6 +1230,7 @@ class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL :
  public:
   inline DescriptorProto() : DescriptorProto(nullptr) {}
   virtual ~DescriptorProto();
+  explicit constexpr DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto(const DescriptorProto& from);
   DescriptorProto(DescriptorProto&& from) noexcept
@@ -1261,8 +1267,9 @@ class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto& default_instance();
-
+  static const DescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto*>(
                &_DescriptorProto_default_instance_);
@@ -1328,8 +1335,7 @@ class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1569,6 +1575,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
  public:
   inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {}
   virtual ~ExtensionRangeOptions();
+  explicit constexpr ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ExtensionRangeOptions(const ExtensionRangeOptions& from);
   ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept
@@ -1605,8 +1612,9 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ExtensionRangeOptions& default_instance();
-
+  static const ExtensionRangeOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ExtensionRangeOptions* internal_default_instance() {
     return reinterpret_cast<const ExtensionRangeOptions*>(
                &_ExtensionRangeOptions_default_instance_);
@@ -1672,8 +1680,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1724,6 +1731,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL :
  public:
   inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {}
   virtual ~FieldDescriptorProto();
+  explicit constexpr FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldDescriptorProto(const FieldDescriptorProto& from);
   FieldDescriptorProto(FieldDescriptorProto&& from) noexcept
@@ -1760,8 +1768,9 @@ class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldDescriptorProto& default_instance();
-
+  static const FieldDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FieldDescriptorProto*>(
                &_FieldDescriptorProto_default_instance_);
@@ -1827,8 +1836,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2156,6 +2164,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL :
  public:
   inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {}
   virtual ~OneofDescriptorProto();
+  explicit constexpr OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofDescriptorProto(const OneofDescriptorProto& from);
   OneofDescriptorProto(OneofDescriptorProto&& from) noexcept
@@ -2192,8 +2201,9 @@ class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const OneofDescriptorProto& default_instance();
-
+  static const OneofDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const OneofDescriptorProto*>(
                &_OneofDescriptorProto_default_instance_);
@@ -2259,8 +2269,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2331,6 +2340,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL :
  public:
   inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {}
   virtual ~EnumDescriptorProto_EnumReservedRange();
+  explicit constexpr EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from);
   EnumDescriptorProto_EnumReservedRange(EnumDescriptorProto_EnumReservedRange&& from) noexcept
@@ -2367,8 +2377,9 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumDescriptorProto_EnumReservedRange& default_instance();
-
+  static const EnumDescriptorProto_EnumReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto_EnumReservedRange*>(
                &_EnumDescriptorProto_EnumReservedRange_default_instance_);
@@ -2434,8 +2445,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2494,6 +2504,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL :
  public:
   inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {}
   virtual ~EnumDescriptorProto();
+  explicit constexpr EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto(const EnumDescriptorProto& from);
   EnumDescriptorProto(EnumDescriptorProto&& from) noexcept
@@ -2530,8 +2541,9 @@ class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumDescriptorProto& default_instance();
-
+  static const EnumDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto*>(
                &_EnumDescriptorProto_default_instance_);
@@ -2597,8 +2609,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2737,6 +2748,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL :
  public:
   inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {}
   virtual ~EnumValueDescriptorProto();
+  explicit constexpr EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
   EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept
@@ -2773,8 +2785,9 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumValueDescriptorProto& default_instance();
-
+  static const EnumValueDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumValueDescriptorProto*>(
                &_EnumValueDescriptorProto_default_instance_);
@@ -2840,8 +2853,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2927,6 +2939,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL :
  public:
   inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {}
   virtual ~ServiceDescriptorProto();
+  explicit constexpr ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceDescriptorProto(const ServiceDescriptorProto& from);
   ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept
@@ -2963,8 +2976,9 @@ class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ServiceDescriptorProto& default_instance();
-
+  static const ServiceDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const ServiceDescriptorProto*>(
                &_ServiceDescriptorProto_default_instance_);
@@ -3030,8 +3044,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3122,6 +3135,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL :
  public:
   inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {}
   virtual ~MethodDescriptorProto();
+  explicit constexpr MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodDescriptorProto(const MethodDescriptorProto& from);
   MethodDescriptorProto(MethodDescriptorProto&& from) noexcept
@@ -3158,8 +3172,9 @@ class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MethodDescriptorProto& default_instance();
-
+  static const MethodDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const MethodDescriptorProto*>(
                &_MethodDescriptorProto_default_instance_);
@@ -3225,8 +3240,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3371,6 +3385,7 @@ class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL :
  public:
   inline FileOptions() : FileOptions(nullptr) {}
   virtual ~FileOptions();
+  explicit constexpr FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileOptions(const FileOptions& from);
   FileOptions(FileOptions&& from) noexcept
@@ -3407,8 +3422,9 @@ class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileOptions& default_instance();
-
+  static const FileOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileOptions* internal_default_instance() {
     return reinterpret_cast<const FileOptions*>(
                &_FileOptions_default_instance_);
@@ -3474,8 +3490,7 @@ class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3929,6 +3944,7 @@ class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL :
  public:
   inline MessageOptions() : MessageOptions(nullptr) {}
   virtual ~MessageOptions();
+  explicit constexpr MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MessageOptions(const MessageOptions& from);
   MessageOptions(MessageOptions&& from) noexcept
@@ -3965,8 +3981,9 @@ class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MessageOptions& default_instance();
-
+  static const MessageOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MessageOptions* internal_default_instance() {
     return reinterpret_cast<const MessageOptions*>(
                &_MessageOptions_default_instance_);
@@ -4032,8 +4049,7 @@ class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4145,6 +4161,7 @@ class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL :
  public:
   inline FieldOptions() : FieldOptions(nullptr) {}
   virtual ~FieldOptions();
+  explicit constexpr FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldOptions(const FieldOptions& from);
   FieldOptions(FieldOptions&& from) noexcept
@@ -4181,8 +4198,9 @@ class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldOptions& default_instance();
-
+  static const FieldOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldOptions* internal_default_instance() {
     return reinterpret_cast<const FieldOptions*>(
                &_FieldOptions_default_instance_);
@@ -4248,8 +4266,7 @@ class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4455,6 +4472,7 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
  public:
   inline OneofOptions() : OneofOptions(nullptr) {}
   virtual ~OneofOptions();
+  explicit constexpr OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofOptions(const OneofOptions& from);
   OneofOptions(OneofOptions&& from) noexcept
@@ -4491,8 +4509,9 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const OneofOptions& default_instance();
-
+  static const OneofOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofOptions* internal_default_instance() {
     return reinterpret_cast<const OneofOptions*>(
                &_OneofOptions_default_instance_);
@@ -4558,8 +4577,7 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4610,6 +4628,7 @@ class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL :
  public:
   inline EnumOptions() : EnumOptions(nullptr) {}
   virtual ~EnumOptions();
+  explicit constexpr EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumOptions(const EnumOptions& from);
   EnumOptions(EnumOptions&& from) noexcept
@@ -4646,8 +4665,9 @@ class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumOptions& default_instance();
-
+  static const EnumOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumOptions* internal_default_instance() {
     return reinterpret_cast<const EnumOptions*>(
                &_EnumOptions_default_instance_);
@@ -4713,8 +4733,7 @@ class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4796,6 +4815,7 @@ class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL :
  public:
   inline EnumValueOptions() : EnumValueOptions(nullptr) {}
   virtual ~EnumValueOptions();
+  explicit constexpr EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueOptions(const EnumValueOptions& from);
   EnumValueOptions(EnumValueOptions&& from) noexcept
@@ -4832,8 +4852,9 @@ class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumValueOptions& default_instance();
-
+  static const EnumValueOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueOptions* internal_default_instance() {
     return reinterpret_cast<const EnumValueOptions*>(
                &_EnumValueOptions_default_instance_);
@@ -4899,8 +4920,7 @@ class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4967,6 +4987,7 @@ class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL :
  public:
   inline ServiceOptions() : ServiceOptions(nullptr) {}
   virtual ~ServiceOptions();
+  explicit constexpr ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceOptions(const ServiceOptions& from);
   ServiceOptions(ServiceOptions&& from) noexcept
@@ -5003,8 +5024,9 @@ class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ServiceOptions& default_instance();
-
+  static const ServiceOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceOptions* internal_default_instance() {
     return reinterpret_cast<const ServiceOptions*>(
                &_ServiceOptions_default_instance_);
@@ -5070,8 +5092,7 @@ class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5138,6 +5159,7 @@ class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL :
  public:
   inline MethodOptions() : MethodOptions(nullptr) {}
   virtual ~MethodOptions();
+  explicit constexpr MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodOptions(const MethodOptions& from);
   MethodOptions(MethodOptions&& from) noexcept
@@ -5174,8 +5196,9 @@ class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MethodOptions& default_instance();
-
+  static const MethodOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodOptions* internal_default_instance() {
     return reinterpret_cast<const MethodOptions*>(
                &_MethodOptions_default_instance_);
@@ -5241,8 +5264,7 @@ class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5356,6 +5378,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL :
  public:
   inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {}
   virtual ~UninterpretedOption_NamePart();
+  explicit constexpr UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
   UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept
@@ -5392,8 +5415,9 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UninterpretedOption_NamePart& default_instance();
-
+  static const UninterpretedOption_NamePart& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption_NamePart* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption_NamePart*>(
                &_UninterpretedOption_NamePart_default_instance_);
@@ -5459,8 +5483,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5529,6 +5552,7 @@ class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL :
  public:
   inline UninterpretedOption() : UninterpretedOption(nullptr) {}
   virtual ~UninterpretedOption();
+  explicit constexpr UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption(const UninterpretedOption& from);
   UninterpretedOption(UninterpretedOption&& from) noexcept
@@ -5565,8 +5589,9 @@ class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UninterpretedOption& default_instance();
-
+  static const UninterpretedOption& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption*>(
                &_UninterpretedOption_default_instance_);
@@ -5632,8 +5657,7 @@ class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5795,6 +5819,7 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL :
  public:
   inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {}
   virtual ~SourceCodeInfo_Location();
+  explicit constexpr SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
   SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept
@@ -5831,8 +5856,9 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const SourceCodeInfo_Location& default_instance();
-
+  static const SourceCodeInfo_Location& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo_Location* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo_Location*>(
                &_SourceCodeInfo_Location_default_instance_);
@@ -5898,8 +5924,7 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6048,6 +6073,7 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
  public:
   inline SourceCodeInfo() : SourceCodeInfo(nullptr) {}
   virtual ~SourceCodeInfo();
+  explicit constexpr SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo(const SourceCodeInfo& from);
   SourceCodeInfo(SourceCodeInfo&& from) noexcept
@@ -6084,8 +6110,9 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const SourceCodeInfo& default_instance();
-
+  static const SourceCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo*>(
                &_SourceCodeInfo_default_instance_);
@@ -6151,8 +6178,7 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6202,6 +6228,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL :
  public:
   inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {}
   virtual ~GeneratedCodeInfo_Annotation();
+  explicit constexpr GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
   GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept
@@ -6238,8 +6265,9 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const GeneratedCodeInfo_Annotation& default_instance();
-
+  static const GeneratedCodeInfo_Annotation& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo_Annotation* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo_Annotation*>(
                &_GeneratedCodeInfo_Annotation_default_instance_);
@@ -6305,8 +6333,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6412,6 +6439,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
  public:
   inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {}
   virtual ~GeneratedCodeInfo();
+  explicit constexpr GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo(const GeneratedCodeInfo& from);
   GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept
@@ -6448,8 +6476,9 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const GeneratedCodeInfo& default_instance();
-
+  static const GeneratedCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo*>(
                &_GeneratedCodeInfo_default_instance_);
@@ -6515,8 +6544,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 65 - 0
src/google/protobuf/descriptor_unittest.cc

@@ -3816,6 +3816,45 @@ TEST_F(ValidationErrorTest, InvalidPackageName) {
       "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
 }
 
+// 'str' is a static C-style string that may contain '\0'
+#define STATIC_STR(str) std::string((str), sizeof(str) - 1)
+
+TEST_F(ValidationErrorTest, NullCharSymbolName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"foo\""
+      "message_type { "
+      "  name: '\\000\\001\\013.Bar' "
+      "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "} "
+      "}",
+      STATIC_STR("bar.proto: foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a "
+                 "valid identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a valid "
+                 "identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar.foo: NAME: \"foo.\0\x1\v.Bar.foo\" contains "
+                 "null character.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"foo.\0\x1\v.Bar\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharFileName) {
+  BuildFileWithErrors(
+      "name: \"bar\\000\\001\\013.proto\" "
+      "package: \"outer.foo\"",
+      STATIC_STR("bar\0\x1\v.proto: bar\0\x1\v.proto: NAME: "
+                 "\"bar\0\x1\v.proto\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharPackageName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"\\000\\001\\013.\"",
+      STATIC_STR("bar.proto: \0\x1\v.: NAME: \"\0\x1\v.\" contains null "
+                 "character.\n"));
+}
+
 TEST_F(ValidationErrorTest, MissingFileName) {
   BuildFileWithErrors("",
 
@@ -4031,6 +4070,32 @@ TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
       file->DebugString());
 }
 
+TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) {
+  const FileDescriptor* file = BuildFile(strings::Substitute(
+      "name: \"foo.proto\" "
+      "enum_type { "
+      "  name: \"Bar\""
+      "  value { name:\"BAR\" number:1 }"
+      "  reserved_range { start: 5 end: $0 }"
+      "}"
+      "message_type {"
+      "  name: \"Foo\""
+      "  reserved_range { start: 5 end: $1 }"
+      "}",
+      std::numeric_limits<int>::max(), FieldDescriptor::kMaxNumber + 1));
+
+  ASSERT_EQ(
+      "syntax = \"proto2\";\n\n"
+      "enum Bar {\n"
+      "  BAR = 1;\n"
+      "  reserved 5 to max;\n"
+      "}\n\n"
+      "message Foo {\n"
+      "  reserved 5 to max;\n"
+      "}\n\n",
+      file->DebugString());
+}
+
 TEST_F(ValidationErrorTest, EnumReservedFieldError) {
   BuildFileWithErrors(
       "name: \"foo.proto\" "

+ 25 - 34
src/google/protobuf/duration.pb.cc

@@ -17,24 +17,20 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class DurationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Duration> _instance;
-} _Duration_default_instance_;
+constexpr Duration::Duration(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : seconds_(PROTOBUF_LONGLONG(0))
+  , nanos_(0){}
+struct DurationDefaultTypeInternal {
+  constexpr DurationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DurationDefaultTypeInternal() {}
+  union {
+    Duration _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Duration_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Duration();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Duration_google_2fprotobuf_2fduration_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
@@ -64,18 +60,18 @@ const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROT
   "uf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Goo"
   "gle.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fduration_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs[1] = {
-  &scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 235,
-  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs, descriptor_table_google_2fprotobuf_2fduration_2eproto_deps, 1, 0,
+  false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 
+  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fduration_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
+  file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
+  return descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
@@ -103,10 +99,10 @@ Duration::Duration(const Duration& from)
 }
 
 void Duration::SharedCtor() {
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
-      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
 }
 
 Duration::~Duration() {
@@ -128,11 +124,6 @@ void Duration::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Duration::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Duration& Duration::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Duration::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)

+ 7 - 5
src/google/protobuf/duration.pb.h

@@ -53,9 +53,10 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Duration;
-class DurationDefaultTypeInternal;
+struct DurationDefaultTypeInternal;
 PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@ class PROTOBUF_EXPORT Duration PROTOBUF_FINAL :
  public:
   inline Duration() : Duration(nullptr) {}
   virtual ~Duration();
+  explicit constexpr Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Duration(const Duration& from);
   Duration(Duration&& from) noexcept
@@ -99,8 +101,9 @@ class PROTOBUF_EXPORT Duration PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Duration& default_instance();
-
+  static const Duration& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Duration* internal_default_instance() {
     return reinterpret_cast<const Duration*>(
                &_Duration_default_instance_);
@@ -166,8 +169,7 @@ class PROTOBUF_EXPORT Duration PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fduration_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 80 - 145
src/google/protobuf/dynamic_message.cc

@@ -67,6 +67,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <unordered_map>
 
 #include <google/protobuf/descriptor.pb.h>
@@ -256,38 +257,10 @@ inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); }
 
 class DynamicMessage : public Message {
  public:
-  struct TypeInfo {
-    int size;
-    int has_bits_offset;
-    int oneof_case_offset;
-    int extensions_offset;
-
-    // Not owned by the TypeInfo.
-    DynamicMessageFactory* factory;  // The factory that created this object.
-    const DescriptorPool* pool;      // The factory's DescriptorPool.
-    const Descriptor* type;          // Type of this DynamicMessage.
-
-    // Warning:  The order in which the following pointers are defined is
-    //   important (the prototype must be deleted *before* the offsets).
-    std::unique_ptr<uint32[]> offsets;
-    std::unique_ptr<uint32[]> has_bits_indices;
-    std::unique_ptr<const Reflection> reflection;
-    // Don't use a unique_ptr to hold the prototype: the destructor for
-    // DynamicMessage needs to know whether it is the prototype, and does so by
-    // looking back at this field. This would assume details about the
-    // implementation of unique_ptr.
-    const DynamicMessage* prototype;
-    int weak_field_map_offset;  // The offset for the weak_field_map;
-
-    TypeInfo() : prototype(NULL) {}
-
-    ~TypeInfo() { delete prototype; }
-  };
-
-  DynamicMessage(const TypeInfo* type_info);
+  explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info);
 
   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
-  DynamicMessage(TypeInfo* type_info, bool lock_factory);
+  DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory);
 
   ~DynamicMessage();
 
@@ -311,6 +284,9 @@ class DynamicMessage : public Message {
 
   Metadata GetMetadata() const override;
 
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+  static void operator delete(DynamicMessage* msg, std::destroying_delete_t);
+#else
   // We actually allocate more memory than sizeof(*this) when this
   // class's memory is allocated via the global operator new. Thus, we need to
   // manually call the global operator delete. Calling the destructor is taken
@@ -319,21 +295,18 @@ class DynamicMessage : public Message {
 #ifndef _MSC_VER
   static void operator delete(void* ptr) { ::operator delete(ptr); }
 #endif  // !_MSC_VER
+#endif
 
  private:
-  DynamicMessage(const TypeInfo* type_info, Arena* arena);
+  DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                 Arena* arena);
 
   void SharedCtor(bool lock_factory);
 
   // Needed to get the offset of the internal metadata member.
   friend class DynamicMessageFactory;
 
-  inline bool is_prototype() const {
-    return type_info_->prototype == this ||
-           // If type_info_->prototype is NULL, then we must be constructing
-           // the prototype now, which means we must be the prototype.
-           type_info_->prototype == NULL;
-  }
+  bool is_prototype() const;
 
   inline void* OffsetToPointer(int offset) {
     return reinterpret_cast<uint8*>(this) + offset;
@@ -342,24 +315,52 @@ class DynamicMessage : public Message {
     return reinterpret_cast<const uint8*>(this) + offset;
   }
 
-  const TypeInfo* type_info_;
+  const DynamicMessageFactory::TypeInfo* type_info_;
   mutable std::atomic<int> cached_byte_size_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 };
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info)
+struct DynamicMessageFactory::TypeInfo {
+  int size;
+  int has_bits_offset;
+  int oneof_case_offset;
+  int extensions_offset;
+
+  // Not owned by the TypeInfo.
+  DynamicMessageFactory* factory;  // The factory that created this object.
+  const DescriptorPool* pool;      // The factory's DescriptorPool.
+  const Descriptor* type;          // Type of this DynamicMessage.
+
+  // Warning:  The order in which the following pointers are defined is
+  //   important (the prototype must be deleted *before* the offsets).
+  std::unique_ptr<uint32[]> offsets;
+  std::unique_ptr<uint32[]> has_bits_indices;
+  std::unique_ptr<const Reflection> reflection;
+  // Don't use a unique_ptr to hold the prototype: the destructor for
+  // DynamicMessage needs to know whether it is the prototype, and does so by
+  // looking back at this field. This would assume details about the
+  // implementation of unique_ptr.
+  const DynamicMessage* prototype;
+  int weak_field_map_offset;  // The offset for the weak_field_map;
+
+  TypeInfo() : prototype(nullptr) {}
+
+  ~TypeInfo() { delete prototype; }
+};
+
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info)
     : type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
-    : Message(arena),
-      type_info_(type_info),
-      cached_byte_size_(0) {
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                               Arena* arena)
+    : Message(arena), type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
+DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info,
+                               bool lock_factory)
     : type_info_(type_info), cached_byte_size_(0) {
   // The prototype in type_info has to be set before creating the prototype
   // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
@@ -484,6 +485,22 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
   }
 }
 
+bool DynamicMessage::is_prototype() const {
+  return type_info_->prototype == this ||
+         // If type_info_->prototype is NULL, then we must be constructing
+         // the prototype now, which means we must be the prototype.
+         type_info_->prototype == nullptr;
+}
+
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+void DynamicMessage::operator delete(DynamicMessage* msg,
+                                     std::destroying_delete_t) {
+  const size_t size = msg->type_info_->size;
+  msg->~DynamicMessage();
+  ::operator delete(msg, size);
+}
+#endif
+
 DynamicMessage::~DynamicMessage() {
   const Descriptor* descriptor = type_info_->type;
 
@@ -517,11 +534,11 @@ DynamicMessage::~DynamicMessage() {
           switch (field->options().ctype()) {
             default:
             case FieldOptions::STRING: {
-              const std::string* default_value =
-                  reinterpret_cast<const ArenaStringPtr*>(
-                      reinterpret_cast<const uint8*>(type_info_->prototype) +
-                      type_info_->offsets[i])
-                      ->GetPointer();
+              // Oneof string fields are never set as a default instance.
+              // We just need to pass some arbitrary default string to make it
+              // work. This allows us to not have the real default accessible
+              // from reflection.
+              const std::string* default_value = nullptr;
               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
                   default_value, NULL);
               break;
@@ -610,6 +627,7 @@ void DynamicMessage::CrossLinkPrototypes() {
     const FieldDescriptor* field = descriptor->field(i);
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->options().weak() && !InRealOneof(field) &&
         !field->is_repeated()) {
       // For fields with message types, we need to cross-link with the
       // prototype for the field's type.
@@ -652,27 +670,14 @@ Metadata DynamicMessage::GetMetadata() const {
 
 // ===================================================================
 
-struct DynamicMessageFactory::PrototypeMap {
-  typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
-      Map;
-  Map map_;
-};
-
 DynamicMessageFactory::DynamicMessageFactory()
-    : pool_(NULL),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(nullptr), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
-    : pool_(pool),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(pool), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::~DynamicMessageFactory() {
-  for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
-       iter != prototypes_->map_.end(); ++iter) {
-    DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
-                               iter->second->prototype);
+  for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) {
     delete iter->second;
   }
 }
@@ -689,13 +694,13 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
     return MessageFactory::generated_factory()->GetPrototype(type);
   }
 
-  const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
+  const TypeInfo** target = &prototypes_[type];
   if (*target != NULL) {
     // Already exists.
     return (*target)->prototype;
   }
 
-  DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
+  TypeInfo* type_info = new TypeInfo;
   *target = type_info;
 
   type_info->type = type;
@@ -772,7 +777,6 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
   // All the fields.
   //
   // TODO(b/31226269):  Optimize the order of fields to minimize padding.
-  int num_weak_fields = 0;
   for (int i = 0; i < type->field_count(); i++) {
     // Make sure field is aligned to avoid bus errors.
     // Oneof fields do not use any space.
@@ -807,14 +811,16 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
     if (type->oneof_decl(i)->is_synthetic()) continue;
     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      int field_size = OneofFieldSpaceUsed(field);
-      size = AlignTo(size, std::min(kSafeAlignment, field_size));
-      offsets[field->index()] = size;
-      size += field_size;
+      // oneof fields are not accessed through offsets, but we still have the
+      // entry from a legacy implementation. This should be removed at some
+      // point.
+      // Mark the field to prevent unintentional access through reflection.
+      // Don't use the top bit because that is for unused fields.
+      offsets[field->index()] = internal::kInvalidFieldOffsetTag;
     }
   }
-  size = AlignOffset(size);
-  // Allocate the prototype + oneof fields.
+
+  // Allocate the prototype fields.
   void* base = operator new(size);
   memset(base, 0, size);
 
@@ -822,12 +828,6 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
   // of dynamic message to avoid dead lock.
   DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
 
-  if (real_oneof_count > 0 || num_weak_fields > 0) {
-    // Construct default oneof instance.
-    ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
-                                  prototype);
-  }
-
   internal::ReflectionSchema schema = {
       type_info->prototype,
       type_info->offsets.get(),
@@ -848,71 +848,6 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
   return prototype;
 }
 
-void DynamicMessageFactory::ConstructDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    void* default_oneof_or_weak_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      void* field_ptr =
-          reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
-          offsets[field->index()];
-      switch (field->cpp_type()) {
-#define HANDLE_TYPE(CPPTYPE, TYPE)                       \
-  case FieldDescriptor::CPPTYPE_##CPPTYPE:               \
-    new (field_ptr) TYPE(field->default_value_##TYPE()); \
-    break;
-
-        HANDLE_TYPE(INT32, int32);
-        HANDLE_TYPE(INT64, int64);
-        HANDLE_TYPE(UINT32, uint32);
-        HANDLE_TYPE(UINT64, uint64);
-        HANDLE_TYPE(DOUBLE, double);
-        HANDLE_TYPE(FLOAT, float);
-        HANDLE_TYPE(BOOL, bool);
-#undef HANDLE_TYPE
-
-        case FieldDescriptor::CPPTYPE_ENUM:
-          new (field_ptr) int(field->default_value_enum()->number());
-          break;
-        case FieldDescriptor::CPPTYPE_STRING:
-          switch (field->options().ctype()) {
-            default:
-            case FieldOptions::STRING:
-              ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
-              asp->UnsafeSetDefault(&field->default_value_string());
-              break;
-          }
-          break;
-
-        case FieldDescriptor::CPPTYPE_MESSAGE: {
-          new (field_ptr) Message*(NULL);
-          break;
-        }
-      }
-    }
-  }
-}
-
-void DynamicMessageFactory::DeleteDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    const void* default_oneof_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-        switch (field->options().ctype()) {
-          default:
-          case FieldOptions::STRING:
-            break;
-        }
-      }
-    }
-  }
-}
-
 }  // namespace protobuf
 }  // namespace google
 

+ 3 - 17
src/google/protobuf/dynamic_message.h

@@ -40,6 +40,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <unordered_map>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
@@ -128,28 +129,13 @@ class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
   const DescriptorPool* pool_;
   bool delegate_to_generated_factory_;
 
-  // This struct just contains a hash_map.  We can't #include <hash_map> from
-  // this header due to hacks needed for hash_map portability in the open source
-  // release.  Namely, stubs/hash.h, which defines hash_map portably, is not a
-  // public header (for good reason), but dynamic_message.h is, and public
-  // headers may only #include other public headers.
-  struct PrototypeMap;
-  std::unique_ptr<PrototypeMap> prototypes_;
+  struct TypeInfo;
+  std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
   mutable internal::WrappedMutex prototypes_mutex_;
 
   friend class DynamicMessage;
   const Message* GetPrototypeNoLock(const Descriptor* type);
 
-  // Construct default oneof instance for reflection usage if oneof
-  // is defined.
-  static void ConstructDefaultOneofInstance(const Descriptor* type,
-                                            const uint32 offsets[],
-                                            void* default_oneof_instance);
-  // Delete default oneof instance. Called by ~DynamicMessageFactory.
-  static void DeleteDefaultOneofInstance(const Descriptor* type,
-                                         const uint32 offsets[],
-                                         const void* default_oneof_instance);
-
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
 };
 

+ 19 - 30
src/google/protobuf/empty.pb.cc

@@ -17,24 +17,18 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class EmptyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Empty> _instance;
-} _Empty_default_instance_;
+constexpr Empty::Empty(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
+struct EmptyDefaultTypeInternal {
+  constexpr EmptyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EmptyDefaultTypeInternal() {}
+  union {
+    Empty _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Empty_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Empty();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Empty_google_2fprotobuf_2fempty_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
@@ -61,18 +55,18 @@ const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBU
   "/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.P"
   "rotobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fempty_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs[1] = {
-  &scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 190,
-  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs, descriptor_table_google_2fprotobuf_2fempty_2eproto_deps, 1, 0,
+  false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 
+  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fempty_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
+  file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
+  return descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
@@ -118,11 +112,6 @@ void Empty::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void Empty::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Empty& Empty::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Empty::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)

+ 7 - 5
src/google/protobuf/empty.pb.h

@@ -53,9 +53,10 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Empty;
-class EmptyDefaultTypeInternal;
+struct EmptyDefaultTypeInternal;
 PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@ class PROTOBUF_EXPORT Empty PROTOBUF_FINAL :
  public:
   inline Empty() : Empty(nullptr) {}
   virtual ~Empty();
+  explicit constexpr Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Empty(const Empty& from);
   Empty(Empty&& from) noexcept
@@ -99,8 +101,9 @@ class PROTOBUF_EXPORT Empty PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Empty& default_instance();
-
+  static const Empty& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Empty* internal_default_instance() {
     return reinterpret_cast<const Empty*>(
                &_Empty_default_instance_);
@@ -166,8 +169,7 @@ class PROTOBUF_EXPORT Empty PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fempty_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 3 - 6
src/google/protobuf/extension_set.cc

@@ -1454,9 +1454,9 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
   return ParseMessageSetLite(input, &finder, &skipper);
 }
 
-uint8* ExtensionSet::_InternalSerialize(int start_field_number,
-                                        int end_field_number, uint8* target,
-                                        io::EpsCopyOutputStream* stream) const {
+uint8* ExtensionSet::_InternalSerializeImpl(
+    int start_field_number, int end_field_number, uint8* target,
+    io::EpsCopyOutputStream* stream) const {
   if (PROTOBUF_PREDICT_FALSE(is_large())) {
     const auto& end = map_.large->end();
     for (auto it = map_.large->lower_bound(start_field_number);
@@ -1885,9 +1885,6 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
   }
   flat_capacity_ = new_flat_capacity;
   map_ = new_map;
-  if (is_large()) {
-    flat_size_ = 0;
-  }
 }
 
 // static

+ 12 - 1
src/google/protobuf/extension_set.h

@@ -469,7 +469,14 @@ class PROTOBUF_EXPORT ExtensionSet {
   // Returns a pointer past the last written byte.
   uint8* _InternalSerialize(int start_field_number, int end_field_number,
                             uint8* target,
-                            io::EpsCopyOutputStream* stream) const;
+                            io::EpsCopyOutputStream* stream) const {
+    if (flat_size_ == 0) {
+      assert(!is_large());
+      return target;
+    }
+    return _InternalSerializeImpl(start_field_number, end_field_number, target,
+                                  stream);
+  }
 
   // Like above but serializes in MessageSet format.
   void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const {
@@ -510,6 +517,10 @@ class PROTOBUF_EXPORT ExtensionSet {
   int SpaceUsedExcludingSelf() const;
 
  private:
+  // Implementation of _InternalSerialize for non-empty map_.
+  uint8* _InternalSerializeImpl(int start_field_number, int end_field_number,
+                                uint8* target,
+                                io::EpsCopyOutputStream* stream) const;
   // Interface of a lazily parsed singular message extension.
   class PROTOBUF_EXPORT LazyMessageExtension {
    public:

+ 20 - 31
src/google/protobuf/field_mask.pb.cc

@@ -17,24 +17,19 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class FieldMaskDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldMask> _instance;
-} _FieldMask_default_instance_;
+constexpr FieldMask::FieldMask(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : paths_(){}
+struct FieldMaskDefaultTypeInternal {
+  constexpr FieldMaskDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldMaskDefaultTypeInternal() {}
+  union {
+    FieldMask _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldMask();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
@@ -63,18 +58,18 @@ const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[]
   "n/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf"
   ".WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs[1] = {
-  &scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 223,
-  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps, 1, 0,
+  false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 
+  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
+  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
+  return descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
@@ -101,7 +96,6 @@ FieldMask::FieldMask(const FieldMask& from)
 }
 
 void FieldMask::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
 }
 
 FieldMask::~FieldMask() {
@@ -123,11 +117,6 @@ void FieldMask::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
 void FieldMask::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldMask& FieldMask::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldMask::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)

+ 7 - 5
src/google/protobuf/field_mask.pb.h

@@ -53,9 +53,10 @@ struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class FieldMask;
-class FieldMaskDefaultTypeInternal;
+struct FieldMaskDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@ class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL :
  public:
   inline FieldMask() : FieldMask(nullptr) {}
   virtual ~FieldMask();
+  explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldMask(const FieldMask& from);
   FieldMask(FieldMask&& from) noexcept
@@ -99,8 +101,9 @@ class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL :
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldMask& default_instance();
-
+  static const FieldMask& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldMask* internal_default_instance() {
     return reinterpret_cast<const FieldMask*>(
                &_FieldMask_default_instance_);
@@ -166,8 +169,7 @@ class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL :
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:

+ 2 - 5
src/google/protobuf/generated_message_reflection.cc

@@ -2479,11 +2479,8 @@ void AssignDescriptorsImpl(const DescriptorTable* table, bool eager) {
 }
 
 void AddDescriptorsImpl(const DescriptorTable* table) {
-  // Reflection refers to the default instances so make sure they are
-  // initialized.
-  for (int i = 0; i < table->num_sccs; i++) {
-    internal::InitSCC(table->init_default_instances[i]);
-  }
+  // Reflection refers to the default fields so make sure they are initialized.
+  internal::InitProtobufDefaults();
 
   // Ensure all dependent descriptors are registered to the generated descriptor
   // pool and message factory.

+ 5 - 6
src/google/protobuf/generated_message_reflection.h

@@ -253,25 +253,24 @@ struct MigrationSchema {
   int object_size;
 };
 
-struct SCCInfoBase;
-
+// This struct tries to reduce unnecessary padding.
+// The num_xxx might not be close to their respective pointer, but this saves
+// padding.
 struct PROTOBUF_EXPORT DescriptorTable {
   mutable bool is_initialized;
   bool is_eager;
+  int size;  // of serialized descriptor
   const char* descriptor;
   const char* filename;
-  int size;  // of serialized descriptor
   once_flag* once;
-  SCCInfoBase* const* init_default_instances;
   const DescriptorTable* const* deps;
-  int num_sccs;
   int num_deps;
+  int num_messages;
   const MigrationSchema* schemas;
   const Message* const* default_instances;
   const uint32* offsets;
   // update the following descriptor arrays.
   Metadata* file_level_metadata;
-  int num_messages;
   const EnumDescriptor** file_level_enum_descriptors;
   const ServiceDescriptor** file_level_service_descriptors;
 };

+ 8 - 4
src/google/protobuf/generated_message_table_driven.h

@@ -207,11 +207,15 @@ static_assert(std::is_standard_layout<ParseTableField>::value, "");
 static_assert(std::is_trivial<ParseTableField>::value, "");
 static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
-static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
+              "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
 static_assert(std::is_standard_layout<ParseTable>::value, "");
 static_assert(std::is_trivial<ParseTable>::value, "");

+ 5 - 84
src/google/protobuf/generated_message_util.cc

@@ -34,14 +34,8 @@
 
 #include <google/protobuf/generated_message_util.h>
 
+#include <atomic>
 #include <limits>
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-// We're only using this as a standard way for getting the thread id.
-// We're not using any thread functionality.
-#include <thread>  // NOLINT
-#endif             // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
 #include <vector>
 
 #include <google/protobuf/io/coded_stream.h>
@@ -51,7 +45,6 @@
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
 
@@ -73,19 +66,15 @@ void DestroyString(const void* s) {
 }
 
 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
-    PROTOBUF_ATTRIBUTE_INIT_PRIORITY EmptyString
-        fixed_address_empty_string;  // NOLINT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed<std::string>
+        fixed_address_empty_string{};  // NOLINT
 
 
 PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false};
 static bool InitProtobufDefaultsImpl() {
-  ::new (static_cast<void*>(&fixed_address_empty_string.value)) std::string();
-  OnShutdownDestroyString(&fixed_address_empty_string.value);
+  fixed_address_empty_string.DefaultConstruct();
+  OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
 
-  // Verify that we can indeed get the address during constant evaluation.
-  PROTOBUF_CONSTINIT static const std::string& fixed_address_empty_string_test =
-      GetEmptyStringAlreadyInited();
-  (void)fixed_address_empty_string_test;
 
   init_protobuf_defaults_state.store(true, std::memory_order_release);
   return true;
@@ -741,74 +730,6 @@ MessageLite* GetOwnedMessageInternal(Arena* message_arena,
   }
 }
 
-namespace {
-
-void InitSCC_DFS(SCCInfoBase* scc) {
-  if (scc->visit_status.load(std::memory_order_relaxed) !=
-      SCCInfoBase::kUninitialized)
-    return;
-  scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed);
-  // Each base is followed by an array of void*, containing first pointers to
-  // SCCInfoBase and then pointers-to-pointers to SCCInfoBase.
-  auto deps = reinterpret_cast<void**>(scc + 1);
-  auto strong_deps = reinterpret_cast<SCCInfoBase* const*>(deps);
-  for (int i = 0; i < scc->num_deps; ++i) {
-    if (strong_deps[i]) InitSCC_DFS(strong_deps[i]);
-  }
-  auto implicit_weak_deps =
-      reinterpret_cast<SCCInfoBase** const*>(deps + scc->num_deps);
-  for (int i = 0; i < scc->num_implicit_weak_deps; ++i) {
-    if (*implicit_weak_deps[i]) {
-      InitSCC_DFS(*implicit_weak_deps[i]);
-    }
-  }
-  scc->init_func();
-  // Mark done (note we use memory order release here), other threads could
-  // now see this as initialized and thus the initialization must have happened
-  // before.
-  scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release);
-}
-
-}  // namespace
-
-void InitSCCImpl(SCCInfoBase* scc) {
-  static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
-  // Either the default in case no initialization is running or the id of the
-  // thread that is currently initializing.
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  static std::atomic<std::thread::id> runner;
-  auto me = std::this_thread::get_id();
-#else
-  // This is a lightweight replacement for std::thread::id. std::thread does not
-  // work on Windows XP SP2 with the latest VC++ libraries, because it utilizes
-  // the Concurrency Runtime that is only supported on Windows XP SP3 and above.
-  static std::atomic_llong runner(-1);
-  auto me = ::GetCurrentThreadId();
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  // This will only happen because the constructor will call InitSCC while
-  // constructing the default instance.
-  if (runner.load(std::memory_order_relaxed) == me) {
-    // Because we're in the process of constructing the default instance.
-    // We can be assured that we're already exploring this SCC.
-    GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed),
-             SCCInfoBase::kRunning);
-    return;
-  }
-  InitProtobufDefaults();
-  mu.Lock();
-  runner.store(me, std::memory_order_relaxed);
-  InitSCC_DFS(scc);
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  runner.store(std::thread::id{}, std::memory_order_relaxed);
-#else
-  runner.store(-1, std::memory_order_relaxed);
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  mu.Unlock();
-}
-
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google

+ 0 - 58
src/google/protobuf/generated_message_util.h

@@ -192,64 +192,6 @@ class PROTOBUF_EXPORT CachedSize {
   std::atomic<int> size_{0};
 };
 
-// SCCInfo represents information of a strongly connected component of
-// mutual dependent messages.
-struct PROTOBUF_EXPORT SCCInfoBase {
-  // We use 0 for the Initialized state, because test eax,eax, jnz is smaller
-  // and is subject to macro fusion.
-  enum {
-    kInitialized = 0,  // final state
-    kRunning = 1,
-    kUninitialized = -1,  // initial state
-  };
-#if defined(_MSC_VER) && !defined(__clang__)
-  // MSVC doesn't make std::atomic constant initialized. This union trick
-  // makes it so.
-  union {
-    int visit_status_to_make_linker_init;
-    std::atomic<int> visit_status;
-  };
-#else
-  std::atomic<int> visit_status;
-#endif
-  int num_deps;
-  int num_implicit_weak_deps;
-  void (*init_func)();
-  // This is followed by an array  of num_deps
-  // const SCCInfoBase* deps[];
-};
-
-// Zero-length arrays are a language extension available in GCC and Clang but
-// not MSVC.
-#ifdef __GNUC__
-#define PROTOBUF_ARRAY_SIZE(n) (n)
-#else
-#define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1)
-#endif
-
-template <int N>
-struct SCCInfo {
-  SCCInfoBase base;
-  // Semantically this is const SCCInfo<T>* which is is a templated type.
-  // The obvious inheriting from SCCInfoBase mucks with struct initialization.
-  // Attempts showed the compiler was generating dynamic initialization code.
-  // This deps array consists of base.num_deps pointers to SCCInfoBase followed
-  // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra
-  // pointer indirection for implicit weak fields. We cannot use a union type
-  // here, since that would prevent the array from being linker-initialized.
-  void* deps[PROTOBUF_ARRAY_SIZE(N)];
-};
-
-#undef PROTOBUF_ARRAY_SIZE
-
-PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc);
-
-inline void InitSCC(SCCInfoBase* scc) {
-  auto status = scc->visit_status.load(std::memory_order_acquire);
-  if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized))
-    InitSCCImpl(scc);
-}
-
 PROTOBUF_EXPORT void DestroyMessage(const void* message);
 PROTOBUF_EXPORT void DestroyString(const void* s);
 // Destroy (not delete) the message

+ 4 - 4
src/google/protobuf/has_bits.h

@@ -47,17 +47,17 @@ namespace internal {
 template <size_t doublewords>
 class HasBits {
  public:
-  constexpr HasBits() PROTOBUF_ALWAYS_INLINE : has_bits_{} {}
+  constexpr HasBits() PROTOBUF_NDEBUG_INLINE : has_bits_{} {}
 
-  void Clear() PROTOBUF_ALWAYS_INLINE {
+  void Clear() PROTOBUF_NDEBUG_INLINE {
     memset(has_bits_, 0, sizeof(has_bits_));
   }
 
-  uint32& operator[](int index) PROTOBUF_ALWAYS_INLINE {
+  uint32& operator[](int index) PROTOBUF_NDEBUG_INLINE {
     return has_bits_[index];
   }
 
-  const uint32& operator[](int index) const PROTOBUF_ALWAYS_INLINE {
+  const uint32& operator[](int index) const PROTOBUF_NDEBUG_INLINE {
     return has_bits_[index];
   }
 

+ 1 - 1
src/google/protobuf/map_type_handler.h

@@ -586,7 +586,7 @@ inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::IsInitialized(
   constexpr auto                                                              \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit()         \
       ->TypeOnMemory {                                                        \
-    return TypeOnMemory(&internal::GetEmptyStringAlreadyInited());            \
+    return TypeOnMemory(&internal::fixed_address_empty_string);               \
   }                                                                           \
   template <typename Type>                                                    \
   inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,            \

+ 1 - 1
src/google/protobuf/message.cc

@@ -178,7 +178,7 @@ namespace {
 #define STR_HASH_FXN hash<::google::protobuf::StringPiece>
 
 
-class GeneratedMessageFactory : public MessageFactory {
+class GeneratedMessageFactory final : public MessageFactory {
  public:
   static GeneratedMessageFactory* singleton();
 

+ 1 - 1
src/google/protobuf/message.h

@@ -231,7 +231,7 @@ bool CreateUnknownEnumValues(const FieldDescriptor* field);
 // the internal library are allowed to create subclasses.
 class PROTOBUF_EXPORT Message : public MessageLite {
  public:
-  constexpr Message() = default;
+  constexpr Message() {}
 
   // Basic Operations ------------------------------------------------
 

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff