瀏覽代碼

Merged 3.13.x into master

Adam Cozzette 5 年之前
父節點
當前提交
58f4260e8e
共有 100 個文件被更改,包括 2002 次插入1532 次删除
  1. 5 0
      .gitignore
  2. 11 2
      CHANGES.txt
  3. 11 10
      Makefile.am
  4. 1 1
      Protobuf-C++.podspec
  5. 1 1
      Protobuf.podspec
  6. 1 1
      configure.ac
  7. 0 56
      conformance/failure_list_php.txt
  8. 0 56
      conformance/failure_list_php_c.txt
  9. 0 56
      conformance/failure_list_php_c_32.txt
  10. 1 1
      csharp/Google.Protobuf.Tools.nuspec
  11. 1 2
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  12. 1 1
      java/bom/pom.xml
  13. 1 1
      java/core/pom.xml
  14. 6 0
      java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
  15. 1 1
      java/lite/pom.xml
  16. 1 1
      java/pom.xml
  17. 1 1
      java/util/pom.xml
  18. 1 1
      js/package.json
  19. 96 0
      kokoro/linux/dockerfile/test/php80/Dockerfile
  20. 18 0
      kokoro/linux/php80/build.sh
  21. 11 0
      kokoro/linux/php80/continuous.cfg
  22. 11 0
      kokoro/linux/php80/presubmit.cfg
  23. 1 1
      kokoro/macos/prepare_build_macos_rc
  24. 19 0
      kokoro/release/python/macos/config.sh
  25. 14 4
      php/ext/google/protobuf/array.c
  26. 48 13
      php/ext/google/protobuf/convert.c
  27. 10 14
      php/ext/google/protobuf/def.c
  28. 11 5
      php/ext/google/protobuf/map.c
  29. 131 28
      php/ext/google/protobuf/message.c
  30. 61 5
      php/ext/google/protobuf/package.xml
  31. 137 78
      php/ext/google/protobuf/php-upb.c
  32. 7 10
      php/ext/google/protobuf/php-upb.h
  33. 7 0
      php/ext/google/protobuf/protobuf.c
  34. 28 0
      php/ext/google/protobuf/protobuf.h
  35. 10 10
      php/phpunit.xml
  36. 2 23
      php/src/GPBMetadata/Google/Protobuf/Struct.php
  37. 8 0
      php/src/Google/Protobuf/Descriptor.php
  38. 8 0
      php/src/Google/Protobuf/FieldDescriptor.php
  39. 23 73
      php/src/Google/Protobuf/Internal/DescriptorProto.php
  40. 35 26
      php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
  41. 24 18
      php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
  42. 23 38
      php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
  43. 24 18
      php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
  44. 24 25
      php/src/Google/Protobuf/Internal/EnumOptions.php
  45. 35 26
      php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
  46. 12 16
      php/src/Google/Protobuf/Internal/EnumValueOptions.php
  47. 0 7
      php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
  48. 11 1
      php/src/Google/Protobuf/Internal/FieldDescriptor.php
  49. 133 100
      php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
  50. 74 63
      php/src/Google/Protobuf/Internal/FieldOptions.php
  51. 58 92
      php/src/Google/Protobuf/Internal/FileDescriptorProto.php
  52. 0 7
      php/src/Google/Protobuf/Internal/FileDescriptorSet.php
  53. 241 188
      php/src/Google/Protobuf/Internal/FileOptions.php
  54. 0 7
      php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
  55. 36 34
      php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
  56. 20 6
      php/src/Google/Protobuf/Internal/Message.php
  57. 48 43
      php/src/Google/Protobuf/Internal/MessageOptions.php
  58. 71 53
      php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
  59. 25 26
      php/src/Google/Protobuf/Internal/MethodOptions.php
  60. 23 17
      php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
  61. 0 7
      php/src/Google/Protobuf/Internal/OneofOptions.php
  62. 23 24
      php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
  63. 12 16
      php/src/Google/Protobuf/Internal/ServiceOptions.php
  64. 0 7
      php/src/Google/Protobuf/Internal/SourceCodeInfo.php
  65. 24 39
      php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
  66. 72 61
      php/src/Google/Protobuf/Internal/UninterpretedOption.php
  67. 24 18
      php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
  68. 1 0
      php/src/Google/Protobuf/NullValue.php
  69. 5 0
      php/src/Google/Protobuf/OneofDescriptor.php
  70. 30 0
      php/src/Google/Protobuf/Value.php
  71. 1 1
      php/tests/ArrayTest.php
  72. 0 0
      php/tests/DescriptorsTest.php
  73. 36 0
      php/tests/EncodeDecodeTest.php
  74. 22 0
      php/tests/GeneratedClassTest.php
  75. 0 0
      php/tests/GeneratedPhpdocTest.php
  76. 0 0
      php/tests/GeneratedServiceTest.php
  77. 0 0
      php/tests/MapFieldTest.php
  78. 1 1
      php/tests/PhpImplementationTest.php
  79. 0 0
      php/tests/WellKnownTest.php
  80. 0 0
      php/tests/WrapperTypeSettersTest.php
  81. 8 1
      php/tests/compatibility_test.sh
  82. 8 8
      php/tests/compile_extension.sh
  83. 2 2
      php/tests/generate_protos.sh
  84. 21 0
      php/tests/proto/test.proto
  85. 6 3
      php/tests/test.sh
  86. 14 28
      php/tests/test_util.php
  87. 12 0
      php/tests/valgrind.supp
  88. 1 1
      protoc-artifacts/pom.xml
  89. 1 1
      python/google/protobuf/__init__.py
  90. 5 1
      python/release.sh
  91. 1 0
      python/setup.py
  92. 1 1
      ruby/google-protobuf.gemspec
  93. 1 1
      src/Makefile.am
  94. 2 2
      src/google/protobuf/any.pb.h
  95. 2 2
      src/google/protobuf/api.pb.h
  96. 33 34
      src/google/protobuf/compiler/php/php_generator.cc
  97. 5 0
      src/google/protobuf/compiler/php/php_generator.h
  98. 2 2
      src/google/protobuf/compiler/plugin.pb.h
  99. 2 2
      src/google/protobuf/descriptor.pb.h
  100. 2 2
      src/google/protobuf/duration.pb.h

+ 5 - 0
.gitignore

@@ -137,19 +137,24 @@ conformance/*.class
 
 # php test output
 composer.lock
+php/tests/.phpunit.result.cache
 php/tests/generated/
 php/tests/old_protoc
+php/tests/phpunit-9.phar
 php/tests/protobuf/
 php/tests/core
 php/tests/vgcore*
 php/tests/multirequest.result
 php/tests/nohup.out
+php/tests/.phpunit.result.cache
+php/tests/phpunit-*
 php/ext/google/protobuf/.libs/
 php/ext/google/protobuf/Makefile.fragments
 php/ext/google/protobuf/Makefile.global
 php/ext/google/protobuf/Makefile.objects
 php/ext/google/protobuf/acinclude.m4
 php/ext/google/protobuf/build/
+php/ext/google/protobuf/bundled_php.c
 php/ext/google/protobuf/config.h
 php/ext/google/protobuf/config.h.in~
 php/ext/google/protobuf/config.nice

+ 11 - 2
CHANGES.txt

@@ -1,4 +1,4 @@
-Unreleased Changes
+2020-07-14 version 3.13.0-rc1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
 
   C++:
   * Removed deprecated unsafe arena string accessors
@@ -37,10 +37,19 @@ Unreleased Changes
     type internally. (#7351)
   * Add `ParseFrom(ReadOnlySequence<byte>)` method to enable GC friendly
     parsing with reduced allocations and buffer copies. (#7351)
+  * Add support for serialization directly to a `IBufferWriter<byte>` or
+    to a `Span<byte>` to enable GC friendly serialization.
+    The new API is available as extension methods on the `IMessage` type. (#7576)
   * Add `GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE` define to make
     generated code compatible with old C# compilers (pre-roslyn compilers
     from .NET framework and old versions of mono) that do not support
-    ref structs. (#7490)
+    ref structs. Users that are still on a legacy stack that does
+    not support C# 7.2 compiler might need to use the new define
+    in their projects to be able to build the newly generated code. (#7490)
+  * Due to the major overhaul of parsing and serialization internals (#7351 and #7576),
+    it is recommended to regenerate your generated code to achieve the best
+    performance (the legacy generated code will still work, but might incur
+    a slight performance penalty).
 
 2020-06-01 version 3.12.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
 

+ 11 - 10
Makefile.am

@@ -916,23 +916,23 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/UInt64Value.php                             \
   php/src/Google/Protobuf/Value.php                                   \
   php/src/phpdoc.dist.xml                                             \
-  php/tests/array_test.php                                            \
+  php/tests/ArrayTest.php                                             \
   php/tests/autoload.php                                              \
   php/tests/bootstrap_phpunit.php                                     \
   php/tests/compatibility_test.sh                                     \
   php/tests/compile_extension.sh                                      \
-  php/tests/descriptors_test.php                                      \
-  php/tests/encode_decode_test.php                                    \
+  php/tests/DescriptorsTest.php                                       \
+  php/tests/EncodeDecodeTest.php                                      \
   php/tests/gdb_test.sh                                               \
   php/tests/generate_protos.sh                                        \
-  php/tests/generated_class_test.php                                  \
-  php/tests/generated_phpdoc_test.php                                 \
-  php/tests/generated_service_test.php                                \
-  php/tests/map_field_test.php                                        \
+  php/tests/GeneratedClassTest.php                                    \
+  php/tests/GeneratedPhpdocTest.php                                   \
+  php/tests/GeneratedServiceTest.php                                  \
+  php/tests/MapFieldTest.php                                          \
   php/tests/memory_leak_test.php                                      \
   php/tests/multirequest.php                                          \
   php/tests/multirequest.sh                                           \
-  php/tests/php_implementation_test.php                               \
+  php/tests/PhpImplementationTest.php                                 \
   php/tests/proto/empty/echo.proto                                    \
   php/tests/proto/test.proto                                          \
   php/tests/proto/test_descriptors.proto                              \
@@ -955,8 +955,9 @@ php_EXTRA_DIST=                                                       \
   php/tests/test_base.php                                             \
   php/tests/test_util.php                                             \
   php/tests/undefined_test.php                                        \
-  php/tests/well_known_test.php                                       \
-  php/tests/wrapper_type_setters_test.php
+  php/tests/valgrind.supp                                             \
+  php/tests/WellKnownTest.php                                         \
+  php/tests/WrapperTypeSettersTest.php
 
 python_EXTRA_DIST=                                                           \
   python/MANIFEST.in                                                         \

+ 1 - 1
Protobuf-C++.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'Protobuf-C++'
-  s.version  = '3.12.3'
+  s.version  = '3.13.0'
   s.summary  = 'Protocol Buffers v3 runtime library for C++.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'

+ 1 - 1
Protobuf.podspec

@@ -5,7 +5,7 @@
 # dependent projects use the :git notation to refer to the library.
 Pod::Spec.new do |s|
   s.name     = 'Protobuf'
-  s.version  = '3.12.3'
+  s.version  = '3.13.0'
   s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
   s.homepage = 'https://github.com/protocolbuffers/protobuf'
   s.license  = '3-Clause BSD License'

+ 1 - 1
configure.ac

@@ -17,7 +17,7 @@ AC_PREREQ(2.59)
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.12.3],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.13.0],[protobuf@googlegroups.com],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 

+ 0 - 56
conformance/failure_list_php.txt

@@ -6,62 +6,6 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
 Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
 Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
 Required.Proto3.JsonInput.DoubleFieldTooSmall
 Required.Proto3.JsonInput.FloatFieldTooLarge

+ 0 - 56
conformance/failure_list_php_c.txt

@@ -1,58 +1,2 @@
 Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator

+ 0 - 56
conformance/failure_list_php_c_32.txt

@@ -1,58 +1,2 @@
 Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator

+ 1 - 1
csharp/Google.Protobuf.Tools.nuspec

@@ -5,7 +5,7 @@
     <title>Google Protocol Buffers tools</title>
     <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
     <description>See project site for more info.</description>
-    <version>3.12.3</version>
+    <version>3.13.0</version>
     <authors>Google Inc.</authors>
     <owners>protobuf-packages</owners>
     <licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>

+ 1 - 2
csharp/src/Google.Protobuf/Google.Protobuf.csproj

@@ -4,8 +4,7 @@
     <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
     <Copyright>Copyright 2015, Google Inc.</Copyright>
     <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
-    <VersionPrefix>3.12.2</VersionPrefix>
-    <VersionPrefix>3.12.3</VersionPrefix>
+    <VersionPrefix>3.13.0</VersionPrefix>
     <!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
     <LangVersion>7.2</LangVersion>
     <Authors>Google Inc.</Authors>

+ 1 - 1
java/bom/pom.xml

@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-bom</artifactId>
-  <version>3.12.3</version>
+  <version>3.13.0</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [BOM]</name>

+ 1 - 1
java/core/pom.xml

@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.12.3</version>
+    <version>3.13.0</version>
   </parent>
 
   <artifactId>protobuf-java</artifactId>

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

@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import org.junit.Ignore;
 import protobuf_unittest.NonNestedExtension;
 import protobuf_unittest.NonNestedExtensionLite;
 import java.lang.reflect.Method;
@@ -52,7 +53,12 @@ import junit.framework.TestSuite;
  *
  * <p>The test mechanism employed here is based on the pattern in {@code
  * com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest}
+ *
+ * <p> This test is temporarily disabled due to what appears to be a subtle change to class loading
+ * behavior in Java 11. That seems to have broken the way the test uses a custom ClassLoader to
+ * exercise Lite functionality.
  */
+@Ignore
 public class ExtensionRegistryFactoryTest extends TestCase {
 
   // A classloader which blacklists some non-Lite classes.

+ 1 - 1
java/lite/pom.xml

@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.12.3</version>
+    <version>3.13.0</version>
   </parent>
 
   <artifactId>protobuf-javalite</artifactId>

+ 1 - 1
java/pom.xml

@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-parent</artifactId>
-  <version>3.12.3</version>
+  <version>3.13.0</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [Parent]</name>

+ 1 - 1
java/util/pom.xml

@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.12.3</version>
+    <version>3.13.0</version>
   </parent>
 
   <artifactId>protobuf-java-util</artifactId>

+ 1 - 1
js/package.json

@@ -1,6 +1,6 @@
 {
   "name": "google-protobuf",
-  "version": "3.12.3",
+  "version": "3.13.0",
   "description": "Protocol Buffers for JavaScript",
   "main": "google-protobuf.js",
   "files": [

+ 96 - 0
kokoro/linux/dockerfile/test/php80/Dockerfile

@@ -0,0 +1,96 @@
+FROM debian:jessie
+
+# Install dependencies.  We start with the basic ones require to build protoc
+# and the C++ build
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  git \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  parallel \
+  time \
+  wget \
+  re2c \
+  sqlite3 \
+  vim \
+  libonig-dev \
+  libsqlite3-dev \
+  && apt-get clean
+
+# Install php dependencies
+RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
+  php5 \
+  libcurl4-openssl-dev \
+  libgmp-dev \
+  libgmp3-dev \
+  libssl-dev \
+  libxml2-dev \
+  unzip \
+  zlib1g-dev \
+  pkg-config \
+  && apt-get clean
+
+# Install other dependencies
+RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
+RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz
+RUN cd /var/local \
+  && tar -zxvf bison-3.0.1.tar.gz \
+  && cd /var/local/bison-3.0.1 \
+  && ./configure \
+  && make \
+  && make install
+
+# Install composer
+RUN curl -sS https://getcomposer.org/installer | php
+RUN mv composer.phar /usr/local/bin/composer
+
+# Download php source code
+RUN git clone https://github.com/php/php-src
+
+# php 8.0
+RUN cd php-src \
+  && git checkout php-8.0.0alpha3 \
+  && ./buildconf --force
+RUN cd php-src \
+  && ./configure \
+  --enable-bcmath \
+  --enable-mbstring \
+  --with-gmp \
+  --with-openssl \
+  --with-zlib \
+  --prefix=/usr/local/php-8.0 \
+  && make \
+  && make install \
+  && make clean
+RUN cd php-src \
+  && ./configure \
+  --enable-bcmath \
+  --enable-mbstring \
+  --enable-maintainer-zts \
+  --with-gmp \
+  --with-openssl \
+  --with-zlib \
+  --prefix=/usr/local/php-8.0-zts \
+  && make \
+  && make install \
+  && make clean
+
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-9.phar \
+  && chmod +x phpunit \
+  && cp phpunit /usr/local/php-8.0/bin \
+  && mv phpunit /usr/local/php-8.0-zts/bin
+
+# Install php dependencies
+RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
+  valgrind \
+  && apt-get clean

+ 18 - 0
kokoro/linux/php80/build.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "pull request" project:
+#
+# This script selects a specific Dockerfile (for building a Docker image) and
+# a script to run inside that image.  Then we delegate to the general
+# build_and_run_docker.sh script.
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php
+export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
+export OUTPUT_DIR=testoutput
+export TEST_SET="php8.0_all"
+./kokoro/linux/build_and_run_docker.sh

+ 11 - 0
kokoro/linux/php80/continuous.cfg

@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/php80/build.sh"
+timeout_mins: 120
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}

+ 11 - 0
kokoro/linux/php80/presubmit.cfg

@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/php80/build.sh"
+timeout_mins: 120
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}

+ 1 - 1
kokoro/macos/prepare_build_macos_rc

@@ -66,7 +66,7 @@ fi
 # Install Tox
 
 if [[ "${KOKORO_INSTALL_TOX:-}" == "yes" ]] ; then
-  sudo pip install tox==2.4.1
+  sudo python3 -m pip install --upgrade pip tox
 fi
 
 ##

+ 19 - 0
kokoro/release/python/macos/config.sh

@@ -1,6 +1,25 @@
 # Define custom utilities
 # Test for OSX with [ -n "$IS_OSX" ]
 
+function remove_travis_ve_pip {
+    # Removing the system virtualenv or pip can be very problematic for
+    # macOS on Kokoro, so just leave them be.
+    :;
+}
+
+function install_pip {
+    check_python
+    PIP_CMD="sudo $PYTHON_EXE -m pip${pip_args:+ $pip_args}"
+    $PIP_CMD install --upgrade pip
+}
+
+function install_virtualenv {
+    check_python
+    check_pip
+    $PIP_CMD install --upgrade virtualenv
+    VIRTUALENV_CMD="$PYTHON_EXE -m virtualenv"
+}
+
 function pre_build {
     # Any stuff that you need to do before you start building the wheels
     # Runs in the root directory of this repository.

+ 14 - 4
php/ext/google/protobuf/array.c

@@ -94,11 +94,12 @@ static void RepeatedField_destructor(zend_object* obj) {
   zend_object_std_dtor(&intern->std);
 }
 
-static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) {
+static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) {
   return NULL;  // We do not have a properties table.
 }
 
-static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member,
+static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object,
+                                             PROTO_STR *member,
                                              int type, void **cache_slot) {
   return NULL;  // We don't offer direct references to our properties.
 }
@@ -392,6 +393,15 @@ PHP_METHOD(RepeatedField, getIterator) {
   RETURN_ZVAL(&ret, 0, 1);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
+  ZEND_ARG_INFO(0, type)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1)
+  ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
   ZEND_ARG_INFO(0, index)
 ZEND_END_ARG_INFO()
@@ -405,8 +415,8 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
 ZEND_END_ARG_INFO()
 
 static zend_function_entry repeated_field_methods[] = {
-  PHP_ME(RepeatedField, __construct,  NULL,              ZEND_ACC_PUBLIC)
-  PHP_ME(RepeatedField, append,       NULL,              ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedField, __construct,  arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedField, append,       arginfo_append,    ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetGet,    arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)

+ 48 - 13
php/ext/google/protobuf/convert.c

@@ -92,20 +92,55 @@ PHP_METHOD(Util, checkRepeatedField) {
   RETURN_ZVAL(val, 1, 0);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1)
+  ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, key_type)
+  ZEND_ARG_INFO(0, value_type)
+  ZEND_ARG_INFO(0, value_class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, type)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry util_methods[] = {
-  PHP_ME(Util, checkInt32,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkUint32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkInt64,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkUint64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkEnum,   NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkFloat,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkDouble, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkBool,   NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkBytes,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkMapField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkRepeatedField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkInt32,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkUint32, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkInt64,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkUint64, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkEnum,   arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkFloat,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkDouble, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkBool,   arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkString, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkBytes,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkMessage, arginfo_checkMessage,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkMapField, arginfo_checkMapField,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
   ZEND_FE_END
 };
 

+ 10 - 14
php/ext/google/protobuf/def.c

@@ -180,8 +180,7 @@ PHP_METHOD(EnumDescriptor, getValue) {
   zend_long index;
   zval ret;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
@@ -284,8 +283,7 @@ PHP_METHOD(OneofDescriptor, getField) {
   zend_long index;
   zval ret;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
@@ -615,8 +613,7 @@ PHP_METHOD(Descriptor, getField) {
   zval ret;
   zend_long index;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
@@ -658,8 +655,7 @@ PHP_METHOD(Descriptor, getOneofDecl) {
   zend_long index;
   zval ret;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
@@ -799,8 +795,8 @@ PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
   zend_string *str;
   zval ret;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
-                            &classname_len) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
+      FAILURE) {
     return;
   }
 
@@ -828,8 +824,8 @@ PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
   zend_string *str;
   zval ret;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
-                            &classname_len) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
+      FAILURE) {
     return;
   }
 
@@ -856,8 +852,8 @@ PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {
   zend_long protoname_len;
   const upb_msgdef *m;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protoname,
-                            &protoname_len) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) ==
+      FAILURE) {
     return;
   }
 

+ 11 - 5
php/ext/google/protobuf/map.c

@@ -90,12 +90,12 @@ static void MapField_destructor(zend_object* obj) {
   zend_object_std_dtor(&intern->std);
 }
 
-static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type,
-                                      void **cache_slot) {
+static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member,
+                                   int type, void **cache_slot) {
   return NULL;  // We don't offer direct references to our properties.
 }
 
-static HashTable *map_get_properties(zval *object TSRMLS_DC) {
+static HashTable *Map_GetProperties(PROTO_VAL *object) {
   return NULL;  // We do not have a properties table.
 }
 
@@ -378,6 +378,12 @@ PHP_METHOD(MapField, getIterator) {
   RETURN_ZVAL(&ret, 0, 1);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
+  ZEND_ARG_INFO(0, key_type)
+  ZEND_ARG_INFO(0, value_type)
+  ZEND_ARG_INFO(0, value_class)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
   ZEND_ARG_INFO(0, index)
 ZEND_END_ARG_INFO()
@@ -391,7 +397,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
 ZEND_END_ARG_INFO()
 
 static zend_function_entry MapField_methods[] = {
-  PHP_ME(MapField, __construct,  NULL,              ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, __construct,  arginfo_construct, ZEND_ACC_PUBLIC)
   PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(MapField, offsetGet,    arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(MapField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
@@ -572,7 +578,7 @@ void Map_ModuleInit() {
   h = &MapField_object_handlers;
   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
   h->dtor_obj = MapField_destructor;
-  h->get_properties = map_get_properties;
+  h->get_properties = Map_GetProperties;
   h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;
 
   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter",

+ 131 - 28
php/ext/google/protobuf/message.c

@@ -95,10 +95,10 @@ static void Message_dtor(zend_object* obj) {
  *
  * Helper function to look up a field given a member name (as a string).
  */
-static const upb_fielddef *get_field(Message *msg, zval *member) {
+static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) {
   const upb_msgdef *m = msg->desc->msgdef;
   const upb_fielddef *f =
-      upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member));
+      upb_msgdef_ntof(m, PROTO_STRVAL_P(member), PROTO_STRLEN_P(member));
 
   if (!f) {
     zend_throw_exception_ex(NULL, 0, "No such property %s.",
@@ -108,6 +108,78 @@ static const upb_fielddef *get_field(Message *msg, zval *member) {
   return f;
 }
 
+/**
+ * Message_has_property()
+ *
+ * Object handler for testing whether a property exists. Called when PHP code
+ * does any of:
+ *
+ *   isset($message->foobar);
+ *   property_exists($message->foobar);
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like this
+ * (if the field has presence):
+ *
+ *   public function hasOptionalInt32()
+ *   {
+ *       return isset($this->optional_int32);
+ *   }
+ */
+static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member,
+                                int has_set_exists,
+                                void **cache_slot) {
+  Message* intern = PROTO_MSG_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (!f) return 0;
+
+  if (!upb_fielddef_haspresence(f)) {
+    zend_throw_exception_ex(
+        NULL, 0,
+        "Cannot call isset() on field %s which does not have presence.",
+        ZSTR_VAL(intern->desc->class_entry->name));
+    return 0;
+  }
+
+  return upb_msg_has(intern->msg, f);
+}
+
+/**
+ * Message_unset_property()
+ *
+ * Object handler for unsetting a property. Called when PHP code calls:
+ * does any of:
+ *
+ *   unset($message->foobar);
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like this
+ * (if the field has presence):
+ *
+ *   public function clearOptionalInt32()
+ *   {
+ *       unset($this->optional_int32);
+ *   }
+ */
+static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member,
+                                   void **cache_slot) {
+  Message* intern = PROTO_MSG_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (!f) return;
+
+  if (!upb_fielddef_haspresence(f)) {
+    zend_throw_exception_ex(
+        NULL, 0,
+        "Cannot call unset() on field %s which does not have presence.",
+        ZSTR_VAL(intern->desc->class_entry->name));
+    return;
+  }
+
+  upb_msg_clearfield(intern->msg, f);
+}
+
 /**
  * Message_read_property()
  *
@@ -126,9 +198,9 @@ static const upb_fielddef *get_field(Message *msg, zval *member) {
  * We lookup the field and return the scalar, RepeatedField, or MapField for
  * this field.
  */
-static zval *Message_read_property(zval *obj, zval *member, int type,
-                                   void **cache_slot, zval *rv) {
-  Message* intern = (Message*)Z_OBJ_P(obj);
+static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member,
+                                   int type, void **cache_slot, zval *rv) {
+  Message* intern = PROTO_MSG_P(obj);
   const upb_fielddef *f = get_field(intern, member);
   upb_arena *arena = Arena_Get(&intern->arena);
 
@@ -170,29 +242,41 @@ static zval *Message_read_property(zval *obj, zval *member, int type,
  * The C extension version of checkInt32() doesn't actually check anything, so
  * we perform all checking and conversion in this function.
  */
-static void Message_write_property(zval *obj, zval *member, zval *val,
-                                   void **cache_slot) {
-  Message* intern = (Message*)Z_OBJ_P(obj);
+static PROTO_RETURN_VAL Message_write_property(
+    PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) {
+  Message* intern = PROTO_MSG_P(obj);
   const upb_fielddef *f = get_field(intern, member);
   upb_arena *arena = Arena_Get(&intern->arena);
   upb_msgval msgval;
 
-  if (!f) return;
+  if (!f) goto error;
 
   if (upb_fielddef_ismap(f)) {
     msgval.map_val = MapField_GetUpbMap(val, f, arena);
-    if (!msgval.map_val) return;
+    if (!msgval.map_val) goto error;
   } else if (upb_fielddef_isseq(f)) {
     msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
-    if (!msgval.array_val) return;
+    if (!msgval.array_val) goto error;
   } else {
     upb_fieldtype_t type = upb_fielddef_type(f);
     const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
     bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
-    if (!ok) return;
+    if (!ok) goto error;
   }
 
   upb_msg_set(intern->msg, f, msgval, arena);
+#if PHP_VERSION_ID < 704000
+  return;
+#else
+  return val;
+#endif
+
+error:
+#if PHP_VERSION_ID < 704000
+  return;
+#else
+  return &EG(error_zval);
+#endif
 }
 
 /**
@@ -202,7 +286,8 @@ static void Message_write_property(zval *obj, zval *member, zval *val,
  * reference to our internal properties. We don't support this, so we return
  * NULL.
  */
-static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type,
+static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member,
+                                          int type,
                                           void **cache_slot) {
   return NULL;  // We do not have a properties table.
 }
@@ -213,7 +298,7 @@ static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type,
  * Object handler for the get_properties event in PHP. This returns a HashTable
  * of our internal properties. We don't support this, so we return NULL.
  */
-static HashTable* Message_get_properties(zval* object TSRMLS_DC) {
+static HashTable *Message_get_properties(PROTO_VAL *object) {
   return NULL;  // We don't offer direct references to our properties.
 }
 
@@ -549,7 +634,7 @@ PHP_METHOD(Message, serializeToJsonString) {
   zend_bool preserve_proto_fieldnames = false;
   upb_status status;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b",
                             &preserve_proto_fieldnames) == FAILURE) {
     return;
   }
@@ -800,20 +885,36 @@ PHP_METHOD(Message, writeOneof) {
   upb_msg_set(intern->msg, f, msgval, arena);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFrom, 0, 0, 1)
+  ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_read, 0, 0, 1)
+  ZEND_ARG_INFO(0, field)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_write, 0, 0, 2)
+  ZEND_ARG_INFO(0, field)
+  ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry Message_methods[] = {
-  PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED)
+  PHP_ME(Message, clear,                 arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, discardUnknownFields,  arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, serializeToString,     arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFromString,       arginfo_mergeFrom, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, serializeToJsonString, arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFromJsonString,   arginfo_mergeFrom, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFrom,             arginfo_mergeFrom, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, readWrapperValue,      arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, writeWrapperValue,     arginfo_write,     ZEND_ACC_PROTECTED)
+  PHP_ME(Message, readOneof,             arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, writeOneof,            arginfo_write,     ZEND_ACC_PROTECTED)
+  PHP_ME(Message, whichOneof,            arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, __construct,           arginfo_void,      ZEND_ACC_PROTECTED)
   ZEND_FE_END
 };
 
@@ -836,6 +937,8 @@ void Message_ModuleInit() {
   h->dtor_obj = Message_dtor;
   h->read_property = Message_read_property;
   h->write_property = Message_write_property;
+  h->has_property = Message_has_property;
+  h->unset_property = Message_unset_property;
   h->get_properties = Message_get_properties;
   h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
 }

+ 61 - 5
php/ext/google/protobuf/package.xml

@@ -10,11 +10,11 @@
   <email>protobuf-opensource@google.com</email>
   <active>yes</active>
  </lead>
- <date>2020-06-01</date>
- <time>01:14:10</time>
+ <date>2020-08-14</date>
+ <time>14:07:59</time>
  <version>
-  <release>3.12.3</release>
-  <api>3.12.3</api>
+  <release>3.13.0</release>
+  <api>3.13.0</api>
  </version>
  <stability>
   <release>stable</release>
@@ -51,7 +51,7 @@
  <dependencies>
   <required>
    <php>
-    <min>5.5.9</min>
+    <min>7.0.0</min>
    </php>
    <pearinstaller>
     <min>1.4.0</min>
@@ -619,5 +619,61 @@ G  A release.
    <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
    <notes>GA release.</notes>
   </release>
+  <release>
+   <version>
+    <release>3.13.0RC1</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-05</date>
+   <time>11:21:41</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0RC2</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-05</date>
+   <time>11:22:52</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0RC3</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-12</date>
+   <time>13:46:54</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-08-14</date>
+   <time>14:07:59</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
  </changelog>
 </package>

+ 137 - 78
php/ext/google/protobuf/php-upb.c

@@ -174,6 +174,11 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
 #else
 #define UPB_INFINITY (1.0 / 0.0)
 #endif
+#ifdef NAN
+#define UPB_NAN NAN
+#else
+#define UPB_NAN (0.0 / 0.0)
+#endif
 
 #include <setjmp.h>
 #include <string.h>
@@ -235,11 +240,13 @@ static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
                                    (1 << UPB_DTYPE_SFIXED64);
 
 /* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_SCALAR_LG2(n) (n)
-#define OP_FIXPCK_LG2(n) (n + 4)
-#define OP_VARPCK_LG2(n) (n + 8)
+#define OP_SCALAR_LG2(n) (n)      /* n in [0, 2, 3] => op in [0, 2, 3] */
 #define OP_STRING 4
-#define OP_SUBMSG 5
+#define OP_BYTES 5
+#define OP_SUBMSG 6
+/* Ops above are scalar-only. Repeated fields can use any op.  */
+#define OP_FIXPCK_LG2(n) (n + 5)  /* n in [2, 3] => op in [7, 8] */
+#define OP_VARPCK_LG2(n) (n + 9)  /* n in [0, 2, 3] => op in [9, 11, 12] */
 
 static const int8_t varint_ops[19] = {
     -1,               /* field not found */
@@ -277,7 +284,7 @@ static const int8_t delim_ops[37] = {
     OP_STRING, /* STRING */
     -1,        /* GROUP */
     OP_SUBMSG, /* MESSAGE */
-    OP_STRING, /* BYTES */
+    OP_BYTES,  /* BYTES */
     -1,        /* UINT32 */
     -1,        /* ENUM */
     -1,        /* SFIXED32 */
@@ -296,7 +303,7 @@ static const int8_t delim_ops[37] = {
     OP_STRING,        /* REPEATED STRING */
     OP_SUBMSG,        /* REPEATED GROUP */
     OP_SUBMSG,        /* REPEATED MESSAGE */
-    OP_STRING,        /* REPEATED BYTES */
+    OP_BYTES,         /* REPEATED BYTES */
     OP_VARPCK_LG2(2), /* REPEATED UINT32 */
     OP_VARPCK_LG2(2), /* REPEATED ENUM */
     OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
@@ -328,6 +335,40 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
 
 UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); }
 
+void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
+  static const uint8_t utf8_offset[] = {
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+      1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+      2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+      4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+  };
+
+  int i, j;
+  uint8_t offset;
+
+  i = 0;
+  while (i < len) {
+    offset = utf8_offset[(uint8_t)buf[i]];
+    if (offset == 0 || i + offset > len) {
+      decode_err(d);
+    }
+    for (j = i + 1; j < i + offset; j++) {
+      if ((buf[j] & 0xc0) != 0x80) {
+        decode_err(d);
+      }
+    }
+    i += offset;
+  }
+  if (i != len) decode_err(d);
+}
+
 static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
   bool need_realloc = arr->size - arr->len < elem;
   if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) {
@@ -395,7 +436,7 @@ static void decode_munge(int type, wireval *val) {
 
 static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
                                                  uint32_t field_number) {
-  static upb_msglayout_field none = {0};
+  static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
 
   /* Lots of optimization opportunities here. */
   int i;
@@ -473,7 +514,10 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
       memcpy(mem, &val, 1 << op);
       return ptr;
     case OP_STRING:
-      /* Append string. */
+      decode_verifyutf8(d, val.str_val.data, val.str_val.size);
+      /* Fallthrough. */
+    case OP_BYTES:
+      /* Append bytes. */
       mem =
           UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void);
       arr->len++;
@@ -607,6 +651,9 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
       break;
     }
     case OP_STRING:
+      decode_verifyutf8(d, val.str_val.data, val.str_val.size);
+      /* Fallthrough. */
+    case OP_BYTES:
       memcpy(mem, &val, sizeof(upb_strview));
       break;
     case OP_SCALAR_LG2(3):
@@ -1892,17 +1939,6 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
   return success;
 }
 
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
-  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
-}
-
-upb_value upb_inttable_pop(upb_inttable *t) {
-  upb_value val;
-  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
-  UPB_ASSERT(ok);
-  return val;
-}
-
 bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
                              upb_alloc *a) {
   return upb_inttable_insert2(t, (uintptr_t)key, val, a);
@@ -2328,15 +2364,28 @@ struct upb_arena {
 
 static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
 
+static upb_arena *arena_findroot(upb_arena *a) {
+  /* Path splitting keeps time complexity down, see:
+   *   https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
+  while (a->parent != a) {
+    upb_arena *next = a->parent;
+    a->parent = next->parent;
+    a = next;
+  }
+  return a;
+}
+
 static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) {
   mem_block *block = ptr;
+  upb_arena *root = arena_findroot(a);
 
-  block->next = a->freelist;
+  /* The block is for arena |a|, but should appear in the freelist of |root|. */
+  block->next = root->freelist;
   block->size = (uint32_t)size;
   block->cleanups = 0;
-  a->freelist = block;
+  root->freelist = block;
   a->last_size = block->size;
-  if (!a->freelist_tail) a->freelist_tail = block;
+  if (!root->freelist_tail) root->freelist_tail = block;
 
   a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
   a->head.end = UPB_PTR_AT(block, size, char);
@@ -2371,17 +2420,6 @@ static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
   return upb_arena_realloc(a, ptr, oldsize, size);
 }
 
-static upb_arena *arena_findroot(upb_arena *a) {
-  /* Path splitting keeps time complexity down, see:
-   *   https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
-  while (a->parent != a) {
-    upb_arena *next = a->parent;
-    a->parent = next->parent;
-    a = next;
-  }
-  return a;
-}
-
 /* Public Arena API ***********************************************************/
 
 upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
@@ -2540,9 +2578,9 @@ static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6]
 };
 
 static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {3, UPB_SIZE(36, 72), 0, 0, 9, 3},
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(36, 72), 0, 0, 12, 3},
   {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
   {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
   {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
@@ -2551,7 +2589,7 @@ static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12]
   {9, UPB_SIZE(32, 64), 5, 5, 11, 1},
   {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
   {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
-  {12, UPB_SIZE(20, 40), 3, 0, 9, 1},
+  {12, UPB_SIZE(20, 40), 3, 0, 12, 1},
 };
 
 const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
@@ -2571,7 +2609,7 @@ static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = {
 };
 
 static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
   {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
   {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
   {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
@@ -2580,7 +2618,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
   {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
   {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
   {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
-  {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
+  {10, UPB_SIZE(44, 88), 0, 0, 12, 3},
 };
 
 const upb_msglayout google_protobuf_DescriptorProto_msginit = {
@@ -2635,16 +2673,16 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1
 };
 
 static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
-  {1, UPB_SIZE(36, 40), 6, 0, 9, 1},
-  {2, UPB_SIZE(44, 56), 7, 0, 9, 1},
+  {1, UPB_SIZE(36, 40), 6, 0, 12, 1},
+  {2, UPB_SIZE(44, 56), 7, 0, 12, 1},
   {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
   {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
   {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {6, UPB_SIZE(52, 72), 8, 0, 9, 1},
-  {7, UPB_SIZE(60, 88), 9, 0, 9, 1},
+  {6, UPB_SIZE(52, 72), 8, 0, 12, 1},
+  {7, UPB_SIZE(60, 88), 9, 0, 12, 1},
   {8, UPB_SIZE(76, 120), 11, 0, 11, 1},
   {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
-  {10, UPB_SIZE(68, 104), 10, 0, 9, 1},
+  {10, UPB_SIZE(68, 104), 10, 0, 12, 1},
   {17, UPB_SIZE(32, 32), 5, 0, 8, 1},
 };
 
@@ -2659,7 +2697,7 @@ static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1
 };
 
 static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
   {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
 };
 
@@ -2676,11 +2714,11 @@ static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3]
 };
 
 static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
   {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
   {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
   {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {5, UPB_SIZE(24, 48), 0, 0, 9, 3},
+  {5, UPB_SIZE(24, 48), 0, 0, 12, 3},
 };
 
 const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
@@ -2705,7 +2743,7 @@ static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_subms
 };
 
 static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 2, 0, 9, 1},
+  {1, UPB_SIZE(8, 8), 2, 0, 12, 1},
   {2, UPB_SIZE(4, 4), 1, 0, 5, 1},
   {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
 };
@@ -2722,7 +2760,7 @@ static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs
 };
 
 static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
   {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
   {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
 };
@@ -2738,9 +2776,9 @@ static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[
 };
 
 static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 3, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 4, 0, 9, 1},
-  {3, UPB_SIZE(20, 40), 5, 0, 9, 1},
+  {1, UPB_SIZE(4, 8), 3, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 4, 0, 12, 1},
+  {3, UPB_SIZE(20, 40), 5, 0, 12, 1},
   {4, UPB_SIZE(28, 56), 6, 0, 11, 1},
   {5, UPB_SIZE(1, 1), 1, 0, 8, 1},
   {6, UPB_SIZE(2, 2), 2, 0, 8, 1},
@@ -2757,11 +2795,11 @@ static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
 };
 
 static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(28, 32), 11, 0, 9, 1},
-  {8, UPB_SIZE(36, 48), 12, 0, 9, 1},
+  {1, UPB_SIZE(28, 32), 11, 0, 12, 1},
+  {8, UPB_SIZE(36, 48), 12, 0, 12, 1},
   {9, UPB_SIZE(8, 8), 1, 0, 14, 1},
   {10, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {11, UPB_SIZE(44, 64), 13, 0, 9, 1},
+  {11, UPB_SIZE(44, 64), 13, 0, 12, 1},
   {16, UPB_SIZE(17, 17), 3, 0, 8, 1},
   {17, UPB_SIZE(18, 18), 4, 0, 8, 1},
   {18, UPB_SIZE(19, 19), 5, 0, 8, 1},
@@ -2769,14 +2807,14 @@ static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
   {23, UPB_SIZE(21, 21), 7, 0, 8, 1},
   {27, UPB_SIZE(22, 22), 8, 0, 8, 1},
   {31, UPB_SIZE(23, 23), 9, 0, 8, 1},
-  {36, UPB_SIZE(52, 80), 14, 0, 9, 1},
-  {37, UPB_SIZE(60, 96), 15, 0, 9, 1},
-  {39, UPB_SIZE(68, 112), 16, 0, 9, 1},
-  {40, UPB_SIZE(76, 128), 17, 0, 9, 1},
-  {41, UPB_SIZE(84, 144), 18, 0, 9, 1},
+  {36, UPB_SIZE(52, 80), 14, 0, 12, 1},
+  {37, UPB_SIZE(60, 96), 15, 0, 12, 1},
+  {39, UPB_SIZE(68, 112), 16, 0, 12, 1},
+  {40, UPB_SIZE(76, 128), 17, 0, 12, 1},
+  {41, UPB_SIZE(84, 144), 18, 0, 12, 1},
   {42, UPB_SIZE(24, 24), 10, 0, 8, 1},
-  {44, UPB_SIZE(92, 160), 19, 0, 9, 1},
-  {45, UPB_SIZE(100, 176), 20, 0, 9, 1},
+  {44, UPB_SIZE(92, 160), 19, 0, 12, 1},
+  {45, UPB_SIZE(100, 176), 20, 0, 12, 1},
   {999, UPB_SIZE(108, 192), 0, 0, 11, 3},
 };
 
@@ -2906,12 +2944,12 @@ static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1]
 
 static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
   {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
-  {3, UPB_SIZE(32, 32), 4, 0, 9, 1},
+  {3, UPB_SIZE(32, 32), 4, 0, 12, 1},
   {4, UPB_SIZE(8, 8), 1, 0, 4, 1},
   {5, UPB_SIZE(16, 16), 2, 0, 3, 1},
   {6, UPB_SIZE(24, 24), 3, 0, 1, 1},
   {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
-  {8, UPB_SIZE(48, 64), 6, 0, 9, 1},
+  {8, UPB_SIZE(48, 64), 6, 0, 12, 1},
 };
 
 const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
@@ -2921,7 +2959,7 @@ const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
 };
 
 static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 2, 0, 9, 2},
+  {1, UPB_SIZE(4, 8), 2, 0, 12, 2},
   {2, UPB_SIZE(1, 1), 1, 0, 8, 2},
 };
 
@@ -2948,9 +2986,9 @@ const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
 static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
   {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
   {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
-  {3, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {4, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {6, UPB_SIZE(28, 56), 0, 0, 9, 3},
+  {3, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {4, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {6, UPB_SIZE(28, 56), 0, 0, 12, 3},
 };
 
 const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
@@ -2975,7 +3013,7 @@ const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
 
 static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
   {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
-  {2, UPB_SIZE(12, 16), 3, 0, 9, 1},
+  {2, UPB_SIZE(12, 16), 3, 0, 12, 1},
   {3, UPB_SIZE(4, 4), 1, 0, 5, 1},
   {4, UPB_SIZE(8, 8), 2, 0, 5, 1},
 };
@@ -4383,6 +4421,13 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
     field->descriptortype = upb_fielddef_descriptortype(f);
     field->label = upb_fielddef_label(f);
 
+    if (field->descriptortype == UPB_DTYPE_STRING &&
+        f->file->syntax == UPB_SYNTAX_PROTO2) {
+      /* See TableDescriptorType() in upbc/generator.cc for details and
+       * rationale. */
+      field->descriptortype = UPB_DTYPE_BYTES;
+    }
+
     if (upb_fielddef_ismap(f)) {
       field->label = _UPB_LABEL_MAP;
     } else if (upb_fielddef_packed(f)) {
@@ -4918,13 +4963,21 @@ static bool create_fielddef(
     f->oneof = NULL;
   }
 
-  if (google_protobuf_FieldDescriptorProto_has_options(field_proto)) {
-    options = google_protobuf_FieldDescriptorProto_options(field_proto);
-    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
+  options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ?
+    google_protobuf_FieldDescriptorProto_options(field_proto) : NULL;
+
+  if (options && google_protobuf_FieldOptions_has_packed(options)) {
     f->packed_ = google_protobuf_FieldOptions_packed(options);
+  } else {
+    /* Repeated fields default to packed for proto3 only. */
+    f->packed_ = upb_fielddef_isprimitive(f) &&
+        f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3;
+  }
+
+  if (options) {
+    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
   } else {
     f->lazy_ = false;
-    f->packed_ = false;
   }
 
   return true;
@@ -5188,7 +5241,7 @@ static bool build_filedef(
   const google_protobuf_FieldDescriptorProto *const *exts;
   const upb_strview* strs;
   size_t i, n;
-  decl_counts counts = {0};
+  decl_counts counts = {0, 0, 0};
 
   count_types_in_file(file_proto, &counts);
 
@@ -5612,7 +5665,11 @@ const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
   if (upb_oneof_done(&i)) return false;
   f = upb_oneof_iter_field(&i);
   field = upb_fielddef_layout(f);
-  oneof_case = _upb_getoneofcase_field(msg, field);
+  if (in_oneof(field)) {
+    oneof_case = _upb_getoneofcase_field(msg, field);
+  } else {
+    return _upb_hasbit_field(msg, field) ? f : NULL;
+  }
 
   return oneof_case ? upb_msgdef_itof(m, oneof_case) : NULL;
 }
@@ -6341,6 +6398,7 @@ static upb_strview jsondec_string(jsondec *d) {
         upb_strview ret;
         ret.data = buf;
         ret.size = end - buf;
+        *end = '\0';  /* Needed for possible strtod(). */
         return ret;
       }
       case '\\':
@@ -6665,7 +6723,7 @@ static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) {
     case JD_STRING:
       str = jsondec_string(d);
       if (jsondec_streql(str, "NaN")) {
-        val.double_val = 0.0 / 0.0;
+        val.double_val = UPB_NAN;
       } else if (jsondec_streql(str, "Infinity")) {
         val.double_val = UPB_INFINITY;
       } else if (jsondec_streql(str, "-Infinity")) {
@@ -6822,7 +6880,7 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
     return;
   }
 
-  if (upb_fielddef_containingoneof(f) &&
+  if (upb_fielddef_realcontainingoneof(f) &&
       upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
     jsondec_err(d, "More than one field for this oneof.");
   }
@@ -7655,7 +7713,7 @@ static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) {
   ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr);
 
   if (!ret) {
-    jsonenc_errf(e, "Couldn't find Any type: %.*s (full URL: " UPB_STRVIEW_FORMAT ")", (int)(end - ptr), ptr, UPB_STRVIEW_ARGS(type_url));
+    jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
   }
 
   return ret;
@@ -8071,6 +8129,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
 #undef UPB_ASSERT_DEBUGVAR
 #undef UPB_UNREACHABLE
 #undef UPB_INFINITY
+#undef UPB_NAN
 #undef UPB_MSVC_VSNPRINTF
 #undef _upb_snprintf
 #undef _upb_vsnprintf

+ 7 - 10
php/ext/google/protobuf/php-upb.h

@@ -173,6 +173,11 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
 #else
 #define UPB_INFINITY (1.0 / 0.0)
 #endif
+#ifdef NAN
+#define UPB_NAN NAN
+#else
+#define UPB_NAN (0.0 / 0.0)
+#endif
 /*
 ** upb_decode: parsing into a upb_msg using a upb_msglayout.
 */
@@ -799,15 +804,6 @@ UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
  * invalidate iterators. */
 bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
 
-/* Handy routines for treating an inttable like a stack.  May not be mixed with
- * other insert/remove calls. */
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
-upb_value upb_inttable_pop(upb_inttable *t);
-
-UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
-  return upb_inttable_push2(t, val, &upb_alloc_global);
-}
-
 /* Convenience routines for inttables with pointer keys. */
 bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
                              upb_alloc *a);
@@ -1072,7 +1068,7 @@ UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) {
 
 UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) {
   UPB_ASSERT(f->presence < 0);
-  return ~(int64_t)f->presence;
+  return ~(ptrdiff_t)f->presence;
 }
 
 UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg,
@@ -3879,6 +3875,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
 #undef UPB_ASSERT_DEBUGVAR
 #undef UPB_UNREACHABLE
 #undef UPB_INFINITY
+#undef UPB_NAN
 #undef UPB_MSVC_VSNPRINTF
 #undef _upb_snprintf
 #undef _upb_vsnprintf

+ 7 - 0
php/ext/google/protobuf/protobuf.c

@@ -273,11 +273,18 @@ const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) {
       zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
 
   if (!ret && ce->create_object) {
+#if PHP_VERSION_ID < 80000
     zval tmp;
     zval zv;
     ZVAL_OBJ(&tmp, ce->create_object(ce));
     zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
     zval_ptr_dtor(&tmp);
+#else
+    zval zv;
+    zend_object *tmp = ce->create_object(ce);
+    zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv);
+    OBJ_RELEASE(tmp);
+#endif
     zval_ptr_dtor(&zv);
     ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
   }

+ 28 - 0
php/ext/google/protobuf/protobuf.h

@@ -43,6 +43,34 @@ const zval *get_generated_pool();
 #define GC_DELREF(h) --GC_REFCOUNT(h)
 #endif
 
+// Since php 7.4, the write_property() object handler now returns the assigned
+// value (after possible type coercions) rather than void.
+// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173
+#if PHP_VERSION_ID < 70400
+#define PROTO_RETURN_VAL void
+#else
+#define PROTO_RETURN_VAL zval*
+#endif
+
+// Sine php 8.0, the Object Handlers API was changed to receive zend_object*
+// instead of zval* and zend_string* instead of zval* for property names.
+// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39
+#if PHP_VERSION_ID < 80000
+#define PROTO_VAL zval 
+#define PROTO_STR zval
+#define PROTO_MSG_P(obj) (Message*)Z_OBJ_P(obj)
+#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj)
+#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj)
+#else
+#define PROTO_VAL zend_object
+#define PROTO_STR zend_string
+#define PROTO_MSG_P(obj) (Message*)(obj)
+#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj)
+#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj)
+#endif
+
+#define PHP_PROTOBUF_VERSION "3.13.0"
+
 // ptr -> PHP object cache. This is a weak map that caches lazily-created
 // wrapper objects around upb types:
 //  * upb_msg* -> Message

+ 10 - 10
php/phpunit.xml

@@ -3,16 +3,16 @@
          colors="true">
   <testsuites>
     <testsuite name="protobuf-tests">
-      <file>tests/php_implementation_test.php</file>
-      <file>tests/array_test.php</file>
-      <file>tests/encode_decode_test.php</file>
-      <file>tests/generated_class_test.php</file>
-      <file>tests/generated_phpdoc_test.php</file>
-      <file>tests/map_field_test.php</file>
-      <file>tests/well_known_test.php</file>
-      <file>tests/descriptors_test.php</file>
-      <file>tests/generated_service_test.php</file>
-      <file>tests/wrapper_type_setters_test.php</file>
+      <file>tests/PhpImplementationTest.php</file>
+      <file>tests/ArrayTest.php</file>
+      <file>tests/EncodeDecodeTest.php</file>
+      <file>tests/GeneratedClassTest.php</file>
+      <file>tests/GeneratedPhpdocTest.php</file>
+      <file>tests/MapFieldTest.php</file>
+      <file>tests/WellKnownTest.php</file>
+      <file>tests/DescriptorsTest.php</file>
+      <file>tests/GeneratedServiceTest.php</file>
+      <file>tests/WrapperTypeSettersTest.php</file>
     </testsuite>
   </testsuites>
 </phpunit>

+ 2 - 23
php/src/GPBMetadata/Google/Protobuf/Struct.php

@@ -15,29 +15,8 @@ class Struct
           return;
         }
         $pool->internalAddGeneratedFile(hex2bin(
-            "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e7072" .
-            "6f746f120f676f6f676c652e70726f746f6275662284010a065374727563" .
-            "7412330a066669656c647318012003280b32232e676f6f676c652e70726f" .
-            "746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669" .
-            "656c6473456e747279120b0a036b657918012001280912250a0576616c75" .
-            "6518022001280b32162e676f6f676c652e70726f746f6275662e56616c75" .
-            "653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518" .
-            "012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c5661" .
-            "6c7565480012160a0c6e756d6265725f76616c7565180220012801480012" .
-            "160a0c737472696e675f76616c7565180320012809480012140a0a626f6f" .
-            "6c5f76616c75651804200128084800122f0a0c7374727563745f76616c75" .
-            "6518052001280b32172e676f6f676c652e70726f746f6275662e53747275" .
-            "6374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f" .
-            "676c652e70726f746f6275662e4c69737456616c7565480042060a046b69" .
-            "6e6422330a094c69737456616c756512260a0676616c7565731801200328" .
-            "0b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e" .
-            "756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a1363" .
-            "6f6d2e676f6f676c652e70726f746f627566420b53747275637450726f74" .
-            "6f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275" .
-            "662f7074797065732f7374727563743b7374727563747062f80101a20203" .
-            "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77" .
-            "6e5479706573620670726f746f33"
-        ));
+            "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e70726f746f120f676f6f676c652e70726f746f6275662284010a0653747275637412330a066669656c647318012003280b32232e676f6f676c652e70726f746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669656c6473456e747279120b0a036b657918012001280912250a0576616c756518022001280b32162e676f6f676c652e70726f746f6275662e56616c75653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c56616c7565480012160a0c6e756d6265725f76616c7565180220012801480012160a0c737472696e675f76616c7565180320012809480012140a0a626f6f6c5f76616c75651804200128084800122f0a0c7374727563745f76616c756518052001280b32172e676f6f676c652e70726f746f6275662e537472756374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f676c652e70726f746f6275662e4c69737456616c7565480042060a046b696e6422330a094c69737456616c756512260a0676616c75657318012003280b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a13636f6d2e676f6f676c652e70726f746f627566420b53747275637450726f746f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065732f7374727563743b7374727563747062f80101a20203475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
+        ), true);
 
         static::$is_initialized = true;
     }

+ 8 - 0
php/src/Google/Protobuf/Descriptor.php

@@ -97,4 +97,12 @@ class Descriptor
     {
         return count($this->internal_desc->getOneofDecl());
     }
+
+    /**
+     * @return int Number of real oneofs in message
+     */
+    public function getRealOneofDeclCount()
+    {
+        return $this->internal_desc->getRealOneofDeclCount();
+    }
 }

+ 8 - 0
php/src/Google/Protobuf/FieldDescriptor.php

@@ -114,4 +114,12 @@ class FieldDescriptor
     {
         return $this->internal_desc->isMap();
     }
+
+    /**
+     * @return boolean
+     */
+    public function hasOptionalKeyword()
+    {
+        return $this->internal_desc->hasOptionalKeyword();
+    }
 }

+ 23 - 73
php/src/Google/Protobuf/Internal/DescriptorProto.php

@@ -20,48 +20,39 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
      */
     private $field;
-    private $has_field = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
      */
     private $extension;
-    private $has_extension = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
      */
     private $nested_type;
-    private $has_nested_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
      */
     private $enum_type;
-    private $has_enum_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
      */
     private $extension_range;
-    private $has_extension_range = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
      */
     private $oneof_decl;
-    private $has_oneof_decl = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
      */
     private $reserved_range;
-    private $has_reserved_range = false;
     /**
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
@@ -69,7 +60,6 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated string reserved_name = 10;</code>
      */
     private $reserved_name;
-    private $has_reserved_name = false;
 
     /**
      * Constructor.
@@ -102,7 +92,17 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -114,16 +114,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -142,16 +136,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->field = $arr;
-        $this->has_field = true;
 
         return $this;
     }
 
-    public function hasField()
-    {
-        return $this->has_field;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -170,16 +158,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
-        $this->has_extension = true;
 
         return $this;
     }
 
-    public function hasExtension()
-    {
-        return $this->has_extension;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -198,16 +180,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->nested_type = $arr;
-        $this->has_nested_type = true;
 
         return $this;
     }
 
-    public function hasNestedType()
-    {
-        return $this->has_nested_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -226,16 +202,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
-        $this->has_enum_type = true;
 
         return $this;
     }
 
-    public function hasEnumType()
-    {
-        return $this->has_enum_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -254,16 +224,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class);
         $this->extension_range = $arr;
-        $this->has_extension_range = true;
 
         return $this;
     }
 
-    public function hasExtensionRange()
-    {
-        return $this->has_extension_range;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -282,23 +246,27 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class);
         $this->oneof_decl = $arr;
-        $this->has_oneof_decl = true;
 
         return $this;
     }
 
-    public function hasOneofDecl()
-    {
-        return $this->has_oneof_decl;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
      * @return \Google\Protobuf\Internal\MessageOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -310,16 +278,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -338,16 +300,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class);
         $this->reserved_range = $arr;
-        $this->has_reserved_range = true;
 
         return $this;
     }
 
-    public function hasReservedRange()
-    {
-        return $this->has_reserved_range;
-    }
-
     /**
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
@@ -372,15 +328,9 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->reserved_name = $arr;
-        $this->has_reserved_name = true;
 
         return $this;
     }
 
-    public function hasReservedName()
-    {
-        return $this->has_reserved_name;
-    }
-
 }
 

+ 35 - 26
php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php

@@ -20,20 +20,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Exclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -61,7 +58,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -75,16 +82,10 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Exclusive.
      *
@@ -93,7 +94,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -107,23 +118,27 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
      * @return \Google\Protobuf\Internal\ExtensionRangeOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -135,16 +150,10 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 24 - 18
php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php

@@ -24,15 +24,13 @@ class ReservedRange extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Exclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -59,7 +57,17 @@ class ReservedRange extends \Google\Protobuf\Internal\Message
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -73,16 +81,10 @@ class ReservedRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Exclusive.
      *
@@ -91,7 +93,17 @@ class ReservedRange extends \Google\Protobuf\Internal\Message
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -105,16 +117,10 @@ class ReservedRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 23 - 38
php/src/Google/Protobuf/Internal/EnumDescriptorProto.php

@@ -20,18 +20,15 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
      */
     private $value;
-    private $has_value = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Range of reserved numeric values. Reserved numeric values may not be used
      * by enum values in the same enum declaration. Reserved ranges may not
@@ -40,7 +37,6 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;</code>
      */
     private $reserved_range;
-    private $has_reserved_range = false;
     /**
      * Reserved enum value names, which may not be reused. A given name may only
      * be reserved once.
@@ -48,7 +44,6 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated string reserved_name = 5;</code>
      */
     private $reserved_name;
-    private $has_reserved_name = false;
 
     /**
      * Constructor.
@@ -79,7 +74,17 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -91,16 +96,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -119,23 +118,27 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class);
         $this->value = $arr;
-        $this->has_value = true;
 
         return $this;
     }
 
-    public function hasValue()
-    {
-        return $this->has_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
      * @return \Google\Protobuf\Internal\EnumOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -147,16 +150,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Range of reserved numeric values. Reserved numeric values may not be used
      * by enum values in the same enum declaration. Reserved ranges may not
@@ -183,16 +180,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class);
         $this->reserved_range = $arr;
-        $this->has_reserved_range = true;
 
         return $this;
     }
 
-    public function hasReservedRange()
-    {
-        return $this->has_reserved_range;
-    }
-
     /**
      * Reserved enum value names, which may not be reused. A given name may only
      * be reserved once.
@@ -217,15 +208,9 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->reserved_name = $arr;
-        $this->has_reserved_name = true;
 
         return $this;
     }
 
-    public function hasReservedName()
-    {
-        return $this->has_reserved_name;
-    }
-
 }
 

+ 24 - 18
php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php

@@ -26,15 +26,13 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Inclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -61,7 +59,17 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -75,16 +83,10 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Inclusive.
      *
@@ -93,7 +95,17 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -107,16 +119,10 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 24 - 25
php/src/Google/Protobuf/Internal/EnumOptions.php

@@ -21,8 +21,7 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool allow_alias = 2;</code>
      */
-    protected $allow_alias = false;
-    private $has_allow_alias = false;
+    protected $allow_alias = null;
     /**
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -31,15 +30,13 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -73,7 +70,17 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
      */
     public function getAllowAlias()
     {
-        return $this->allow_alias;
+        return isset($this->allow_alias) ? $this->allow_alias : false;
+    }
+
+    public function hasAllowAlias()
+    {
+        return isset($this->allow_alias);
+    }
+
+    public function clearAllowAlias()
+    {
+        unset($this->allow_alias);
     }
 
     /**
@@ -88,16 +95,10 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->allow_alias = $var;
-        $this->has_allow_alias = true;
 
         return $this;
     }
 
-    public function hasAllowAlias()
-    {
-        return $this->has_allow_alias;
-    }
-
     /**
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -109,7 +110,17 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -126,16 +137,10 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -158,15 +163,9 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 35 - 26
php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php

@@ -20,18 +20,15 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional int32 number = 2;</code>
      */
-    protected $number = 0;
-    private $has_number = false;
+    protected $number = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -55,7 +52,17 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -67,23 +74,27 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional int32 number = 2;</code>
      * @return int
      */
     public function getNumber()
     {
-        return $this->number;
+        return isset($this->number) ? $this->number : 0;
+    }
+
+    public function hasNumber()
+    {
+        return isset($this->number);
+    }
+
+    public function clearNumber()
+    {
+        unset($this->number);
     }
 
     /**
@@ -95,23 +106,27 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
-        $this->has_number = true;
 
         return $this;
     }
 
-    public function hasNumber()
-    {
-        return $this->has_number;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
      * @return \Google\Protobuf\Internal\EnumValueOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -123,15 +138,9 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 

+ 12 - 16
php/src/Google/Protobuf/Internal/EnumValueOptions.php

@@ -23,15 +23,13 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 1 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -64,7 +62,17 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -81,16 +89,10 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -113,15 +115,9 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 0 - 7
php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php

@@ -21,7 +21,6 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -60,15 +59,9 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 11 - 1
php/src/Google/Protobuf/Internal/FieldDescriptor.php

@@ -229,7 +229,17 @@ class FieldDescriptor
         }
 
         $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1;
-        $packed = false;
+        // TODO: once proto2 is supported, this default should be false
+        // for proto2.
+        if ($proto->getLabel() === GPBLabel::REPEATED &&
+            $proto->getType() !== GPBType::MESSAGE &&
+            $proto->getType() !== GPBType::GROUP &&
+            $proto->getType() !== GPBType::STRING &&
+            $proto->getType() !== GPBType::BYTES) {
+          $packed = true;
+        } else {
+          $packed = false;
+        }
         $options = $proto->getOptions();
         if ($options !== null) {
             $packed = $options->getPacked();

+ 133 - 100
php/src/Google/Protobuf/Internal/FieldDescriptorProto.php

@@ -20,26 +20,22 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional int32 number = 3;</code>
      */
-    protected $number = 0;
-    private $has_number = false;
+    protected $number = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
      */
-    protected $label = 0;
-    private $has_label = false;
+    protected $label = null;
     /**
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
      */
-    protected $type = 0;
-    private $has_type = false;
+    protected $type = null;
     /**
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
@@ -49,16 +45,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string type_name = 6;</code>
      */
-    protected $type_name = '';
-    private $has_type_name = false;
+    protected $type_name = null;
     /**
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
      *
      * Generated from protobuf field <code>optional string extendee = 2;</code>
      */
-    protected $extendee = '';
-    private $has_extendee = false;
+    protected $extendee = null;
     /**
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
@@ -68,16 +62,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string default_value = 7;</code>
      */
-    protected $default_value = '';
-    private $has_default_value = false;
+    protected $default_value = null;
     /**
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
      *
      * Generated from protobuf field <code>optional int32 oneof_index = 9;</code>
      */
-    protected $oneof_index = 0;
-    private $has_oneof_index = false;
+    protected $oneof_index = null;
     /**
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
@@ -86,13 +78,11 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string json_name = 10;</code>
      */
-    protected $json_name = '';
-    private $has_json_name = false;
+    protected $json_name = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
@@ -115,8 +105,7 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool proto3_optional = 17;</code>
      */
-    protected $proto3_optional = false;
-    private $has_proto3_optional = false;
+    protected $proto3_optional = null;
 
     /**
      * Constructor.
@@ -186,7 +175,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -198,23 +197,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional int32 number = 3;</code>
      * @return int
      */
     public function getNumber()
     {
-        return $this->number;
+        return isset($this->number) ? $this->number : 0;
+    }
+
+    public function hasNumber()
+    {
+        return isset($this->number);
+    }
+
+    public function clearNumber()
+    {
+        unset($this->number);
     }
 
     /**
@@ -226,23 +229,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
-        $this->has_number = true;
 
         return $this;
     }
 
-    public function hasNumber()
-    {
-        return $this->has_number;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
      * @return int
      */
     public function getLabel()
     {
-        return $this->label;
+        return isset($this->label) ? $this->label : 0;
+    }
+
+    public function hasLabel()
+    {
+        return isset($this->label);
+    }
+
+    public function clearLabel()
+    {
+        unset($this->label);
     }
 
     /**
@@ -252,18 +259,12 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function setLabel($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Label::class);
         $this->label = $var;
-        $this->has_label = true;
 
         return $this;
     }
 
-    public function hasLabel()
-    {
-        return $this->has_label;
-    }
-
     /**
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
@@ -273,7 +274,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getType()
     {
-        return $this->type;
+        return isset($this->type) ? $this->type : 0;
+    }
+
+    public function hasType()
+    {
+        return isset($this->type);
+    }
+
+    public function clearType()
+    {
+        unset($this->type);
     }
 
     /**
@@ -286,18 +297,12 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function setType($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Type::class);
         $this->type = $var;
-        $this->has_type = true;
 
         return $this;
     }
 
-    public function hasType()
-    {
-        return $this->has_type;
-    }
-
     /**
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
@@ -310,7 +315,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getTypeName()
     {
-        return $this->type_name;
+        return isset($this->type_name) ? $this->type_name : '';
+    }
+
+    public function hasTypeName()
+    {
+        return isset($this->type_name);
+    }
+
+    public function clearTypeName()
+    {
+        unset($this->type_name);
     }
 
     /**
@@ -328,16 +343,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->type_name = $var;
-        $this->has_type_name = true;
 
         return $this;
     }
 
-    public function hasTypeName()
-    {
-        return $this->has_type_name;
-    }
-
     /**
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
@@ -347,7 +356,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getExtendee()
     {
-        return $this->extendee;
+        return isset($this->extendee) ? $this->extendee : '';
+    }
+
+    public function hasExtendee()
+    {
+        return isset($this->extendee);
+    }
+
+    public function clearExtendee()
+    {
+        unset($this->extendee);
     }
 
     /**
@@ -362,16 +381,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->extendee = $var;
-        $this->has_extendee = true;
 
         return $this;
     }
 
-    public function hasExtendee()
-    {
-        return $this->has_extendee;
-    }
-
     /**
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
@@ -384,7 +397,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getDefaultValue()
     {
-        return $this->default_value;
+        return isset($this->default_value) ? $this->default_value : '';
+    }
+
+    public function hasDefaultValue()
+    {
+        return isset($this->default_value);
+    }
+
+    public function clearDefaultValue()
+    {
+        unset($this->default_value);
     }
 
     /**
@@ -402,16 +425,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->default_value = $var;
-        $this->has_default_value = true;
 
         return $this;
     }
 
-    public function hasDefaultValue()
-    {
-        return $this->has_default_value;
-    }
-
     /**
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
@@ -421,7 +438,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getOneofIndex()
     {
-        return $this->oneof_index;
+        return isset($this->oneof_index) ? $this->oneof_index : 0;
+    }
+
+    public function hasOneofIndex()
+    {
+        return isset($this->oneof_index);
+    }
+
+    public function clearOneofIndex()
+    {
+        unset($this->oneof_index);
     }
 
     /**
@@ -436,16 +463,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->oneof_index = $var;
-        $this->has_oneof_index = true;
 
         return $this;
     }
 
-    public function hasOneofIndex()
-    {
-        return $this->has_oneof_index;
-    }
-
     /**
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
@@ -457,7 +478,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getJsonName()
     {
-        return $this->json_name;
+        return isset($this->json_name) ? $this->json_name : '';
+    }
+
+    public function hasJsonName()
+    {
+        return isset($this->json_name);
+    }
+
+    public function clearJsonName()
+    {
+        unset($this->json_name);
     }
 
     /**
@@ -474,23 +505,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->json_name = $var;
-        $this->has_json_name = true;
 
         return $this;
     }
 
-    public function hasJsonName()
-    {
-        return $this->has_json_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
      * @return \Google\Protobuf\Internal\FieldOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -502,16 +537,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
@@ -537,7 +566,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getProto3Optional()
     {
-        return $this->proto3_optional;
+        return isset($this->proto3_optional) ? $this->proto3_optional : false;
+    }
+
+    public function hasProto3Optional()
+    {
+        return isset($this->proto3_optional);
+    }
+
+    public function clearProto3Optional()
+    {
+        unset($this->proto3_optional);
     }
 
     /**
@@ -568,15 +607,9 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->proto3_optional = $var;
-        $this->has_proto3_optional = true;
 
         return $this;
     }
 
-    public function hasProto3Optional()
-    {
-        return $this->has_proto3_optional;
-    }
-
 }
 

+ 74 - 63
php/src/Google/Protobuf/Internal/FieldOptions.php

@@ -23,8 +23,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
      */
-    protected $ctype = 0;
-    private $has_ctype = false;
+    protected $ctype = null;
     /**
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
@@ -34,8 +33,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool packed = 2;</code>
      */
-    protected $packed = false;
-    private $has_packed = false;
+    protected $packed = null;
     /**
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
@@ -50,8 +48,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
      */
-    protected $jstype = 0;
-    private $has_jstype = false;
+    protected $jstype = null;
     /**
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
@@ -80,8 +77,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      */
-    protected $lazy = false;
-    private $has_lazy = false;
+    protected $lazy = null;
     /**
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -90,22 +86,19 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * For Google-internal migration only. Do not use.
      *
      * Generated from protobuf field <code>optional bool weak = 10 [default = false];</code>
      */
-    protected $weak = false;
-    private $has_weak = false;
+    protected $weak = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -187,7 +180,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getCtype()
     {
-        return $this->ctype;
+        return isset($this->ctype) ? $this->ctype : 0;
+    }
+
+    public function hasCtype()
+    {
+        return isset($this->ctype);
+    }
+
+    public function clearCtype()
+    {
+        unset($this->ctype);
     }
 
     /**
@@ -202,18 +205,12 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function setCtype($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_CType::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\CType::class);
         $this->ctype = $var;
-        $this->has_ctype = true;
 
         return $this;
     }
 
-    public function hasCtype()
-    {
-        return $this->has_ctype;
-    }
-
     /**
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
@@ -226,7 +223,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getPacked()
     {
-        return $this->packed;
+        return isset($this->packed) ? $this->packed : false;
+    }
+
+    public function hasPacked()
+    {
+        return isset($this->packed);
+    }
+
+    public function clearPacked()
+    {
+        unset($this->packed);
     }
 
     /**
@@ -244,16 +251,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->packed = $var;
-        $this->has_packed = true;
 
         return $this;
     }
 
-    public function hasPacked()
-    {
-        return $this->has_packed;
-    }
-
     /**
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
@@ -271,7 +272,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJstype()
     {
-        return $this->jstype;
+        return isset($this->jstype) ? $this->jstype : 0;
+    }
+
+    public function hasJstype()
+    {
+        return isset($this->jstype);
+    }
+
+    public function clearJstype()
+    {
+        unset($this->jstype);
     }
 
     /**
@@ -292,18 +303,12 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function setJstype($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_JSType::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\JSType::class);
         $this->jstype = $var;
-        $this->has_jstype = true;
 
         return $this;
     }
 
-    public function hasJstype()
-    {
-        return $this->has_jstype;
-    }
-
     /**
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
@@ -335,7 +340,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getLazy()
     {
-        return $this->lazy;
+        return isset($this->lazy) ? $this->lazy : false;
+    }
+
+    public function hasLazy()
+    {
+        return isset($this->lazy);
+    }
+
+    public function clearLazy()
+    {
+        unset($this->lazy);
     }
 
     /**
@@ -372,16 +387,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->lazy = $var;
-        $this->has_lazy = true;
 
         return $this;
     }
 
-    public function hasLazy()
-    {
-        return $this->has_lazy;
-    }
-
     /**
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -393,7 +402,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -410,16 +429,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * For Google-internal migration only. Do not use.
      *
@@ -428,7 +441,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
      */
     public function getWeak()
     {
-        return $this->weak;
+        return isset($this->weak) ? $this->weak : false;
+    }
+
+    public function hasWeak()
+    {
+        return isset($this->weak);
+    }
+
+    public function clearWeak()
+    {
+        unset($this->weak);
     }
 
     /**
@@ -442,16 +465,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->weak = $var;
-        $this->has_weak = true;
 
         return $this;
     }
 
-    public function hasWeak()
-    {
-        return $this->has_weak;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -474,15 +491,9 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 58 - 92
php/src/Google/Protobuf/Internal/FileDescriptorProto.php

@@ -22,29 +22,25 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * e.g. "foo", "foo.bar", etc.
      *
      * Generated from protobuf field <code>optional string package = 2;</code>
      */
-    protected $package = '';
-    private $has_package = false;
+    protected $package = null;
     /**
      * Names of files imported by this file.
      *
      * Generated from protobuf field <code>repeated string dependency = 3;</code>
      */
     private $dependency;
-    private $has_dependency = false;
     /**
      * Indexes of the public imported files in the dependency list above.
      *
      * Generated from protobuf field <code>repeated int32 public_dependency = 10;</code>
      */
     private $public_dependency;
-    private $has_public_dependency = false;
     /**
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
@@ -52,34 +48,28 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated int32 weak_dependency = 11;</code>
      */
     private $weak_dependency;
-    private $has_weak_dependency = false;
     /**
      * All top-level definitions in this file.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
      */
     private $message_type;
-    private $has_message_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
      */
     private $enum_type;
-    private $has_enum_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
      */
     private $service;
-    private $has_service = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
      */
     private $extension;
-    private $has_extension = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
@@ -89,15 +79,13 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
      */
     protected $source_code_info = null;
-    private $has_source_code_info = false;
     /**
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
      *
      * Generated from protobuf field <code>optional string syntax = 12;</code>
      */
-    protected $syntax = '';
-    private $has_syntax = false;
+    protected $syntax = null;
 
     /**
      * Constructor.
@@ -145,7 +133,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -159,16 +157,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * e.g. "foo", "foo.bar", etc.
      *
@@ -177,7 +169,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getPackage()
     {
-        return $this->package;
+        return isset($this->package) ? $this->package : '';
+    }
+
+    public function hasPackage()
+    {
+        return isset($this->package);
+    }
+
+    public function clearPackage()
+    {
+        unset($this->package);
     }
 
     /**
@@ -191,16 +193,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->package = $var;
-        $this->has_package = true;
 
         return $this;
     }
 
-    public function hasPackage()
-    {
-        return $this->has_package;
-    }
-
     /**
      * Names of files imported by this file.
      *
@@ -223,16 +219,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->dependency = $arr;
-        $this->has_dependency = true;
 
         return $this;
     }
 
-    public function hasDependency()
-    {
-        return $this->has_dependency;
-    }
-
     /**
      * Indexes of the public imported files in the dependency list above.
      *
@@ -255,16 +245,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->public_dependency = $arr;
-        $this->has_public_dependency = true;
 
         return $this;
     }
 
-    public function hasPublicDependency()
-    {
-        return $this->has_public_dependency;
-    }
-
     /**
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
@@ -289,16 +273,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->weak_dependency = $arr;
-        $this->has_weak_dependency = true;
 
         return $this;
     }
 
-    public function hasWeakDependency()
-    {
-        return $this->has_weak_dependency;
-    }
-
     /**
      * All top-level definitions in this file.
      *
@@ -321,16 +299,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->message_type = $arr;
-        $this->has_message_type = true;
 
         return $this;
     }
 
-    public function hasMessageType()
-    {
-        return $this->has_message_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -349,16 +321,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
-        $this->has_enum_type = true;
 
         return $this;
     }
 
-    public function hasEnumType()
-    {
-        return $this->has_enum_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -377,16 +343,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class);
         $this->service = $arr;
-        $this->has_service = true;
 
         return $this;
     }
 
-    public function hasService()
-    {
-        return $this->has_service;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -405,23 +365,27 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
-        $this->has_extension = true;
 
         return $this;
     }
 
-    public function hasExtension()
-    {
-        return $this->has_extension;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
      * @return \Google\Protobuf\Internal\FileOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -433,16 +397,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
@@ -454,7 +412,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getSourceCodeInfo()
     {
-        return $this->source_code_info;
+        return isset($this->source_code_info) ? $this->source_code_info : null;
+    }
+
+    public function hasSourceCodeInfo()
+    {
+        return isset($this->source_code_info);
+    }
+
+    public function clearSourceCodeInfo()
+    {
+        unset($this->source_code_info);
     }
 
     /**
@@ -471,16 +439,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class);
         $this->source_code_info = $var;
-        $this->has_source_code_info = true;
 
         return $this;
     }
 
-    public function hasSourceCodeInfo()
-    {
-        return $this->has_source_code_info;
-    }
-
     /**
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
@@ -490,7 +452,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getSyntax()
     {
-        return $this->syntax;
+        return isset($this->syntax) ? $this->syntax : '';
+    }
+
+    public function hasSyntax()
+    {
+        return isset($this->syntax);
+    }
+
+    public function clearSyntax()
+    {
+        unset($this->syntax);
     }
 
     /**
@@ -505,15 +477,9 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->syntax = $var;
-        $this->has_syntax = true;
 
         return $this;
     }
 
-    public function hasSyntax()
-    {
-        return $this->has_syntax;
-    }
-
 }
 

+ 0 - 7
php/src/Google/Protobuf/Internal/FileDescriptorSet.php

@@ -22,7 +22,6 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
      */
     private $file;
-    private $has_file = false;
 
     /**
      * Constructor.
@@ -56,15 +55,9 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class);
         $this->file = $arr;
-        $this->has_file = true;
 
         return $this;
     }
 
-    public function hasFile()
-    {
-        return $this->has_file;
-    }
-
 }
 

+ 241 - 188
php/src/Google/Protobuf/Internal/FileOptions.php

@@ -23,8 +23,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string java_package = 1;</code>
      */
-    protected $java_package = '';
-    private $has_java_package = false;
+    protected $java_package = null;
     /**
      * If set, all the classes from the .proto file are wrapped in a single
      * outer class with the given name.  This applies to both Proto1
@@ -34,8 +33,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      */
-    protected $java_outer_classname = '';
-    private $has_java_outer_classname = false;
+    protected $java_outer_classname = null;
     /**
      * If set true, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
@@ -46,15 +44,13 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool java_multiple_files = 10 [default = false];</code>
      */
-    protected $java_multiple_files = false;
-    private $has_java_multiple_files = false;
+    protected $java_multiple_files = null;
     /**
      * This option does nothing.
      *
      * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
      */
-    protected $java_generate_equals_and_hash = false;
-    private $has_java_generate_equals_and_hash = false;
+    protected $java_generate_equals_and_hash = null;
     /**
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
@@ -65,13 +61,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
      */
-    protected $java_string_check_utf8 = false;
-    private $has_java_string_check_utf8 = false;
+    protected $java_string_check_utf8 = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
      */
-    protected $optimize_for = 0;
-    private $has_optimize_for = false;
+    protected $optimize_for = null;
     /**
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
@@ -81,8 +75,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string go_package = 11;</code>
      */
-    protected $go_package = '';
-    private $has_go_package = false;
+    protected $go_package = null;
     /**
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
@@ -96,23 +89,19 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool cc_generic_services = 16 [default = false];</code>
      */
-    protected $cc_generic_services = false;
-    private $has_cc_generic_services = false;
+    protected $cc_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
      */
-    protected $java_generic_services = false;
-    private $has_java_generic_services = false;
+    protected $java_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
      */
-    protected $py_generic_services = false;
-    private $has_py_generic_services = false;
+    protected $py_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool php_generic_services = 42 [default = false];</code>
      */
-    protected $php_generic_services = false;
-    private $has_php_generic_services = false;
+    protected $php_generic_services = null;
     /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -121,31 +110,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 23 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
      *
      * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = true];</code>
      */
-    protected $cc_enable_arenas = false;
-    private $has_cc_enable_arenas = false;
+    protected $cc_enable_arenas = null;
     /**
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
      *
      * Generated from protobuf field <code>optional string objc_class_prefix = 36;</code>
      */
-    protected $objc_class_prefix = '';
-    private $has_objc_class_prefix = false;
+    protected $objc_class_prefix = null;
     /**
      * Namespace for generated classes; defaults to the package.
      *
      * Generated from protobuf field <code>optional string csharp_namespace = 37;</code>
      */
-    protected $csharp_namespace = '';
-    private $has_csharp_namespace = false;
+    protected $csharp_namespace = null;
     /**
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
@@ -154,16 +139,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string swift_prefix = 39;</code>
      */
-    protected $swift_prefix = '';
-    private $has_swift_prefix = false;
+    protected $swift_prefix = null;
     /**
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
      *
      * Generated from protobuf field <code>optional string php_class_prefix = 40;</code>
      */
-    protected $php_class_prefix = '';
-    private $has_php_class_prefix = false;
+    protected $php_class_prefix = null;
     /**
      * Use this option to change the namespace of php generated classes. Default
      * is empty. When this option is empty, the package name will be used for
@@ -171,8 +154,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string php_namespace = 41;</code>
      */
-    protected $php_namespace = '';
-    private $has_php_namespace = false;
+    protected $php_namespace = null;
     /**
      * Use this option to change the namespace of php generated metadata classes.
      * Default is empty. When this option is empty, the proto file name will be
@@ -180,8 +162,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string php_metadata_namespace = 44;</code>
      */
-    protected $php_metadata_namespace = '';
-    private $has_php_metadata_namespace = false;
+    protected $php_metadata_namespace = null;
     /**
      * Use this option to change the package of ruby generated classes. Default
      * is empty. When this option is not set, the package name will be used for
@@ -189,8 +170,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string ruby_package = 45;</code>
      */
-    protected $ruby_package = '';
-    private $has_ruby_package = false;
+    protected $ruby_package = null;
     /**
      * The parser stores options it doesn't recognize here.
      * See the documentation for the "Options" section above.
@@ -198,7 +178,6 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -307,7 +286,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJavaPackage()
     {
-        return $this->java_package;
+        return isset($this->java_package) ? $this->java_package : '';
+    }
+
+    public function hasJavaPackage()
+    {
+        return isset($this->java_package);
+    }
+
+    public function clearJavaPackage()
+    {
+        unset($this->java_package);
     }
 
     /**
@@ -324,16 +313,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->java_package = $var;
-        $this->has_java_package = true;
 
         return $this;
     }
 
-    public function hasJavaPackage()
-    {
-        return $this->has_java_package;
-    }
-
     /**
      * If set, all the classes from the .proto file are wrapped in a single
      * outer class with the given name.  This applies to both Proto1
@@ -346,7 +329,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJavaOuterClassname()
     {
-        return $this->java_outer_classname;
+        return isset($this->java_outer_classname) ? $this->java_outer_classname : '';
+    }
+
+    public function hasJavaOuterClassname()
+    {
+        return isset($this->java_outer_classname);
+    }
+
+    public function clearJavaOuterClassname()
+    {
+        unset($this->java_outer_classname);
     }
 
     /**
@@ -364,16 +357,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->java_outer_classname = $var;
-        $this->has_java_outer_classname = true;
 
         return $this;
     }
 
-    public function hasJavaOuterClassname()
-    {
-        return $this->has_java_outer_classname;
-    }
-
     /**
      * If set true, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
@@ -387,7 +374,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJavaMultipleFiles()
     {
-        return $this->java_multiple_files;
+        return isset($this->java_multiple_files) ? $this->java_multiple_files : false;
+    }
+
+    public function hasJavaMultipleFiles()
+    {
+        return isset($this->java_multiple_files);
+    }
+
+    public function clearJavaMultipleFiles()
+    {
+        unset($this->java_multiple_files);
     }
 
     /**
@@ -406,16 +403,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->java_multiple_files = $var;
-        $this->has_java_multiple_files = true;
 
         return $this;
     }
 
-    public function hasJavaMultipleFiles()
-    {
-        return $this->has_java_multiple_files;
-    }
-
     /**
      * This option does nothing.
      *
@@ -424,7 +415,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJavaGenerateEqualsAndHash()
     {
-        return $this->java_generate_equals_and_hash;
+        return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false;
+    }
+
+    public function hasJavaGenerateEqualsAndHash()
+    {
+        return isset($this->java_generate_equals_and_hash);
+    }
+
+    public function clearJavaGenerateEqualsAndHash()
+    {
+        unset($this->java_generate_equals_and_hash);
     }
 
     /**
@@ -438,16 +439,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->java_generate_equals_and_hash = $var;
-        $this->has_java_generate_equals_and_hash = true;
 
         return $this;
     }
 
-    public function hasJavaGenerateEqualsAndHash()
-    {
-        return $this->has_java_generate_equals_and_hash;
-    }
-
     /**
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
@@ -461,7 +456,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getJavaStringCheckUtf8()
     {
-        return $this->java_string_check_utf8;
+        return isset($this->java_string_check_utf8) ? $this->java_string_check_utf8 : false;
+    }
+
+    public function hasJavaStringCheckUtf8()
+    {
+        return isset($this->java_string_check_utf8);
+    }
+
+    public function clearJavaStringCheckUtf8()
+    {
+        unset($this->java_string_check_utf8);
     }
 
     /**
@@ -480,23 +485,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->java_string_check_utf8 = $var;
-        $this->has_java_string_check_utf8 = true;
 
         return $this;
     }
 
-    public function hasJavaStringCheckUtf8()
-    {
-        return $this->has_java_string_check_utf8;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
      * @return int
      */
     public function getOptimizeFor()
     {
-        return $this->optimize_for;
+        return isset($this->optimize_for) ? $this->optimize_for : 0;
+    }
+
+    public function hasOptimizeFor()
+    {
+        return isset($this->optimize_for);
+    }
+
+    public function clearOptimizeFor()
+    {
+        unset($this->optimize_for);
     }
 
     /**
@@ -506,18 +515,12 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function setOptimizeFor($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions\OptimizeMode::class);
         $this->optimize_for = $var;
-        $this->has_optimize_for = true;
 
         return $this;
     }
 
-    public function hasOptimizeFor()
-    {
-        return $this->has_optimize_for;
-    }
-
     /**
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
@@ -530,7 +533,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getGoPackage()
     {
-        return $this->go_package;
+        return isset($this->go_package) ? $this->go_package : '';
+    }
+
+    public function hasGoPackage()
+    {
+        return isset($this->go_package);
+    }
+
+    public function clearGoPackage()
+    {
+        unset($this->go_package);
     }
 
     /**
@@ -548,16 +561,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->go_package = $var;
-        $this->has_go_package = true;
 
         return $this;
     }
 
-    public function hasGoPackage()
-    {
-        return $this->has_go_package;
-    }
-
     /**
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
@@ -574,7 +581,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getCcGenericServices()
     {
-        return $this->cc_generic_services;
+        return isset($this->cc_generic_services) ? $this->cc_generic_services : false;
+    }
+
+    public function hasCcGenericServices()
+    {
+        return isset($this->cc_generic_services);
+    }
+
+    public function clearCcGenericServices()
+    {
+        unset($this->cc_generic_services);
     }
 
     /**
@@ -596,23 +613,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->cc_generic_services = $var;
-        $this->has_cc_generic_services = true;
 
         return $this;
     }
 
-    public function hasCcGenericServices()
-    {
-        return $this->has_cc_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
      * @return bool
      */
     public function getJavaGenericServices()
     {
-        return $this->java_generic_services;
+        return isset($this->java_generic_services) ? $this->java_generic_services : false;
+    }
+
+    public function hasJavaGenericServices()
+    {
+        return isset($this->java_generic_services);
+    }
+
+    public function clearJavaGenericServices()
+    {
+        unset($this->java_generic_services);
     }
 
     /**
@@ -624,23 +645,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->java_generic_services = $var;
-        $this->has_java_generic_services = true;
 
         return $this;
     }
 
-    public function hasJavaGenericServices()
-    {
-        return $this->has_java_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
      * @return bool
      */
     public function getPyGenericServices()
     {
-        return $this->py_generic_services;
+        return isset($this->py_generic_services) ? $this->py_generic_services : false;
+    }
+
+    public function hasPyGenericServices()
+    {
+        return isset($this->py_generic_services);
+    }
+
+    public function clearPyGenericServices()
+    {
+        unset($this->py_generic_services);
     }
 
     /**
@@ -652,23 +677,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->py_generic_services = $var;
-        $this->has_py_generic_services = true;
 
         return $this;
     }
 
-    public function hasPyGenericServices()
-    {
-        return $this->has_py_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool php_generic_services = 42 [default = false];</code>
      * @return bool
      */
     public function getPhpGenericServices()
     {
-        return $this->php_generic_services;
+        return isset($this->php_generic_services) ? $this->php_generic_services : false;
+    }
+
+    public function hasPhpGenericServices()
+    {
+        return isset($this->php_generic_services);
+    }
+
+    public function clearPhpGenericServices()
+    {
+        unset($this->php_generic_services);
     }
 
     /**
@@ -680,16 +709,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->php_generic_services = $var;
-        $this->has_php_generic_services = true;
 
         return $this;
     }
 
-    public function hasPhpGenericServices()
-    {
-        return $this->has_php_generic_services;
-    }
-
     /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -701,7 +724,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -718,16 +751,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
@@ -737,7 +764,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getCcEnableArenas()
     {
-        return $this->cc_enable_arenas;
+        return isset($this->cc_enable_arenas) ? $this->cc_enable_arenas : false;
+    }
+
+    public function hasCcEnableArenas()
+    {
+        return isset($this->cc_enable_arenas);
+    }
+
+    public function clearCcEnableArenas()
+    {
+        unset($this->cc_enable_arenas);
     }
 
     /**
@@ -752,16 +789,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->cc_enable_arenas = $var;
-        $this->has_cc_enable_arenas = true;
 
         return $this;
     }
 
-    public function hasCcEnableArenas()
-    {
-        return $this->has_cc_enable_arenas;
-    }
-
     /**
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
@@ -771,7 +802,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getObjcClassPrefix()
     {
-        return $this->objc_class_prefix;
+        return isset($this->objc_class_prefix) ? $this->objc_class_prefix : '';
+    }
+
+    public function hasObjcClassPrefix()
+    {
+        return isset($this->objc_class_prefix);
+    }
+
+    public function clearObjcClassPrefix()
+    {
+        unset($this->objc_class_prefix);
     }
 
     /**
@@ -786,16 +827,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->objc_class_prefix = $var;
-        $this->has_objc_class_prefix = true;
 
         return $this;
     }
 
-    public function hasObjcClassPrefix()
-    {
-        return $this->has_objc_class_prefix;
-    }
-
     /**
      * Namespace for generated classes; defaults to the package.
      *
@@ -804,7 +839,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getCsharpNamespace()
     {
-        return $this->csharp_namespace;
+        return isset($this->csharp_namespace) ? $this->csharp_namespace : '';
+    }
+
+    public function hasCsharpNamespace()
+    {
+        return isset($this->csharp_namespace);
+    }
+
+    public function clearCsharpNamespace()
+    {
+        unset($this->csharp_namespace);
     }
 
     /**
@@ -818,16 +863,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->csharp_namespace = $var;
-        $this->has_csharp_namespace = true;
 
         return $this;
     }
 
-    public function hasCsharpNamespace()
-    {
-        return $this->has_csharp_namespace;
-    }
-
     /**
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
@@ -839,7 +878,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getSwiftPrefix()
     {
-        return $this->swift_prefix;
+        return isset($this->swift_prefix) ? $this->swift_prefix : '';
+    }
+
+    public function hasSwiftPrefix()
+    {
+        return isset($this->swift_prefix);
+    }
+
+    public function clearSwiftPrefix()
+    {
+        unset($this->swift_prefix);
     }
 
     /**
@@ -856,16 +905,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->swift_prefix = $var;
-        $this->has_swift_prefix = true;
 
         return $this;
     }
 
-    public function hasSwiftPrefix()
-    {
-        return $this->has_swift_prefix;
-    }
-
     /**
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
@@ -875,7 +918,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getPhpClassPrefix()
     {
-        return $this->php_class_prefix;
+        return isset($this->php_class_prefix) ? $this->php_class_prefix : '';
+    }
+
+    public function hasPhpClassPrefix()
+    {
+        return isset($this->php_class_prefix);
+    }
+
+    public function clearPhpClassPrefix()
+    {
+        unset($this->php_class_prefix);
     }
 
     /**
@@ -890,16 +943,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->php_class_prefix = $var;
-        $this->has_php_class_prefix = true;
 
         return $this;
     }
 
-    public function hasPhpClassPrefix()
-    {
-        return $this->has_php_class_prefix;
-    }
-
     /**
      * Use this option to change the namespace of php generated classes. Default
      * is empty. When this option is empty, the package name will be used for
@@ -910,7 +957,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getPhpNamespace()
     {
-        return $this->php_namespace;
+        return isset($this->php_namespace) ? $this->php_namespace : '';
+    }
+
+    public function hasPhpNamespace()
+    {
+        return isset($this->php_namespace);
+    }
+
+    public function clearPhpNamespace()
+    {
+        unset($this->php_namespace);
     }
 
     /**
@@ -926,16 +983,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->php_namespace = $var;
-        $this->has_php_namespace = true;
 
         return $this;
     }
 
-    public function hasPhpNamespace()
-    {
-        return $this->has_php_namespace;
-    }
-
     /**
      * Use this option to change the namespace of php generated metadata classes.
      * Default is empty. When this option is empty, the proto file name will be
@@ -946,7 +997,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getPhpMetadataNamespace()
     {
-        return $this->php_metadata_namespace;
+        return isset($this->php_metadata_namespace) ? $this->php_metadata_namespace : '';
+    }
+
+    public function hasPhpMetadataNamespace()
+    {
+        return isset($this->php_metadata_namespace);
+    }
+
+    public function clearPhpMetadataNamespace()
+    {
+        unset($this->php_metadata_namespace);
     }
 
     /**
@@ -962,16 +1023,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->php_metadata_namespace = $var;
-        $this->has_php_metadata_namespace = true;
 
         return $this;
     }
 
-    public function hasPhpMetadataNamespace()
-    {
-        return $this->has_php_metadata_namespace;
-    }
-
     /**
      * Use this option to change the package of ruby generated classes. Default
      * is empty. When this option is not set, the package name will be used for
@@ -982,7 +1037,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      */
     public function getRubyPackage()
     {
-        return $this->ruby_package;
+        return isset($this->ruby_package) ? $this->ruby_package : '';
+    }
+
+    public function hasRubyPackage()
+    {
+        return isset($this->ruby_package);
+    }
+
+    public function clearRubyPackage()
+    {
+        unset($this->ruby_package);
     }
 
     /**
@@ -998,16 +1063,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->ruby_package = $var;
-        $this->has_ruby_package = true;
 
         return $this;
     }
 
-    public function hasRubyPackage()
-    {
-        return $this->has_ruby_package;
-    }
-
     /**
      * The parser stores options it doesn't recognize here.
      * See the documentation for the "Options" section above.
@@ -1032,15 +1091,9 @@ class FileOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 0 - 7
php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php

@@ -26,7 +26,6 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
      */
     private $annotation;
-    private $has_annotation = false;
 
     /**
      * Constructor.
@@ -68,15 +67,9 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class);
         $this->annotation = $arr;
-        $this->has_annotation = true;
 
         return $this;
     }
 
-    public function hasAnnotation()
-    {
-        return $this->has_annotation;
-    }
-
 }
 

+ 36 - 34
php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php

@@ -22,22 +22,19 @@ class Annotation extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
-    private $has_path = false;
     /**
      * Identifies the filesystem path to the original source .proto.
      *
      * Generated from protobuf field <code>optional string source_file = 2;</code>
      */
-    protected $source_file = '';
-    private $has_source_file = false;
+    protected $source_file = null;
     /**
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
      *
      * Generated from protobuf field <code>optional int32 begin = 3;</code>
      */
-    protected $begin = 0;
-    private $has_begin = false;
+    protected $begin = null;
     /**
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
@@ -45,8 +42,7 @@ class Annotation extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional int32 end = 4;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -97,16 +93,10 @@ class Annotation extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
-        $this->has_path = true;
 
         return $this;
     }
 
-    public function hasPath()
-    {
-        return $this->has_path;
-    }
-
     /**
      * Identifies the filesystem path to the original source .proto.
      *
@@ -115,7 +105,17 @@ class Annotation extends \Google\Protobuf\Internal\Message
      */
     public function getSourceFile()
     {
-        return $this->source_file;
+        return isset($this->source_file) ? $this->source_file : '';
+    }
+
+    public function hasSourceFile()
+    {
+        return isset($this->source_file);
+    }
+
+    public function clearSourceFile()
+    {
+        unset($this->source_file);
     }
 
     /**
@@ -129,16 +129,10 @@ class Annotation extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->source_file = $var;
-        $this->has_source_file = true;
 
         return $this;
     }
 
-    public function hasSourceFile()
-    {
-        return $this->has_source_file;
-    }
-
     /**
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
@@ -148,7 +142,17 @@ class Annotation extends \Google\Protobuf\Internal\Message
      */
     public function getBegin()
     {
-        return $this->begin;
+        return isset($this->begin) ? $this->begin : 0;
+    }
+
+    public function hasBegin()
+    {
+        return isset($this->begin);
+    }
+
+    public function clearBegin()
+    {
+        unset($this->begin);
     }
 
     /**
@@ -163,16 +167,10 @@ class Annotation extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->begin = $var;
-        $this->has_begin = true;
 
         return $this;
     }
 
-    public function hasBegin()
-    {
-        return $this->has_begin;
-    }
-
     /**
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
@@ -183,7 +181,17 @@ class Annotation extends \Google\Protobuf\Internal\Message
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -199,16 +207,10 @@ class Annotation extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 20 - 6
php/src/Google/Protobuf/Internal/Message.php

@@ -225,6 +225,15 @@ class Message
         }
     }
 
+    protected function hasOneof($number)
+    {
+        $field = $this->desc->getFieldByNumber($number);
+        $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+        $oneof_name = $oneof->getName();
+        $oneof_field = $this->$oneof_name;
+        return $number === $oneof_field->getNumber();
+    }
+
     protected function writeOneof($number, $value)
     {
         $field = $this->desc->getFieldByNumber($number);
@@ -1559,14 +1568,19 @@ class Message
      */
     private function existField($field)
     {
-        $oneof_index = $field->getOneofIndex();
-        if ($oneof_index !== -1) {
-            $oneof = $this->desc->getOneofDecl()[$oneof_index];
-            $oneof_name = $oneof->getName();
-            return $this->$oneof_name->getNumber() === $field->getNumber();
+        $getter = $field->getGetter();
+        $hazzer = "has" . substr($getter, 3);
+
+        if (method_exists($this, $hazzer)) {
+          return $this->$hazzer();
+        } else if ($field->getOneofIndex() !== -1) {
+          // For old generated code, which does not have hazzers for oneof
+          // fields.
+          $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+          $oneof_name = $oneof->getName();
+          return $this->$oneof_name->getNumber() === $field->getNumber();
         }
 
-        $getter = $field->getGetter();
         $values = $this->$getter();
         if ($field->isMap()) {
             return count($values) !== 0;

+ 48 - 43
php/src/Google/Protobuf/Internal/MessageOptions.php

@@ -34,8 +34,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool message_set_wire_format = 1 [default = false];</code>
      */
-    protected $message_set_wire_format = false;
-    private $has_message_set_wire_format = false;
+    protected $message_set_wire_format = null;
     /**
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
@@ -43,8 +42,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
      */
-    protected $no_standard_descriptor_accessor = false;
-    private $has_no_standard_descriptor_accessor = false;
+    protected $no_standard_descriptor_accessor = null;
     /**
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -53,8 +51,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Whether the message is an automatically generated map entry type for the
      * maps field.
@@ -77,15 +74,13 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      */
-    protected $map_entry = false;
-    private $has_map_entry = false;
+    protected $map_entry = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -168,7 +163,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      */
     public function getMessageSetWireFormat()
     {
-        return $this->message_set_wire_format;
+        return isset($this->message_set_wire_format) ? $this->message_set_wire_format : false;
+    }
+
+    public function hasMessageSetWireFormat()
+    {
+        return isset($this->message_set_wire_format);
+    }
+
+    public function clearMessageSetWireFormat()
+    {
+        unset($this->message_set_wire_format);
     }
 
     /**
@@ -196,16 +201,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->message_set_wire_format = $var;
-        $this->has_message_set_wire_format = true;
 
         return $this;
     }
 
-    public function hasMessageSetWireFormat()
-    {
-        return $this->has_message_set_wire_format;
-    }
-
     /**
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
@@ -216,7 +215,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      */
     public function getNoStandardDescriptorAccessor()
     {
-        return $this->no_standard_descriptor_accessor;
+        return isset($this->no_standard_descriptor_accessor) ? $this->no_standard_descriptor_accessor : false;
+    }
+
+    public function hasNoStandardDescriptorAccessor()
+    {
+        return isset($this->no_standard_descriptor_accessor);
+    }
+
+    public function clearNoStandardDescriptorAccessor()
+    {
+        unset($this->no_standard_descriptor_accessor);
     }
 
     /**
@@ -232,16 +241,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->no_standard_descriptor_accessor = $var;
-        $this->has_no_standard_descriptor_accessor = true;
 
         return $this;
     }
 
-    public function hasNoStandardDescriptorAccessor()
-    {
-        return $this->has_no_standard_descriptor_accessor;
-    }
-
     /**
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -253,7 +256,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -270,16 +283,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Whether the message is an automatically generated map entry type for the
      * maps field.
@@ -305,7 +312,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
      */
     public function getMapEntry()
     {
-        return $this->map_entry;
+        return isset($this->map_entry) ? $this->map_entry : false;
+    }
+
+    public function hasMapEntry()
+    {
+        return isset($this->map_entry);
+    }
+
+    public function clearMapEntry()
+    {
+        unset($this->map_entry);
     }
 
     /**
@@ -336,16 +353,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->map_entry = $var;
-        $this->has_map_entry = true;
 
         return $this;
     }
 
-    public function hasMapEntry()
-    {
-        return $this->has_map_entry;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -368,15 +379,9 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 71 - 53
php/src/Google/Protobuf/Internal/MethodDescriptorProto.php

@@ -20,40 +20,34 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
      *
      * Generated from protobuf field <code>optional string input_type = 2;</code>
      */
-    protected $input_type = '';
-    private $has_input_type = false;
+    protected $input_type = null;
     /**
      * Generated from protobuf field <code>optional string output_type = 3;</code>
      */
-    protected $output_type = '';
-    private $has_output_type = false;
+    protected $output_type = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Identifies if client streams multiple client messages
      *
      * Generated from protobuf field <code>optional bool client_streaming = 5 [default = false];</code>
      */
-    protected $client_streaming = false;
-    private $has_client_streaming = false;
+    protected $client_streaming = null;
     /**
      * Identifies if server streams multiple server messages
      *
      * Generated from protobuf field <code>optional bool server_streaming = 6 [default = false];</code>
      */
-    protected $server_streaming = false;
-    private $has_server_streaming = false;
+    protected $server_streaming = null;
 
     /**
      * Constructor.
@@ -84,7 +78,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -96,16 +100,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
@@ -115,7 +113,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getInputType()
     {
-        return $this->input_type;
+        return isset($this->input_type) ? $this->input_type : '';
+    }
+
+    public function hasInputType()
+    {
+        return isset($this->input_type);
+    }
+
+    public function clearInputType()
+    {
+        unset($this->input_type);
     }
 
     /**
@@ -130,23 +138,27 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->input_type = $var;
-        $this->has_input_type = true;
 
         return $this;
     }
 
-    public function hasInputType()
-    {
-        return $this->has_input_type;
-    }
-
     /**
      * Generated from protobuf field <code>optional string output_type = 3;</code>
      * @return string
      */
     public function getOutputType()
     {
-        return $this->output_type;
+        return isset($this->output_type) ? $this->output_type : '';
+    }
+
+    public function hasOutputType()
+    {
+        return isset($this->output_type);
+    }
+
+    public function clearOutputType()
+    {
+        unset($this->output_type);
     }
 
     /**
@@ -158,23 +170,27 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->output_type = $var;
-        $this->has_output_type = true;
 
         return $this;
     }
 
-    public function hasOutputType()
-    {
-        return $this->has_output_type;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
      * @return \Google\Protobuf\Internal\MethodOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -186,16 +202,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Identifies if client streams multiple client messages
      *
@@ -204,7 +214,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getClientStreaming()
     {
-        return $this->client_streaming;
+        return isset($this->client_streaming) ? $this->client_streaming : false;
+    }
+
+    public function hasClientStreaming()
+    {
+        return isset($this->client_streaming);
+    }
+
+    public function clearClientStreaming()
+    {
+        unset($this->client_streaming);
     }
 
     /**
@@ -218,16 +238,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->client_streaming = $var;
-        $this->has_client_streaming = true;
 
         return $this;
     }
 
-    public function hasClientStreaming()
-    {
-        return $this->has_client_streaming;
-    }
-
     /**
      * Identifies if server streams multiple server messages
      *
@@ -236,7 +250,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getServerStreaming()
     {
-        return $this->server_streaming;
+        return isset($this->server_streaming) ? $this->server_streaming : false;
+    }
+
+    public function hasServerStreaming()
+    {
+        return isset($this->server_streaming);
+    }
+
+    public function clearServerStreaming()
+    {
+        unset($this->server_streaming);
     }
 
     /**
@@ -250,15 +274,9 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->server_streaming = $var;
-        $this->has_server_streaming = true;
 
         return $this;
     }
 
-    public function hasServerStreaming()
-    {
-        return $this->has_server_streaming;
-    }
-
 }
 

+ 25 - 26
php/src/Google/Protobuf/Internal/MethodOptions.php

@@ -23,20 +23,17 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
      */
-    protected $idempotency_level = 0;
-    private $has_idempotency_level = false;
+    protected $idempotency_level = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -70,7 +67,17 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -87,23 +94,27 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
      * @return int
      */
     public function getIdempotencyLevel()
     {
-        return $this->idempotency_level;
+        return isset($this->idempotency_level) ? $this->idempotency_level : 0;
+    }
+
+    public function hasIdempotencyLevel()
+    {
+        return isset($this->idempotency_level);
+    }
+
+    public function clearIdempotencyLevel()
+    {
+        unset($this->idempotency_level);
     }
 
     /**
@@ -113,18 +124,12 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
      */
     public function setIdempotencyLevel($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions\IdempotencyLevel::class);
         $this->idempotency_level = $var;
-        $this->has_idempotency_level = true;
 
         return $this;
     }
 
-    public function hasIdempotencyLevel()
-    {
-        return $this->has_idempotency_level;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -147,15 +152,9 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 23 - 17
php/src/Google/Protobuf/Internal/OneofDescriptorProto.php

@@ -20,13 +20,11 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -49,7 +47,17 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -61,23 +69,27 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
      * @return \Google\Protobuf\Internal\OneofOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -89,15 +101,9 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 

+ 0 - 7
php/src/Google/Protobuf/Internal/OneofOptions.php

@@ -21,7 +21,6 @@ class OneofOptions extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -60,15 +59,9 @@ class OneofOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 23 - 24
php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php

@@ -20,18 +20,15 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
      */
     private $method;
-    private $has_method = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -55,7 +52,17 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -67,16 +74,10 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -95,23 +96,27 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class);
         $this->method = $arr;
-        $this->has_method = true;
 
         return $this;
     }
 
-    public function hasMethod()
-    {
-        return $this->has_method;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
      * @return \Google\Protobuf\Internal\ServiceOptions
      */
     public function getOptions()
     {
-        return $this->options;
+        return isset($this->options) ? $this->options : null;
+    }
+
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
     }
 
     /**
@@ -123,15 +128,9 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 

+ 12 - 16
php/src/Google/Protobuf/Internal/ServiceOptions.php

@@ -23,15 +23,13 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -64,7 +62,17 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -81,16 +89,10 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -113,15 +115,9 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 

+ 0 - 7
php/src/Google/Protobuf/Internal/SourceCodeInfo.php

@@ -64,7 +64,6 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
      */
     private $location;
-    private $has_location = false;
 
     /**
      * Constructor.
@@ -223,15 +222,9 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class);
         $this->location = $arr;
-        $this->has_location = true;
 
         return $this;
     }
 
-    public function hasLocation()
-    {
-        return $this->has_location;
-    }
-
 }
 

+ 24 - 39
php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php

@@ -41,7 +41,6 @@ class Location extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
-    private $has_path = false;
     /**
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
@@ -52,7 +51,6 @@ class Location extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated int32 span = 2 [packed = true];</code>
      */
     private $span;
-    private $has_span = false;
     /**
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
@@ -93,18 +91,15 @@ class Location extends \Google\Protobuf\Internal\Message
      *
      * Generated from protobuf field <code>optional string leading_comments = 3;</code>
      */
-    protected $leading_comments = '';
-    private $has_leading_comments = false;
+    protected $leading_comments = null;
     /**
      * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
      */
-    protected $trailing_comments = '';
-    private $has_trailing_comments = false;
+    protected $trailing_comments = null;
     /**
      * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
      */
     private $leading_detached_comments;
-    private $has_leading_detached_comments = false;
 
     /**
      * Constructor.
@@ -248,16 +243,10 @@ class Location extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
-        $this->has_path = true;
 
         return $this;
     }
 
-    public function hasPath()
-    {
-        return $this->has_path;
-    }
-
     /**
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
@@ -288,16 +277,10 @@ class Location extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->span = $arr;
-        $this->has_span = true;
 
         return $this;
     }
 
-    public function hasSpan()
-    {
-        return $this->has_span;
-    }
-
     /**
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
@@ -341,7 +324,17 @@ class Location extends \Google\Protobuf\Internal\Message
      */
     public function getLeadingComments()
     {
-        return $this->leading_comments;
+        return isset($this->leading_comments) ? $this->leading_comments : '';
+    }
+
+    public function hasLeadingComments()
+    {
+        return isset($this->leading_comments);
+    }
+
+    public function clearLeadingComments()
+    {
+        unset($this->leading_comments);
     }
 
     /**
@@ -390,23 +383,27 @@ class Location extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->leading_comments = $var;
-        $this->has_leading_comments = true;
 
         return $this;
     }
 
-    public function hasLeadingComments()
-    {
-        return $this->has_leading_comments;
-    }
-
     /**
      * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
      * @return string
      */
     public function getTrailingComments()
     {
-        return $this->trailing_comments;
+        return isset($this->trailing_comments) ? $this->trailing_comments : '';
+    }
+
+    public function hasTrailingComments()
+    {
+        return isset($this->trailing_comments);
+    }
+
+    public function clearTrailingComments()
+    {
+        unset($this->trailing_comments);
     }
 
     /**
@@ -418,16 +415,10 @@ class Location extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->trailing_comments = $var;
-        $this->has_trailing_comments = true;
 
         return $this;
     }
 
-    public function hasTrailingComments()
-    {
-        return $this->has_trailing_comments;
-    }
-
     /**
      * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -446,16 +437,10 @@ class Location extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->leading_detached_comments = $arr;
-        $this->has_leading_detached_comments = true;
 
         return $this;
     }
 
-    public function hasLeadingDetachedComments()
-    {
-        return $this->has_leading_detached_comments;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 72 - 61
php/src/Google/Protobuf/Internal/UninterpretedOption.php

@@ -26,40 +26,33 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
      */
     private $name;
-    private $has_name = false;
     /**
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
      *
      * Generated from protobuf field <code>optional string identifier_value = 3;</code>
      */
-    protected $identifier_value = '';
-    private $has_identifier_value = false;
+    protected $identifier_value = null;
     /**
      * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
      */
-    protected $positive_int_value = 0;
-    private $has_positive_int_value = false;
+    protected $positive_int_value = null;
     /**
      * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
      */
-    protected $negative_int_value = 0;
-    private $has_negative_int_value = false;
+    protected $negative_int_value = null;
     /**
      * Generated from protobuf field <code>optional double double_value = 6;</code>
      */
-    protected $double_value = 0.0;
-    private $has_double_value = false;
+    protected $double_value = null;
     /**
      * Generated from protobuf field <code>optional bytes string_value = 7;</code>
      */
-    protected $string_value = '';
-    private $has_string_value = false;
+    protected $string_value = null;
     /**
      * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
      */
-    protected $aggregate_value = '';
-    private $has_aggregate_value = false;
+    protected $aggregate_value = null;
 
     /**
      * Constructor.
@@ -101,16 +94,10 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class);
         $this->name = $arr;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
@@ -120,7 +107,17 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
      */
     public function getIdentifierValue()
     {
-        return $this->identifier_value;
+        return isset($this->identifier_value) ? $this->identifier_value : '';
+    }
+
+    public function hasIdentifierValue()
+    {
+        return isset($this->identifier_value);
+    }
+
+    public function clearIdentifierValue()
+    {
+        unset($this->identifier_value);
     }
 
     /**
@@ -135,23 +132,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->identifier_value = $var;
-        $this->has_identifier_value = true;
 
         return $this;
     }
 
-    public function hasIdentifierValue()
-    {
-        return $this->has_identifier_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
      * @return int|string
      */
     public function getPositiveIntValue()
     {
-        return $this->positive_int_value;
+        return isset($this->positive_int_value) ? $this->positive_int_value : 0;
+    }
+
+    public function hasPositiveIntValue()
+    {
+        return isset($this->positive_int_value);
+    }
+
+    public function clearPositiveIntValue()
+    {
+        unset($this->positive_int_value);
     }
 
     /**
@@ -163,23 +164,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkUint64($var);
         $this->positive_int_value = $var;
-        $this->has_positive_int_value = true;
 
         return $this;
     }
 
-    public function hasPositiveIntValue()
-    {
-        return $this->has_positive_int_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
      * @return int|string
      */
     public function getNegativeIntValue()
     {
-        return $this->negative_int_value;
+        return isset($this->negative_int_value) ? $this->negative_int_value : 0;
+    }
+
+    public function hasNegativeIntValue()
+    {
+        return isset($this->negative_int_value);
+    }
+
+    public function clearNegativeIntValue()
+    {
+        unset($this->negative_int_value);
     }
 
     /**
@@ -191,23 +196,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkInt64($var);
         $this->negative_int_value = $var;
-        $this->has_negative_int_value = true;
 
         return $this;
     }
 
-    public function hasNegativeIntValue()
-    {
-        return $this->has_negative_int_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional double double_value = 6;</code>
      * @return float
      */
     public function getDoubleValue()
     {
-        return $this->double_value;
+        return isset($this->double_value) ? $this->double_value : 0.0;
+    }
+
+    public function hasDoubleValue()
+    {
+        return isset($this->double_value);
+    }
+
+    public function clearDoubleValue()
+    {
+        unset($this->double_value);
     }
 
     /**
@@ -219,23 +228,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkDouble($var);
         $this->double_value = $var;
-        $this->has_double_value = true;
 
         return $this;
     }
 
-    public function hasDoubleValue()
-    {
-        return $this->has_double_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional bytes string_value = 7;</code>
      * @return string
      */
     public function getStringValue()
     {
-        return $this->string_value;
+        return isset($this->string_value) ? $this->string_value : '';
+    }
+
+    public function hasStringValue()
+    {
+        return isset($this->string_value);
+    }
+
+    public function clearStringValue()
+    {
+        unset($this->string_value);
     }
 
     /**
@@ -247,23 +260,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, False);
         $this->string_value = $var;
-        $this->has_string_value = true;
 
         return $this;
     }
 
-    public function hasStringValue()
-    {
-        return $this->has_string_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
      * @return string
      */
     public function getAggregateValue()
     {
-        return $this->aggregate_value;
+        return isset($this->aggregate_value) ? $this->aggregate_value : '';
+    }
+
+    public function hasAggregateValue()
+    {
+        return isset($this->aggregate_value);
+    }
+
+    public function clearAggregateValue()
+    {
+        unset($this->aggregate_value);
     }
 
     /**
@@ -275,15 +292,9 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->aggregate_value = $var;
-        $this->has_aggregate_value = true;
 
         return $this;
     }
 
-    public function hasAggregateValue()
-    {
-        return $this->has_aggregate_value;
-    }
-
 }
 

+ 24 - 18
php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php

@@ -24,13 +24,11 @@ class NamePart extends \Google\Protobuf\Internal\Message
     /**
      * Generated from protobuf field <code>required string name_part = 1;</code>
      */
-    protected $name_part = '';
-    private $has_name_part = false;
+    protected $name_part = null;
     /**
      * Generated from protobuf field <code>required bool is_extension = 2;</code>
      */
-    protected $is_extension = false;
-    private $has_is_extension = false;
+    protected $is_extension = null;
 
     /**
      * Constructor.
@@ -53,7 +51,17 @@ class NamePart extends \Google\Protobuf\Internal\Message
      */
     public function getNamePart()
     {
-        return $this->name_part;
+        return isset($this->name_part) ? $this->name_part : '';
+    }
+
+    public function hasNamePart()
+    {
+        return isset($this->name_part);
+    }
+
+    public function clearNamePart()
+    {
+        unset($this->name_part);
     }
 
     /**
@@ -65,23 +73,27 @@ class NamePart extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkString($var, True);
         $this->name_part = $var;
-        $this->has_name_part = true;
 
         return $this;
     }
 
-    public function hasNamePart()
-    {
-        return $this->has_name_part;
-    }
-
     /**
      * Generated from protobuf field <code>required bool is_extension = 2;</code>
      * @return bool
      */
     public function getIsExtension()
     {
-        return $this->is_extension;
+        return isset($this->is_extension) ? $this->is_extension : false;
+    }
+
+    public function hasIsExtension()
+    {
+        return isset($this->is_extension);
+    }
+
+    public function clearIsExtension()
+    {
+        unset($this->is_extension);
     }
 
     /**
@@ -93,16 +105,10 @@ class NamePart extends \Google\Protobuf\Internal\Message
     {
         GPBUtil::checkBool($var);
         $this->is_extension = $var;
-        $this->has_is_extension = true;
 
         return $this;
     }
 
-    public function hasIsExtension()
-    {
-        return $this->has_is_extension;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.

+ 1 - 0
php/src/Google/Protobuf/NullValue.php

@@ -35,6 +35,7 @@ class NullValue
         return self::$valueToName[$value];
     }
 
+
     public static function value($name)
     {
         $const = __CLASS__ . '::' . strtoupper($name);

+ 5 - 0
php/src/Google/Protobuf/OneofDescriptor.php

@@ -72,4 +72,9 @@ class OneofDescriptor
     {
         return count($this->internal_desc->getFields());
     }
+
+    public function isSynthetic()
+    {
+      return $this->internal_desc->isSynthetic();
+    }
 }

+ 30 - 0
php/src/Google/Protobuf/Value.php

@@ -57,6 +57,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(1);
     }
 
+    public function hasNullValue()
+    {
+        return $this->hasOneof(1);
+    }
+
     /**
      * Represents a null value.
      *
@@ -83,6 +88,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(2);
     }
 
+    public function hasNumberValue()
+    {
+        return $this->hasOneof(2);
+    }
+
     /**
      * Represents a double value.
      *
@@ -109,6 +119,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(3);
     }
 
+    public function hasStringValue()
+    {
+        return $this->hasOneof(3);
+    }
+
     /**
      * Represents a string value.
      *
@@ -135,6 +150,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(4);
     }
 
+    public function hasBoolValue()
+    {
+        return $this->hasOneof(4);
+    }
+
     /**
      * Represents a boolean value.
      *
@@ -161,6 +181,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(5);
     }
 
+    public function hasStructValue()
+    {
+        return $this->hasOneof(5);
+    }
+
     /**
      * Represents a structured value.
      *
@@ -187,6 +212,11 @@ class Value extends \Google\Protobuf\Internal\Message
         return $this->readOneof(6);
     }
 
+    public function hasListValue()
+    {
+        return $this->hasOneof(6);
+    }
+
     /**
      * Represents a repeated `Value`.
      *

+ 1 - 1
php/tests/array_test.php → php/tests/ArrayTest.php

@@ -7,7 +7,7 @@ use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
 use Foo\TestMessage\Sub;
 
-class RepeatedFieldTest extends \PHPUnit\Framework\TestCase
+class ArrayTest extends \PHPUnit\Framework\TestCase
 {
 
     #########################################################

+ 0 - 0
php/tests/descriptors_test.php → php/tests/DescriptorsTest.php


+ 36 - 0
php/tests/encode_decode_test.php → php/tests/EncodeDecodeTest.php

@@ -326,6 +326,42 @@ class EncodeDecodeTest extends TestBase
 
     }
 
+    public function testEncodeDecodeOptional()
+    {
+      $m = new TestMessage();
+      $this->assertFalse($m->hasTrueOptionalInt32());
+      $data = $m->serializeToString();
+      $this->assertSame("", $data);
+
+      $m->setTrueOptionalInt32(0);
+      $this->assertTrue($m->hasTrueOptionalInt32());
+      $data = $m->serializeToString();
+      $this->assertNotSame("", $data);
+
+      $m2 = new TestMessage();
+      $m2->mergeFromString($data);
+      $this->assertTrue($m2->hasTrueOptionalInt32());
+      $this->assertSame(0, $m2->getTrueOptionalInt32());
+    }
+
+    public function testJsonEncodeDecodeOptional()
+    {
+      $m = new TestMessage();
+      $this->assertFalse($m->hasTrueOptionalInt32());
+      $data = $m->serializeToJsonString();
+      $this->assertSame("{}", $data);
+
+      $m->setTrueOptionalInt32(0);
+      $this->assertTrue($m->hasTrueOptionalInt32());
+      $data = $m->serializeToJsonString();
+      $this->assertNotSame("{}", $data);
+
+      $m2 = new TestMessage();
+      $m2->mergeFromJsonString($data);
+      $this->assertTrue($m2->hasTrueOptionalInt32());
+      $this->assertSame(0, $m2->getTrueOptionalInt32());
+    }
+
     public function testJsonEncodeDecodeOneof()
     {
         $m = new TestMessage();

+ 22 - 0
php/tests/generated_class_test.php → php/tests/GeneratedClassTest.php

@@ -71,6 +71,28 @@ class GeneratedClassTest extends TestBase
         $this->assertSame(MIN_INT32, $m->getOptionalInt32());
     }
 
+    #########################################################
+    # Test optional int32 field.
+    #########################################################
+
+    public function testOptionalInt32Field()
+    {
+        $m = new TestMessage();
+
+        $this->assertFalse($m->hasTrueOptionalInt32());
+        $this->assertSame(0, $m->getTrueOptionalInt32());
+
+        // Set integer.
+        $m->setTrueOptionalInt32(MAX_INT32);
+        $this->assertTrue($m->hasTrueOptionalInt32());
+        $this->assertSame(MAX_INT32, $m->getTrueOptionalInt32());
+
+        // Clear integer.
+        $m->clearTrueOptionalInt32();
+        $this->assertFalse($m->hasTrueOptionalInt32());
+        $this->assertSame(0, $m->getTrueOptionalInt32());
+    }
+
     #########################################################
     # Test uint32 field.
     #########################################################

+ 0 - 0
php/tests/generated_phpdoc_test.php → php/tests/GeneratedPhpdocTest.php


+ 0 - 0
php/tests/generated_service_test.php → php/tests/GeneratedServiceTest.php


+ 0 - 0
php/tests/map_field_test.php → php/tests/MapFieldTest.php


+ 1 - 1
php/tests/php_implementation_test.php → php/tests/PhpImplementationTest.php

@@ -515,7 +515,7 @@ class ImplementationTest extends TestBase
     {
         $m = new TestMessage();
         TestUtil::setTestMessage($m);
-        $this->assertSame(518, $m->byteSize());
+        $this->assertSame(504, $m->byteSize());
     }
 
     public function testPackedByteSize()

+ 0 - 0
php/tests/well_known_test.php → php/tests/WellKnownTest.php


+ 0 - 0
php/tests/wrapper_type_setters_test.php → php/tests/WrapperTypeSettersTest.php


+ 8 - 1
php/tests/compatibility_test.sh

@@ -100,11 +100,18 @@ cd protobuf/php
 composer install
 
 # Remove implementation detail tests.
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
+# TODO(teboring): Temporarily disable encode_decode_test.php. In 3.13.0-rc1,
+# repeated primitive field encoding is changed to packed, which is a bug fix.
+# However, this fails the compatibility test which hard coded old encoding.
+# Will reenable the test after making a release. After the version bump, the
+# compatibility test will use the updated test code.
+tests=( array_test.php generated_class_test.php map_field_test.php well_known_test.php )
 sed -i.bak '/php_implementation_test.php/d' phpunit.xml
 sed -i.bak '/generated_phpdoc_test.php/d' phpunit.xml
+sed -i.bak '/encode_decode_test.php/d' phpunit.xml
 sed -i.bak 's/generated_phpdoc_test.php//g' tests/test.sh
 sed -i.bak 's/generated_service_test.php//g' tests/test.sh
+sed -i.bak 's/encode_decode_test.php//g' tests/test.sh
 sed -i.bak '/memory_leak_test.php/d' tests/test.sh
 sed -i.bak '/^    public function testTimestamp()$/,/^    }$/d' tests/well_known_test.php
 sed -i.bak 's/PHPUnit_Framework_TestCase/\\PHPUnit\\Framework\\TestCase/g' tests/array_test.php

+ 8 - 8
php/tests/compile_extension.sh

@@ -4,17 +4,17 @@ set -ex
 
 cd $(dirname $0)
 
+pushd  ../ext/google/protobuf
+phpize --clean
+rm -f configure.in configure.ac
+php make-preload.php
+phpize
 if [ "$1" = "--release" ]; then
-  CFLAGS="-Wall"
+  ./configure --with-php-config=$(which php-config)
 else
   # To get debugging symbols in PHP itself, build PHP with:
   #   $ ./configure --enable-debug CFLAGS='-g -O0'
-  CFLAGS="-g -O0 -Wall"
+  ./configure --with-php-config=$(which php-config) CFLAGS="-g -O0 -Wall"
 fi
-
-pushd  ../ext/google/protobuf
-phpize --clean
-rm -f configure.in configure.ac
-php make-preload.php
-phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make
+make
 popd

+ 2 - 2
php/tests/generate_protos.sh

@@ -7,10 +7,10 @@ cd `dirname $0`
 rm -rf generated
 mkdir -p generated
 
-find proto -type f -name "*.proto"| xargs ../../src/protoc --php_out=generated -I../../src -I.
+find proto -type f -name "*.proto"| xargs ../../src/protoc --experimental_allow_proto3_optional --php_out=generated -I../../src -I.
 
 if [ "$1" = "--aggregate_metadata" ]; then
   # Overwrite some of the files to use aggregation.
   AGGREGATED_FILES="proto/test.proto proto/test_include.proto proto/test_import_descriptor_proto.proto"
-  ../../src/protoc --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. $AGGREGATED_FILES
+  ../../src/protoc --experimental_allow_proto3_optional --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. $AGGREGATED_FILES
 fi

+ 21 - 0
php/tests/proto/test.proto

@@ -34,6 +34,27 @@ message TestMessage {
   bar.TestInclude optional_included_message = 18;
   TestMessage recursive = 19;
 
+  // True optional
+  optional int32 true_optional_int32 = 201;
+  optional int64 true_optional_int64 = 202;
+  optional uint32 true_optional_uint32 = 203;
+  optional uint64 true_optional_uint64 = 204;
+  optional sint32 true_optional_sint32 = 205;
+  optional sint64 true_optional_sint64 = 206;
+  optional fixed32 true_optional_fixed32 = 207;
+  optional fixed64 true_optional_fixed64 = 208;
+  optional sfixed32 true_optional_sfixed32 = 209;
+  optional sfixed64 true_optional_sfixed64 = 210;
+  optional float true_optional_float = 211;
+  optional double true_optional_double = 212;
+  optional bool true_optional_bool = 213;
+  optional string true_optional_string = 214;
+  optional bytes true_optional_bytes = 215;
+
+  optional TestEnum true_optional_enum = 216;
+  optional Sub true_optional_message = 217;
+  optional bar.TestInclude true_optional_included_message = 218;
+
   // Repeated
   repeated    int32 repeated_int32    = 31;
   repeated    int64 repeated_int64    = 32;

+ 6 - 3
php/tests/test.sh

@@ -18,6 +18,9 @@ case "$PHP_VERSION" in
   7.3.*|7.4.*)
     PHPUNIT=phpunit-8.phar
     ;;
+  8.0.*)
+    PHPUNIT=phpunit-9.phar
+    ;;
   *)
     echo "ERROR: Unsupported PHP version $PHP_VERSION"
     exit 1
@@ -26,7 +29,7 @@ esac
 
 [ -f $PHPUNIT ] || wget https://phar.phpunit.de/$PHPUNIT
 
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php descriptors_test.php wrapper_type_setters_test.php)
+tests=( ArrayTest.php EncodeDecodeTest.php GeneratedClassTest.php MapFieldTest.php WellKnownTest.php DescriptorsTest.php WrapperTypeSettersTest.php)
 
 for t in "${tests[@]}"
 do
@@ -51,8 +54,8 @@ done
 
 export ZEND_DONT_UNLOAD_MODULES=1
 export USE_ZEND_ALLOC=0
-valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
-valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
+valgrind --suppressions=valgrind.supp --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
+valgrind --suppressions=valgrind.supp --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
 
 # TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by
 # regression test.)

+ 14 - 28
php/tests/test_util.php

@@ -338,38 +338,24 @@ class TestUtil
             "800101" .
             "8A01020821" .
 
-            "F801D6FFFFFFFFFFFFFFFF01" .
-            "F801CCFFFFFFFFFFFFFFFF01" .
-            "8002D5FFFFFFFFFFFFFFFF01" .
-            "8002CBFFFFFFFFFFFFFFFF01" .
-            "88022A" .
-            "880234" .
-            "90022B" .
-            "900235" .
-            "980257" .
-            "98026B" .
-            "A00259" .
-            "A0026D" .
-            "AD022E000000" .
-            "AD0238000000" .
-            "B1022F00000000000000" .
-            "B1023900000000000000" .
-            "BD02D2FFFFFF" .
-            "BD02C8FFFFFF" .
-            "C102D1FFFFFFFFFFFFFF" .
-            "C102C7FFFFFFFFFFFFFF" .
-            "CD020000C03F" .
-            "CD0200002040" .
-            "D1029A9999999999F93F" .
-            "D102CDCCCCCCCCCC0440" .
-            "D80201" .
-            "D80200" .
+            "FA0114D6FFFFFFFFFFFFFFFF01CCFFFFFFFFFFFFFFFF01" .
+            "820214D5FFFFFFFFFFFFFFFF01CBFFFFFFFFFFFFFFFF01" .
+            "8A02022A34" .
+            "9202022B35" .
+            "9A0202576B" .
+            "A20202596D" .
+            "AA02082E00000038000000" .
+            "B202102F000000000000003900000000000000" .
+            "BA0208D2FFFFFFC8FFFFFF" .
+            "C20210D1FFFFFFFFFFFFFFC7FFFFFFFFFFFFFF" .
+            "CA02080000C03F00002040" .
+            "D202109A9999999999F93FCDCCCCCCCCCC0440" .
+            "DA02020100" .
             "E2020161" .
             "E2020163" .
             "EA020462626262" .
             "EA020464646464" .
-            "F00200" .
-            "F00201" .
+            "F202020001" .
             "FA02020822" .
             "FA02020823" .
 

+ 12 - 0
php/tests/valgrind.supp

@@ -0,0 +1,12 @@
+{
+   PHP_Equal_Val
+   Memcheck:Cond
+   fun:zend_string_equal_val
+}
+
+{
+   PHP_ScanDir_Tail
+   Memcheck:Cond
+   obj:/usr/bin/php7.3
+   fun:__scandir64_tail
+}

+ 1 - 1
protoc-artifacts/pom.xml

@@ -8,7 +8,7 @@
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protoc</artifactId>
-  <version>3.12.3</version>
+  <version>3.13.0</version>
   <packaging>pom</packaging>
   <name>Protobuf Compiler</name>
   <description>

+ 1 - 1
python/google/protobuf/__init__.py

@@ -30,7 +30,7 @@
 
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.12.3'
+__version__ = '3.13.0'
 
 if __name__ != '__main__':
   try:

+ 5 - 1
python/release.sh

@@ -11,7 +11,10 @@ function run_install_test() {
   local PYTHON=$2
   local PYPI=$3
 
-  virtualenv --no-site-packages -p `which $PYTHON` test-venv
+  # Setuptools 45.0 removed support for Python 2, so to test with Python 2 we
+  # pass --no-setuptools here and then install an older setuptools version
+  # below.
+  virtualenv -p `which $PYTHON` --no-setuptools test-venv
 
   # Intentionally put a broken protoc in the path to make sure installation
   # doesn't require protoc installed.
@@ -19,6 +22,7 @@ function run_install_test() {
   chmod +x test-venv/bin/protoc
 
   source test-venv/bin/activate
+  pip install "setuptools<45"
   pip install -i ${PYPI} protobuf==${VERSION} --no-cache-dir
   deactivate
   rm -fr test-venv

+ 1 - 0
python/setup.py

@@ -279,6 +279,7 @@ if __name__ == '__main__':
           'build_py': build_py,
           'test_conformance': test_conformance,
       },
+      setup_requires = ['wheel'],
       install_requires=install_requires,
       ext_modules=ext_module_list,
   )

+ 1 - 1
ruby/google-protobuf.gemspec

@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name        = "google-protobuf"
-  s.version     = "3.12.3"
+  s.version     = "3.13.0"
   git_tag       = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag
   s.licenses    = ["BSD-3-Clause"]
   s.summary     = "Protocol Buffers"

+ 1 - 1
src/Makefile.am

@@ -18,7 +18,7 @@ else
 PTHREAD_DEF =
 endif
 
-PROTOBUF_VERSION = 23:3:0
+PROTOBUF_VERSION = 24:0:0
 
 if GCC
 # Turn on all warnings except for sign comparison (we ignore sign comparison

+ 2 - 2
src/google/protobuf/any.pb.h

@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3012000
+#if PROTOBUF_VERSION < 3013000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.

+ 2 - 2
src/google/protobuf/api.pb.h

@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3012000
+#if PROTOBUF_VERSION < 3013000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.

+ 33 - 34
src/google/protobuf/compiler/php/php_generator.cc

@@ -624,21 +624,17 @@ void GenerateField(const FieldDescriptor* field, io::Printer* printer,
     printer->Print(
         "private $^name^;\n",
         "name", field->name());
-  } else if (field->containing_oneof()) {
+  } else if (field->real_containing_oneof()) {
     // Oneof fields are handled by GenerateOneofField.
     return;
   } else {
+    std::string initial_value =
+        field->has_presence() ? "null" : DefaultForField(field);
     GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
     printer->Print(
-        "protected $^name^ = ^default^;\n",
+        "protected $^name^ = ^initial_value^;\n",
         "name", field->name(),
-        "default", DefaultForField(field));
-  }
-
-  if (is_descriptor) {
-    printer->Print(
-        "private $has_^name^ = false;\n",
-        "name", field->name());
+        "initial_value", initial_value);
   }
 }
 
@@ -652,20 +648,41 @@ void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) {
 
 void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
                            io::Printer* printer) {
-  const OneofDescriptor* oneof = field->containing_oneof();
+  const OneofDescriptor* oneof = field->real_containing_oneof();
 
   // Generate getter.
+  GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
+
   if (oneof != NULL) {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
         "    return $this->readOneof(^number^);\n"
+        "}\n\n"
+        "public function has^camel_name^()\n"
+        "{\n"
+        "    return $this->hasOneof(^number^);\n"
         "}\n\n",
         "camel_name", UnderscoresToCamelCase(field->name(), true),
         "number", IntToString(field->number()));
+  } else if (field->has_presence()) {
+    printer->Print(
+        "public function get^camel_name^()\n"
+        "{\n"
+        "    return isset($this->^name^) ? $this->^name^ : ^default_value^;\n"
+        "}\n\n"
+        "public function has^camel_name^()\n"
+        "{\n"
+        "    return isset($this->^name^);\n"
+        "}\n\n"
+        "public function clear^camel_name^()\n"
+        "{\n"
+        "    unset($this->^name^);\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "name", field->name(),
+        "default_value", DefaultForField(field));
   } else {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
@@ -774,13 +791,6 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
         "name", field->name());
   }
 
-  // Set has bit for proto2 only.
-  if (is_descriptor) {
-    printer->Print(
-        "$this->has_^field_name^ = true;\n",
-        "field_name", field->name());
-  }
-
   printer->Print("\nreturn $this;\n");
 
   Outdent(printer);
@@ -803,17 +813,6 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
         "camel_name", UnderscoresToCamelCase(field->name(), true),
         "field_name", field->name());
   }
-
-  // Generate has method for proto2 only.
-  if (is_descriptor) {
-    printer->Print(
-        "public function has^camel_name^()\n"
-        "{\n"
-        "    return $this->has_^field_name^;\n"
-        "}\n\n",
-        "camel_name", UnderscoresToCamelCase(field->name(), true),
-        "field_name", field->name());
-  }
 }
 
 void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
@@ -878,7 +877,7 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
           "value", ToUpper(val->type_name()),
           "number", StrCat(field->number()),
           "other", EnumOrMessageSuffix(val, true));
-    } else if (!field->containing_oneof()) {
+    } else if (!field->real_containing_oneof()) {
       printer->Print(
           "->^label^('^field^', "
           "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
@@ -891,7 +890,7 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
   }
 
   // oneofs.
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     printer->Print("->oneof(^name^)\n",
                    "name", oneof->name());
@@ -1414,7 +1413,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
     const FieldDescriptor* field = message->field(i);
     GenerateField(field, &printer, is_descriptor);
   }
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     GenerateOneofField(oneof, &printer);
   }
@@ -1443,7 +1442,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
     const FieldDescriptor* field = message->field(i);
     GenerateFieldAccessor(field, is_descriptor, &printer);
   }
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     printer.Print(
       "/**\n"

+ 5 - 0
src/google/protobuf/compiler/php/php_generator.h

@@ -55,6 +55,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
                    const std::string& parameter,
                    GeneratorContext* generator_context,
                    std::string* error) const override;
+
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
  private:
   bool Generate(
       const FileDescriptor* file,

+ 2 - 2
src/google/protobuf/compiler/plugin.pb.h

@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3012000
+#if PROTOBUF_VERSION < 3013000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.

+ 2 - 2
src/google/protobuf/descriptor.pb.h

@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3012000
+#if PROTOBUF_VERSION < 3013000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.

+ 2 - 2
src/google/protobuf/duration.pb.h

@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3012000
+#if PROTOBUF_VERSION < 3013000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.

部分文件因文件數量過多而無法顯示