diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json index bfdb1084d5..b4d95e4830 100644 --- a/.bcr/metadata.template.json +++ b/.bcr/metadata.template.json @@ -4,110 +4,122 @@ { "email": "protobuf-packages@google.com", "github": "protobuf-team-bot", + "github_user_id": 105450428, "name": "Protobuf Team" }, { "email": "sandyzhang@google.com", "github": "zhangskz", + "github_user_id": 89936743, "name": "Sandy Zhang" }, { "email": "mkruskal@google.com", "github": "mkruskal-google", + "github_user_id": 62662355, "name": "Mike Kruskal" }, { "email": "gberg@google.com", "github": "googleberg", + "github_user_id": 107155935, "name": "Jerry Berg" }, { "email": "deannagarcia@google.com", "github": "deannagarcia", + "github_user_id": 69992229, "name": "Deanna Garcia", "do_not_notify": true }, { "email": "esrauch@google.com", "github": "esrauchg", + "github_user_id": 140440793, "name": "Em Rauch", "do_not_notify": true }, { "email": "haberman@google.com", "github": "haberman", + "github_user_id": 1270, "name": "Josh Haberman", "do_not_notify": true }, - { - "email": "hongshin@google.com", - "github": "honglooker", - "name": "Hong Shin", - "do_not_notify": true - }, { "email": "jatl@google.com", "github": "JasonLunn", + "github_user_id": 778854, "name": "Jason Lunn", "do_not_notify": true }, { "email": "jieluo@google.com", "github": "anandolee", + "github_user_id": 11618033, "name": "Jie Luo", "do_not_notify": true }, { "email": "salo@google.com", "github": "salo", + "github_user_id": 152465, "name": "Eric Salo", "do_not_notify": true }, { "email": "sangki@google.com", "github": "jguamie", + "github_user_id": 35405521, "name": "John Lee", "do_not_notify": true }, { "email": "sbenza@google.com", "github": "sbenzaquen", + "github_user_id": 14094653, "name": "Samuel Benzaquen", "do_not_notify": true }, { "email": "shaod@google.com", "github": "shaod2", + "github_user_id": 67387070, "name": "Dennis Shao", "do_not_notify": true }, { "email": "tonyliaoss@google.com", "github": "tonyliaoss", + "github_user_id": 1459994, "name": "Tony Liao", "do_not_notify": true }, { "email": "rgoldfinger@google.com", "github": "rgoldfinger6", + "github_user_id": 94469227, "name": "Rachel Goldfinger", "do_not_notify": true }, { "email": "jamiepilgrim@google.com", "github": "pilgrimmemoirs", + "github_user_id": 8316393, "name": "Jamie Pilgrim", "do_not_notify": true }, { "email": "karenwuz@google.com", "github": "karenwuz", + "github_user_id": 242015323, "name": "Karen Wu", "do_not_notify": true }, { "email": "runze@google.com", "github": "runzw", + "github_user_id": 78052475, "name": "Runze Wang", "do_not_notify": true } diff --git a/BUILD.bazel b/BUILD.bazel index 6c13f7a319..8c8b2360cb 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -506,6 +506,12 @@ alias( visibility = ["//visibility:public"], ) +alias( + name = "json_enumvalue_options_proto_srcs", + actual = "//src/google/protobuf:json_enumvalue_options_proto_srcs", + visibility = ["//visibility:public"], +) + alias( name = "json_enumvalue_options_cc_proto", actual = "//src/google/protobuf:json_enumvalue_options_cc_proto", diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b7187778d..c23665e583 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ if (protobuf_BUILD_SHARED_LIBS) endif () # Version metadata -set(protobuf_VERSION_STRING "7.36.0") +set(protobuf_VERSION_STRING "7.36.0-rc-2") set(protobuf_DESCRIPTION "Protocol Buffers") set(protobuf_CONTACT "protobuf@googlegroups.com") diff --git a/MODULE.bazel b/MODULE.bazel index 3c342e4063..7bd7930bc6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -3,7 +3,7 @@ module( name = "protobuf", - version = "36.0-dev", # Automatically updated on release + version = "36.0-rc2", # Automatically updated on release bazel_compatibility = [">=8.0.0"], compatibility_level = 1, repo_name = "com_google_protobuf", @@ -212,7 +212,7 @@ crate.spec( ) crate.spec( package = "syn", - version = ">=2", + version = "2", ) crate.from_specs() use_repo(crate, crate_index = "crates") diff --git a/Protobuf.podspec b/Protobuf.podspec index 1a06267bd0..1c122a122b 100644 --- a/Protobuf.podspec +++ b/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 = '5.36.0' + s.version = '5.36.0-rc2' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.homepage = 'https://github.com/protocolbuffers/protobuf' s.license = 'BSD-3-Clause' diff --git a/cmake/install.cmake b/cmake/install.cmake index 4d7d68fc6e..3e0e16558f 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -98,15 +98,8 @@ include(${protobuf_SOURCE_DIR}/src/file_lists.cmake) set(protobuf_HEADERS ${libprotobuf_hdrs} ${libprotoc_public_hdrs} - ${wkt_protos_files} - ${cpp_file_options_proto_proto_srcs} - ${json_enumvalue_options_proto_proto_srcs} - ${cpp_features_proto_proto_srcs} - ${descriptor_proto_proto_srcs} ${plugin_proto_proto_srcs} - ${c_sharp_features_proto_proto_srcs} - ${java_features_proto_proto_srcs} - ${go_features_proto_proto_srcs} + ${release_all_options_protos_files} ) if (protobuf_BUILD_LIBUPB) list(APPEND protobuf_HEADERS ${libupb_hdrs}) @@ -115,6 +108,8 @@ if (protobuf_BUILD_LIBUPB) FILES ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb.h ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.h + ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb.h + ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/google/protobuf COMPONENT protobuf-headers ) diff --git a/cmake/installed_include_golden.txt b/cmake/installed_include_golden.txt index a1a85b2076..a8646f6e36 100644 --- a/cmake/installed_include_golden.txt +++ b/cmake/installed_include_golden.txt @@ -45,6 +45,7 @@ google/protobuf/cpp_features.pb.h google/protobuf/cpp_features.proto google/protobuf/cpp_file_options.pb.h google/protobuf/cpp_file_options.proto +google/protobuf/cpp_options.proto google/protobuf/descriptor.h google/protobuf/descriptor.pb.h google/protobuf/descriptor.proto @@ -95,6 +96,9 @@ google/protobuf/java_features.proto google/protobuf/json/json.h google/protobuf/json_enumvalue_options.pb.h google/protobuf/json_enumvalue_options.proto +google/protobuf/json_enumvalue_options.upb.h +google/protobuf/json_enumvalue_options.upb_minitable.h +google/protobuf/json_options.proto google/protobuf/map.h google/protobuf/map_entry.h google/protobuf/map_field.h @@ -221,6 +225,7 @@ upb/reflection/enum_value_def.h upb/reflection/extension_range.h upb/reflection/field_def.h upb/reflection/file_def.h +upb/reflection/json_enumvalue_options_bootstrap.h upb/reflection/message.h upb/reflection/message.hpp upb/reflection/message_def.h diff --git a/cmake/libupb.cmake b/cmake/libupb.cmake index c7c1eb24f0..6622429ca8 100644 --- a/cmake/libupb.cmake +++ b/cmake/libupb.cmake @@ -9,6 +9,9 @@ set(bootstrap_sources ${bootstrap_cmake_dir}/google/protobuf/descriptor.upb.h ${bootstrap_cmake_dir}/google/protobuf/descriptor.upb_minitable.h ${bootstrap_cmake_dir}/google/protobuf/descriptor.upb_minitable.c + ${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb.h + ${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb_minitable.h + ${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb_minitable.c ) # Note: upb does not support shared library builds, and is intended to be diff --git a/csharp/BUILD.bazel b/csharp/BUILD.bazel index b21428baa6..4bca560c65 100644 --- a/csharp/BUILD.bazel +++ b/csharp/BUILD.bazel @@ -15,7 +15,7 @@ load("//upb/cmake:build_defs.bzl", "staleness_test") filegroup( name = "c_sharp_features_proto_srcs", srcs = ["google/protobuf/c_sharp_features.proto"], - visibility = ["//:__subpackages__"], + visibility = ["//src/google/protobuf:__pkg__"], ) proto_library( diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index 2cb5ec03ff..ad7e1f64ec 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -5,7 +5,7 @@ Google Protocol Buffers tools Tools for Protocol Buffers - Google's data interchange format. See project site for more info. - 3.36.0 + 3.36.0-rc2 Google Inc. protobuf-packages https://github.com/protocolbuffers/protobuf/blob/main/LICENSE diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index dcfb63c961..dd969f2416 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -5,7 +5,7 @@ C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers - 3.36.0 + 3.36.0-rc2 10.0 Google Inc. netstandard2.0;net8.0 diff --git a/go/BUILD.bazel b/go/BUILD.bazel index 3dfdd21c1d..7390cdc0c4 100644 --- a/go/BUILD.bazel +++ b/go/BUILD.bazel @@ -3,7 +3,7 @@ load("//bazel:proto_library.bzl", "proto_library") filegroup( name = "go_features_proto_srcs", srcs = ["google/protobuf/go_features.proto"], - visibility = ["//:__subpackages__"], + visibility = ["//src/google/protobuf:__pkg__"], ) proto_library( diff --git a/java/bom/pom.xml b/java/bom/pom.xml index f9813ed0d0..427a52abf2 100644 --- a/java/bom/pom.xml +++ b/java/bom/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-bom - 4.36.0 + 4.36.0-RC2 pom Protocol Buffers [BOM] diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel index f167846b8e..0502c5489f 100644 --- a/java/core/BUILD.bazel +++ b/java/core/BUILD.bazel @@ -192,7 +192,7 @@ proto_library( "//:__pkg__", "//editions:__pkg__", "//java/__subpackages__", - "//pkg:__pkg__", + "//src/google/protobuf:__pkg__", ], deps = ["//:descriptor_proto"], ) @@ -210,8 +210,8 @@ filegroup( name = "java_features_proto_srcs", srcs = ["src/main/resources/google/protobuf/java_features.proto"], visibility = [ - "//pkg:__pkg__", "//python:__pkg__", + "//src/google/protobuf:__pkg__", ], ) diff --git a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java index d688f3a50e..c49f229c5e 100644 --- a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java +++ b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java @@ -30,7 +30,7 @@ public final class RuntimeVersion { public static final int OSS_MAJOR = 4; public static final int OSS_MINOR = 36; public static final int OSS_PATCH = 0; - public static final String OSS_SUFFIX = "-dev"; + public static final String OSS_SUFFIX = "-rc2"; public static final RuntimeDomain DOMAIN = OSS_DOMAIN; public static final int MAJOR = OSS_MAJOR; diff --git a/java/kotlin/pom.xml b/java/kotlin/pom.xml index 0dc1bc0496..263a7cf801 100644 --- a/java/kotlin/pom.xml +++ b/java/kotlin/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 4.36.0 + 4.36.0-RC2 protobuf-kotlin diff --git a/java/pom.xml b/java/pom.xml index 8b714a8b14..c293bfce9c 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 4.36.0 + 4.36.0-RC2 pom Protocol Buffers [Parent] diff --git a/java/protoc/pom.xml b/java/protoc/pom.xml index 5d2050f599..510bf80a67 100644 --- a/java/protoc/pom.xml +++ b/java/protoc/pom.xml @@ -8,7 +8,7 @@ com.google.protobuf protoc - 4.36.0 + 4.36.0-RC2 pom Protobuf Compiler diff --git a/java/util/BUILD.bazel b/java/util/BUILD.bazel index d633579b26..d2d5c0108f 100644 --- a/java/util/BUILD.bazel +++ b/java/util/BUILD.bazel @@ -1,16 +1,26 @@ load("@rules_java//java:java_library.bzl", "java_library") -load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") +load("//:protobuf.bzl", "internal_gen_well_known_protos_java") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") load("//bazel:java_proto_library.bzl", "java_proto_library") load("//bazel:proto_library.bzl", "proto_library") load("//build_defs:java_opts.bzl", "protobuf_java_export", "protobuf_versioned_java_library") load("//java/internal:testing.bzl", "junit_tests") +internal_gen_well_known_protos_java( + name = "gen_language_neutral_protos_java", + deps = [ + "//:json_enumvalue_options_proto", + "//:json_options_proto", + ], +) + java_library( name = "util", srcs = glob([ "src/main/java/com/google/protobuf/util/*.java", - ]), + ]) + [ + ":gen_language_neutral_protos_java", + ], visibility = ["//visibility:public"], deps = [ "//java/core", @@ -24,7 +34,9 @@ protobuf_versioned_java_library( name = "util_bundle", srcs = glob([ "src/main/java/com/google/protobuf/util/*.java", - ]), + ]) + [ + ":gen_language_neutral_protos_java", + ], automatic_module_name = "com.google.protobuf.util", bundle_description = "Utilities for Protocol Buffers", bundle_name = "Protocol Buffers [Util]", @@ -44,6 +56,9 @@ protobuf_java_export( deploy_env = ["//java/core"], maven_coordinates = "com.google.protobuf:protobuf-java-util:%s" % PROTOBUF_JAVA_VERSION, pom_template = "pom_template.xml", + resources = [ + "//src/google/protobuf:json_options_proto_srcs", + ], tags = ["manual"], visibility = ["//java:__pkg__"], runtime_deps = [":util_bundle"], @@ -63,6 +78,9 @@ filegroup( proto_library( name = "test_protos", srcs = glob(["src/test/proto/**/*.proto"]), + option_deps = [ + "//:json_options_proto", + ], deps = [ "//:any_proto", "//:duration_proto", @@ -78,6 +96,12 @@ java_proto_library( deps = [":test_protos"], ) +java_proto_library( + name = "json_enumvalue_options_java_proto", + visibility = ["//visibility:public"], + deps = ["//:json_enumvalue_options_proto"], +) + junit_tests( name = "tests", package_name = "com.google.protobuf.util", diff --git a/java/util/generate-sources-build.xml b/java/util/generate-sources-build.xml new file mode 100644 index 0000000000..c19809db70 --- /dev/null +++ b/java/util/generate-sources-build.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index d56371b559..89c49f2788 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -1546,7 +1546,14 @@ public class JsonFormat { if (printingEnumsAsInts || ((EnumValueDescriptor) value).getIndex() == -1) { generator.print(String.valueOf(((EnumValueDescriptor) value).getNumber())); } else { - generator.print("\"" + ((EnumValueDescriptor) value).getName() + "\""); + EnumValueDescriptor enumValue = (EnumValueDescriptor) value; + JsonEnumValueOptions ext = + enumValue.getOptions().getExtension(JsonEnumvalueOptionsProto.json); + if (ext.hasString()) { + printStringEscapedAndQuoted(ext.getString()); + } else { + generator.print("\"" + enumValue.getName() + "\""); + } } } break; @@ -1649,6 +1656,8 @@ public class JsonFormat { private final int recursionLimit; private final boolean legacyLenient; private int currentDepth; + private final Map enumJsonNamesCache = + new HashMap<>(); ParserImpl( com.google.protobuf.TypeRegistry registry, @@ -2428,31 +2437,56 @@ public class JsonFormat { @Nullable private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement json) throws InvalidProtocolBufferException { - String value = json.getAsString(); - EnumValueDescriptor result = enumDescriptor.findValueByName(value); - if (result == null) { - // Try to interpret the value as a number. - try { - int numericValue = parseInt32(json); - if (enumDescriptor.isClosed()) { - result = enumDescriptor.findValueByNumber(numericValue); - } else { - result = enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue); - } - } catch (InvalidProtocolBufferException e) { - // Fall through. This exception is about invalid int32 value we get from parseInt32() but - // that's not the exception we want the user to see. Since result == null, we will throw - // an exception later. - } + // Calling json.getAsString() works for both JsonPrimitive and single-element JsonArray (e.g., + // ["FOO"] or [2]), throwing UnsupportedOperationException/IllegalStateException for other + // structures. + final String name; + try { + name = json.getAsString(); + } catch (UnsupportedOperationException | IllegalStateException e) { + // UnsupportedOperationException is thrown by Gson when getAsString() is called on a + // JsonObject (e.g., "{}") or JsonNull (e.g., "null"). IllegalStateException is thrown when + // getAsString() is called on a JsonArray whose length is not exactly 1 (e.g., "[]" or + // '["FOO", "BAR"]'). + throw new InvalidProtocolBufferException( + "Invalid enum value: " + json + " for enum type: " + enumDescriptor.getFullName(), e); + } - // todo(elharo): if we are ignoring unknown fields, shouldn't we still - // throw InvalidProtocolBufferException for a non-numeric value here? - if (result == null && !ignoringUnknownFields) { - throw new InvalidProtocolBufferException( - "Invalid enum value: " + value + " for enum type: " + enumDescriptor.getFullName()); + EnumValueDescriptor result = enumDescriptor.findValueByName(name); + if (result != null) { + return result; + } + + // Custom JSON string lookup is restricted strictly to string primitives, explicitly + // rejecting single-element arrays of custom names (e.g., ["custom_enum_name"]). + if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) { + AlternativeEnumJsonNames enumJsonNames = + enumJsonNamesCache.computeIfAbsent(enumDescriptor, AlternativeEnumJsonNames::new); + result = enumJsonNames.map.get(name); + if (result != null) { + return result; } } - return result; + try { + int numericValue = parseInt32(json); + result = + enumDescriptor.isClosed() + ? enumDescriptor.findValueByNumber(numericValue) + : enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue); + if (result != null) { + return result; + } + } catch (InvalidProtocolBufferException e) { + // Fall through when json is not a valid int32 value (e.g., when json is a string like + // "XXX" or boolean true). + } + // todo(elharo): if we are ignoring unknown fields, shouldn't we still + // throw InvalidProtocolBufferException for a non-numeric value here? + if (!ignoringUnknownFields) { + throw new InvalidProtocolBufferException( + "Invalid enum value: " + json + " for enum type: " + enumDescriptor.getFullName()); + } + return null; } @SuppressWarnings("AvoidValueSetter") @@ -2533,5 +2567,20 @@ public class JsonFormat { throw new InvalidProtocolBufferException("Invalid field type: " + field.getType()); } } + + private static final class AlternativeEnumJsonNames { + final Map map; + + AlternativeEnumJsonNames(EnumDescriptor enumDescriptor) { + Map m = new HashMap<>(); + for (EnumValueDescriptor ev : enumDescriptor.getValues()) { + JsonEnumValueOptions ext = ev.getOptions().getExtension(JsonEnumvalueOptionsProto.json); + if (ext.hasString()) { + m.put(ext.getString(), ev); + } + } + this.map = Collections.unmodifiableMap(m); + } + } } } diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java index 86a13419f7..dc9b3de92b 100644 --- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java @@ -38,6 +38,8 @@ import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; import com.google.protobuf.util.JsonFormat.TypeRegistry; +import com.google.protobuf.util.proto.Armor; +import com.google.protobuf.util.proto.Helmet; import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes; import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.AliasedEnum; import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedEnum; @@ -54,6 +56,7 @@ import com.google.protobuf.util.proto.JsonTestProto.TestTimestamp; import com.google.protobuf.util.proto.JsonTestProto.TestWrappers; import com.google.protobuf.util.proto.JsonTestProto2; import com.google.protobuf.util.proto.JsonTestProto2.TestAllTypesProto2; +import com.google.protobuf.util.proto.Knight; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -2714,4 +2717,207 @@ public class JsonFormatTest { assertThat(builder.getInt32ToStringMapMap()).containsEntry(3, "baz"); assertThat(builder.getInt32ToStringMapMap()).hasSize(3); } + + @Test + public void gorgetDefaultSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_GORGET).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_GORGET); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"ARMOR_GORGET\"}"); + } + + @Test + public void greatHelmSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_GREAT_HELM).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_GREAT_HELM); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"gr8 helm\"}"); + } + + @Test + public void gauntletSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_GAUNTLET).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_GAUNTLET); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"a\\\"b\"}"); + } + + @Test + public void doubleQuoteEnumSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_PLATE).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_PLATE); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"\\\"plate\\\"\"}"); + } + + @Test + public void coifEmptySerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_COIF).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_COIF); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"\"}"); + } + + @Test + public void helmetEmptyOptionSerialization() throws Exception { + Knight msg = Knight.newBuilder().setHelmet(Helmet.HELMET_GOBLIN).build(); + assertThat(msg.getHelmet()).isEqualTo(Helmet.HELMET_GOBLIN); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"helmet\":\"HELMET_GOBLIN\"}"); + } + + @Test + public void pauldronEscapingSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_PAULDRON).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_PAULDRON); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"p\\taul\\ndron\"}"); + } + + @Test + public void hachiMaiDoSerialization() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_HACHI_MAI_DO).build(); + assertThat(msg.getArmor()).isEqualTo(Armor.ARMOR_HACHI_MAI_DO); + + String jsonRes = JsonFormat.printer().omittingInsignificantWhitespace().print(msg); + + assertThat(jsonRes).isEqualTo("{\"armor\":\"8\"}"); + } + + @Test + public void greatHelmIntOverride() throws Exception { + Knight msg = Knight.newBuilder().setArmor(Armor.ARMOR_GREAT_HELM).build(); + + String jsonRes = + JsonFormat.printer().omittingInsignificantWhitespace().printingEnumsAsInts().print(msg); + + // Integer overrides always win. + assertThat(jsonRes).isEqualTo("{\"armor\":1}"); + } + + // --- Parser Tests --- + + @Test + public void greatHelmParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"gr8 helm\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_GREAT_HELM); + } + + @Test + public void greatHelmRawNameParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"ARMOR_GREAT_HELM\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_GREAT_HELM); + } + + @Test + public void gauntletParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"a\\\"b\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_GAUNTLET); + } + + @Test + public void doubleQuoteEnumParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"\\\"plate\\\"\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_PLATE); + } + + @Test + public void coifEmptyParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_COIF); + } + + @Test + public void helmetEmptyOptionParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"helmet\":\"HELMET_GOBLIN\"}", builder); + assertThat(builder.getHelmet()).isEqualTo(Helmet.HELMET_GOBLIN); + } + + @Test + public void helmetEmptyStringParsingFails() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + assertThrows( + InvalidProtocolBufferException.class, + () -> JsonFormat.parser().merge("{\"helmet\":\"\"}", builder)); + } + + @Test + public void pauldronEscapingParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"p\\taul\\ndron\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_PAULDRON); + } + + @Test + public void hachiMaiDoParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"8\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_HACHI_MAI_DO); + } + + @Test + public void hachiMaiDoIntParsing() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":8}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_HACHI_MAI_DO); + } + + @Test + public void parseCustomStringTrue() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + JsonFormat.parser().merge("{\"armor\":\"true\"}", builder); + assertThat(builder.getArmor()).isEqualTo(Armor.ARMOR_SHIELD); + } + + @Test + public void parseCustomStringSingleElementArrayFails() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + assertThrows( + InvalidProtocolBufferException.class, + () -> JsonFormat.parser().merge("{\"armor\":[\"gr8 helm\"]}", builder)); + } + + @Test + public void parseCustomStringTrueAsBooleanFails() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + assertThrows( + InvalidProtocolBufferException.class, + () -> JsonFormat.parser().merge("{\"armor\":true}", builder)); + } + + @Test + public void caseInsensitiveGauntletParsingFails() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + assertThrows( + InvalidProtocolBufferException.class, + () -> JsonFormat.parser().merge("{\"armor\":\"A\\\"b\"}", builder)); + } + + @Test + public void caseInsensitiveGauntletRawNameParsingFails() throws Exception { + Knight.Builder builder = Knight.newBuilder(); + assertThrows( + InvalidProtocolBufferException.class, + () -> JsonFormat.parser().merge("{\"armor\":\"armor_GAUNtlet\"}", builder)); + } } diff --git a/java/util/src/test/proto/com/google/protobuf/util/json_test_custom_enum_string.proto b/java/util/src/test/proto/com/google/protobuf/util/json_test_custom_enum_string.proto new file mode 100644 index 0000000000..8229b28cc8 --- /dev/null +++ b/java/util/src/test/proto/com/google/protobuf/util/json_test_custom_enum_string.proto @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2026 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +// Tests custom JSON string representation for enum values +// ((pb.enumvalue.json).string). +edition = "2026"; + +package com.google.protobuf.util.json_test_custom_enum_string; + +import option "google/protobuf/json_options.proto"; + +option java_package = "com.google.protobuf.util.proto"; + +enum Armor { + ARMOR_UNKNOWN = 0; + ARMOR_GREAT_HELM = 1 [(pb.enumvalue.json).string = "gr8 helm"]; + ARMOR_GORGET = 2; + ARMOR_GAUNTLET = 3 [(pb.enumvalue.json).string = "a\"b"]; + ARMOR_PLATE = 4 [(pb.enumvalue.json).string = "\"plate\""]; + ARMOR_COIF = 5 [(pb.enumvalue.json).string = ""]; + ARMOR_PAULDRON = 6 [(pb.enumvalue.json).string = "p\taul\ndron"]; + ARMOR_SHIELD = 7 [(pb.enumvalue.json).string = "true"]; + ARMOR_HACHI_MAI_DO = 8 [(pb.enumvalue.json).string = "8"]; +} + +enum Helmet { + HELMET_UNKNOWN = 0; + HELMET_GOBLIN = 1 [(pb.enumvalue.json) = {}]; +} + +message Knight { + Armor armor = 1; + Helmet helmet = 2; +} diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index 60c98d276e..be8a4f658c 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -38,6 +38,13 @@ #define UPB_GNUC_MIN(x, y) 0 #endif +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define UPB_CLANG_MIN(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define UPB_CLANG_MIN(x, y) 0 +#endif + // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. @@ -602,10 +609,12 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name; \ - extern type __stop_linkarr_##name; \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name; \ + extern type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -616,13 +625,15 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name __asm( \ - "section$start$__DATA$__la_" #name); \ - extern type __stop_linkarr_##name __asm( \ - "section$end$__DATA$" \ - "__la_" #name); \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -660,7 +671,9 @@ Error, UINTPTR_MAX is undefined // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) -#define UPB_LINKARR_DECLARE(name, type) +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) @@ -677,11 +690,46 @@ Error, UINTPTR_MAX is undefined #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif -#if defined(__ELF__) || defined(__wasm__) || defined(__MACH__) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define _UPB_STRINGIFY2(x) #x +#define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) + +#if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) +/* + * Workaround for b/456308964 and b/456317163. Although weak constructors + * resolve to a single function body, Clang still emits a pointer into + * .init_array for every translation unit, causing the constructor to be + * executed multiple times and inflating binary size. We wrap the .init_array + * entry in a COMDAT group (using inline assembly) to force the linker to + * deduplicate the pointer to exactly one instance. %cc is used in preference to + * the more widely available %c because %c may under some circumstances still + * output a function name including relocation information, which will then + * confuse the linker. This was only a problem on gcc; when %cc was introduced + * to clang it was just an alias to %c, and clang's %c had already done the + * checks that %cc introduced to gcc. + * References: + * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa + * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 + */ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ + __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ + void) { \ + __asm__ volatile( \ + ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ + ".dc.a %cc0\n" \ + ".popsection\n" \ + : \ + : "X"(UPB_PRIVATE(name))); \ + __VA_ARGS__ \ + } +#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ + defined(__MINGW32__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ - name)(void) + name)(void) { \ + __VA_ARGS__ \ + } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 @@ -692,17 +740,22 @@ Error, UINTPTR_MAX is undefined * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ - static void __cdecl UPB_PRIVATE(name)(void) - + static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. -#define UPB_CONSTRUCTOR(name, unique_name) static void UPB_PRIVATE(name)(void) +#if defined(__GNUC__) || defined(__clang__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#else +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#endif #endif // @@ -740,9 +793,9 @@ Error, UINTPTR_MAX is undefined #elif defined(__ELF__) || defined(__wasm__) -// On ELF, weak aliases work properly, so we can have all weak MiniTables point -// to the same empty singleton MiniTable. This reduces code size if many -// MiniTables are tree shaken. + // On ELF, weak aliases work properly, so we can have all weak MiniTables + // point to the same empty singleton MiniTable. This reduces code size if many + // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ @@ -2389,7 +2442,7 @@ const upb_MiniTableEnum google__protobuf__SymbolVisibility_enum_init = { }, }; -static const upb_MiniTable *messages_layout[35] = { +static const upb_MiniTable *messages_layout_google_protobuf_descriptor_proto_upb_file_layout[35] = { &google__protobuf__FileDescriptorSet_msg_init, &google__protobuf__FileDescriptorProto_msg_init, &google__protobuf__DescriptorProto_msg_init, @@ -2427,7 +2480,7 @@ static const upb_MiniTable *messages_layout[35] = { &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, }; -static const upb_MiniTableEnum *enums_layout[21] = { +static const upb_MiniTableEnum *enums_layout_google_protobuf_descriptor_proto_upb_file_layout[21] = { &google__protobuf__Edition_enum_init, &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init, &google__protobuf__FeatureSet__EnforceNamingStyle_enum_init, @@ -2452,8 +2505,8 @@ static const upb_MiniTableEnum *enums_layout[21] = { }; const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { - messages_layout, - enums_layout, + messages_layout_google_protobuf_descriptor_proto_upb_file_layout, + enums_layout_google_protobuf_descriptor_proto_upb_file_layout, NULL, 35, 21, @@ -2471,7 +2524,7 @@ const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { -static const char descriptor[14056] = { +static const char descriptor_google_protobuf_descriptor_proto_upbdefinit[14056] = { '\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', @@ -3646,15 +3699,142 @@ static const char descriptor[14056] = { 't', 'i', 'o', 'n', }; -static _upb_DefPool_Init *deps[1] = { +static _upb_DefPool_Init* deps_google_protobuf_descriptor_proto_upbdefinit[1] = { NULL, }; _upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = { - deps, + deps_google_protobuf_descriptor_proto_upbdefinit, &google_protobuf_descriptor_proto_upb_file_layout, "google/protobuf/descriptor.proto", - UPB_STRINGVIEW_INIT(descriptor, sizeof(descriptor)), + UPB_STRINGVIEW_INIT(descriptor_google_protobuf_descriptor_proto_upbdefinit, + sizeof(descriptor_google_protobuf_descriptor_proto_upbdefinit)), +}; + +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#include + +// Must be last. + +extern const UPB_PRIVATE(upb_GeneratedExtensionListEntry)* UPB_PRIVATE(upb_generated_extension_list); +typedef struct { + upb_MiniTableField fields[1]; +} pb__enumvalue__JsonEnumValueOptions_msg_init_Fields; + +static const pb__enumvalue__JsonEnumValueOptions_msg_init_Fields pb_enumvalue_JsonEnumValueOptions__fields = {{ + {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}}; + +const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init = { + &pb_enumvalue_JsonEnumValueOptions__fields.fields[0], + UPB_SIZE(24, 32), 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "pb.enumvalue.JsonEnumValueOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeUnknown}, + {0x001000000000000a, &upb_DecodeFast_String_Scalar_Tag1Byte}, + }) +}; + +static const upb_MiniTableExtension pb_enumvalue_json_ext_obj = { + {998, 0, 0, UPB_SIZE(3, 4), 11, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsExtension | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {.UPB_PRIVATE(submsg) = &pb__enumvalue__JsonEnumValueOptions_msg_init}, + &google__protobuf__EnumValueOptions_msg_init, + +}; +UPB_LINKARR_APPEND(upb_AllExts) +const upb_MiniTableExtension* pb_enumvalue_json_ext = &pb_enumvalue_json_ext_obj; + static const upb_MiniTable *messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb__enumvalue__JsonEnumValueOptions_msg_init, +}; + + +static const upb_MiniTableExtension *extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb_enumvalue_json_ext_obj, +}; + +UPB_LINKARR_DECLARE(upb_AllExts, const upb_MiniTableExtension*); +UPB_CONSTRUCTOR(upb_GeneratedRegistry_Constructor, google_protobuf_json_enumvalue_options_proto_ext_constructor, { + static bool finished = false; + if (finished) return; + finished = true; + static UPB_PRIVATE(upb_GeneratedExtensionListEntry) entry = { + UPB_LINKARR_START(upb_AllExts), + UPB_LINKARR_STOP(upb_AllExts), + NULL + }; + UPB_ASSERT(entry.next == NULL); + entry.next = UPB_PRIVATE(upb_generated_extension_list); + UPB_PRIVATE(upb_generated_extension_list) = &entry; +}) +const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout = { + messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + NULL, + extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + 1, + 0, + 1, +}; + + +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + + + +extern _upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit; + +static const char descriptor_google_protobuf_json_enumvalue_options_proto_upbdefinit[285] = { + '\n', ',', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', + 't', 'o', 'b', 'u', 'f', '/', 'j', 's', 'o', 'n', '_', 'e', + 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', '_', 'o', 'p', 't', + 'i', 'o', 'n', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\014', + 'p', 'b', '.', 'e', 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', + '\032', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', + 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', + 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\"', '0', + '\n', '\024', 'J', 's', 'o', 'n', 'E', 'n', 'u', 'm', 'V', 'a', + 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\026', + '\n', '\006', 's', 't', 'r', 'i', 'n', 'g', '\030', '\001', ' ', '\001', + '(', '\t', 'R', '\006', 's', 't', 'r', 'i', 'n', 'g', 'X', '\001', + ':', 'b', '\n', '\004', 'j', 's', 'o', 'n', '\022', '!', '.', 'g', + 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', + 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', + 'O', 'p', 't', 'i', 'o', 'n', 's', '\030', '\346', '\007', ' ', '\001', + '(', '\013', '2', '\"', '.', 'p', 'b', '.', 'e', 'n', 'u', 'm', + 'v', 'a', 'l', 'u', 'e', '.', 'J', 's', 'o', 'n', 'E', 'n', + 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', + 'n', 's', 'B', '\006', '\262', '\001', '\003', '\010', '\352', '\007', 'R', '\004', + 'j', 's', 'o', 'n', 'B', '\032', '\n', '\030', 'c', 'o', 'm', '.', + 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', + 'b', 'u', 'f', '.', 'u', 't', 'i', 'l', 'b', '\010', 'e', 'd', + 'i', 't', 'i', 'o', 'n', 's', 'p', '\351', '\007', +}; + +static _upb_DefPool_Init* deps_google_protobuf_json_enumvalue_options_proto_upbdefinit[2] = { + &google_protobuf_descriptor_proto_upbdefinit, + NULL, +}; + +_upb_DefPool_Init google_protobuf_json_enumvalue_options_proto_upbdefinit = { + deps_google_protobuf_json_enumvalue_options_proto_upbdefinit, + &google_protobuf_json_enumvalue_options_proto_upb_file_layout, + "google/protobuf/json_enumvalue_options.proto", + UPB_STRINGVIEW_INIT(descriptor_google_protobuf_json_enumvalue_options_proto_upbdefinit, + sizeof(descriptor_google_protobuf_json_enumvalue_options_proto_upbdefinit)), }; @@ -5403,7 +5583,7 @@ static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { upb_StringView str = jsondec_string(d); const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); const upb_EnumValueDef* ev = - upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); + upb_EnumDef_FindByJsonNameWithSize(e, str.data, str.size); upb_JsonMessageValue val = {.ignore = false}; if (ev) { val.value.int32_val = upb_EnumValueDef_Number(ev); @@ -6181,11 +6361,12 @@ int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, } -#include #include #include #include +#include #include +#include #include @@ -6212,6 +6393,7 @@ static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m, bool first); static void jsonenc_value(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m); +static void jsonenc_string(jsonenc* e, upb_StringView str); UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { upb_Status_SetErrorMessage(e->status, msg); @@ -6373,7 +6555,8 @@ static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { : upb_EnumDef_FindValueByNumber(e_def, val); if (ev) { - jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); + const char* name = upb_EnumValueDef_JsonName(ev); + jsonenc_string(e, upb_StringView_FromString(name)); } else { jsonenc_printf(e, "%" PRId32, val); } @@ -12710,6 +12893,28 @@ struct upb_EnumDef { bool is_sorted; // Whether all of the values are defined in ascending order. }; +// We store both regular proto enum names and custom JSON enum names in the +// same strtable (ntoi). This is safe because protoc enforces that custom JSON +// enum names never conflict with default enum names across different enum +// values (or are identical, in which case we leave the entry untagged). Because +// upb_EnumValueDef pointers are arena-aligned to at least 4 bytes (bit 0 is +// always 0 for untagged pointers), we set bit 0 to tag custom JSON-only names +// so that regular name lookups can ignore them. +static const uintptr_t kUpb_EnumDef_JsonOnlyTag = 1ULL; + +static upb_value _upb_EnumDef_TagJsonOnly(upb_value v) { + v.val |= kUpb_EnumDef_JsonOnlyTag; + return v; +} + +static bool _upb_EnumDef_IsJsonOnly(upb_value v) { + return (v.val & kUpb_EnumDef_JsonOnlyTag) != 0; +} + +static const upb_EnumValueDef* _upb_EnumDef_Untag(upb_value v) { + return (const upb_EnumValueDef*)(v.val & ~kUpb_EnumDef_JsonOnlyTag); +} + upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) { return (upb_EnumDef*)&e[i]; } @@ -12718,18 +12923,43 @@ const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) { return e->layout; } -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) { +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v) { const char* name = upb_EnumValueDef_Name(v); const upb_value val = upb_value_constptr(v); - bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a); - if (!ok) return false; + bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, ctx->arena); + if (!ok) _upb_DefBuilder_OomErr(ctx); - // Multiple enumerators can have the same number, first one wins. + // Aliased enum values can share the same custom JSON name, first one wins. + const char* json_name = upb_EnumValueDef_JsonName(v); + size_t json_len = strlen(json_name); + if (strcmp(json_name, name) != 0) { + upb_value existing_value; + if (upb_strtable_lookup2(&e->ntoi, json_name, json_len, &existing_value)) { + const upb_EnumValueDef* enumval = _upb_EnumDef_Untag(existing_value); + if (upb_EnumValueDef_Number(enumval) != upb_EnumValueDef_Number(v)) { + // If the custom JSON name exists, but points to a value with a + // different number, then this is a parse/conflict error. + _upb_DefBuilder_Errf(ctx, + "duplicate custom json_name (%s) in enum (%s)", + json_name, upb_EnumDef_FullName(e)); + } + } else { + upb_value json_val = _upb_EnumDef_TagJsonOnly(val); + if (!upb_strtable_insert(&e->ntoi, json_name, json_len, json_val, + ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } + } + } + + // Multiple enum values can have the same number, first one wins. const int number = upb_EnumValueDef_Number(v); if (!upb_inttable_lookup(&e->iton, number, NULL)) { - return upb_inttable_insert(&e->iton, number, val, a); + if (!upb_inttable_insert(&e->iton, number, val, ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } } - return true; } const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) { @@ -12786,6 +13016,16 @@ upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) { int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; } +const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize(const upb_EnumDef* e, + const char* name, + size_t size) { + upb_value v; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + return _upb_EnumDef_Untag(v); +} + const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name) { return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name)); @@ -12794,9 +13034,13 @@ const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( const upb_EnumDef* e, const char* name, size_t size) { upb_value v; - return upb_strtable_lookup2(&e->ntoi, name, size, &v) - ? upb_value_getconstptr(v) - : NULL; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + if (_upb_EnumDef_IsJsonOnly(v)) { + return NULL; + } + return upb_value_getconstptr(v); } const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e, @@ -12937,7 +13181,7 @@ static void create_enumdef(upb_DefBuilder* ctx, const char* prefix, upb_EnumDef_FullName(e)); } - bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena); + bool ok = upb_strtable_init(&e->ntoi, n_value * 2, ctx->arena); if (!ok) _upb_DefBuilder_OomErr(ctx); ok = upb_inttable_init(&e->iton, ctx->arena); @@ -13054,6 +13298,7 @@ struct upb_EnumValueDef { const google_protobuf_FeatureSet* resolved_features; const upb_EnumDef* parent; const char* full_name; + const char* json_name; int32_t number; }; @@ -13075,7 +13320,7 @@ const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v, (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*)); if (!out) return NULL; - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { out[i] = (upb_EnumValueDef*)&v[i]; } qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare); @@ -13105,6 +13350,10 @@ const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) { return v->full_name; } +const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v) { + return v->json_name ? v->json_name : upb_EnumValueDef_Name(v); +} + const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) { return _upb_DefBuilder_FullToShort(v->full_name); } @@ -13116,6 +13365,19 @@ uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) { return v - upb_EnumDef_Value(v->parent, 0); } +static const char* _upb_EnumValueDef_ExtractJsonName( + upb_DefBuilder* ctx, const upb_EnumValueDef* v) { + if (!upb_EnumValueDef_HasOptions(v)) return NULL; + const google_protobuf_EnumValueOptions* opts = (const google_protobuf_EnumValueOptions*)v->opts; + if (!pb_enumvalue_has_json(opts)) return NULL; + const pb_enumvalue_JsonEnumValueOptions* json_opts = pb_enumvalue_json(opts); + if (!json_opts || !pb_enumvalue_JsonEnumValueOptions_has_string(json_opts)) { + return NULL; + } + upb_StringView str = pb_enumvalue_JsonEnumValueOptions_string(json_opts); + return upb_strdup2(str.data, str.size, ctx->arena); +} + static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, const google_protobuf_EnumValueDescriptorProto* val_proto, const google_protobuf_FeatureSet* parent_features, @@ -13130,11 +13392,11 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, v->parent = e; // Must happen prior to _upb_DefBuilder_Add() v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name); v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto); + v->json_name = _upb_EnumValueDef_ExtractJsonName(ctx, v); _upb_DefBuilder_Add(ctx, v->full_name, _upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL)); - bool ok = _upb_EnumDef_Insert(e, v, ctx->arena); - if (!ok) _upb_DefBuilder_OomErr(ctx); + _upb_EnumDef_Insert(ctx, e, v); } // Allocate and initialize an array of |n| enum value defs owned by |e|. @@ -19094,6 +19356,7 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( #undef UPB_TSAN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN +#undef UPB_CLANG_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME #undef UPB_DESC_MINITABLE #undef UPB_IS_GOOGLE3 @@ -19120,3 +19383,6 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( #undef UPB_DEPRECATE_AND_INLINE #undef UPB_MAYBE_ASSUME #undef UPB_ATTR_CONST +#undef _UPB_STRINGIFY +#undef _UPB_STRINGIFY2 +#undef UPB_CONSTRUCTOR diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index dd943a7f14..f431b86a71 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -37,6 +37,13 @@ #define UPB_GNUC_MIN(x, y) 0 #endif +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define UPB_CLANG_MIN(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define UPB_CLANG_MIN(x, y) 0 +#endif + // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. @@ -601,10 +608,12 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name; \ - extern type __stop_linkarr_##name; \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name; \ + extern type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -615,13 +624,15 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name __asm( \ - "section$start$__DATA$__la_" #name); \ - extern type __stop_linkarr_##name __asm( \ - "section$end$__DATA$" \ - "__la_" #name); \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -659,7 +670,9 @@ Error, UINTPTR_MAX is undefined // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) -#define UPB_LINKARR_DECLARE(name, type) +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) @@ -676,11 +689,46 @@ Error, UINTPTR_MAX is undefined #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif -#if defined(__ELF__) || defined(__wasm__) || defined(__MACH__) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define _UPB_STRINGIFY2(x) #x +#define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) + +#if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) +/* + * Workaround for b/456308964 and b/456317163. Although weak constructors + * resolve to a single function body, Clang still emits a pointer into + * .init_array for every translation unit, causing the constructor to be + * executed multiple times and inflating binary size. We wrap the .init_array + * entry in a COMDAT group (using inline assembly) to force the linker to + * deduplicate the pointer to exactly one instance. %cc is used in preference to + * the more widely available %c because %c may under some circumstances still + * output a function name including relocation information, which will then + * confuse the linker. This was only a problem on gcc; when %cc was introduced + * to clang it was just an alias to %c, and clang's %c had already done the + * checks that %cc introduced to gcc. + * References: + * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa + * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 + */ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ + __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ + void) { \ + __asm__ volatile( \ + ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ + ".dc.a %cc0\n" \ + ".popsection\n" \ + : \ + : "X"(UPB_PRIVATE(name))); \ + __VA_ARGS__ \ + } +#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ + defined(__MINGW32__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ - name)(void) + name)(void) { \ + __VA_ARGS__ \ + } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 @@ -691,17 +739,22 @@ Error, UINTPTR_MAX is undefined * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ - static void __cdecl UPB_PRIVATE(name)(void) - + static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. -#define UPB_CONSTRUCTOR(name, unique_name) static void UPB_PRIVATE(name)(void) +#if defined(__GNUC__) || defined(__clang__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#else +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#endif #endif // @@ -739,9 +792,9 @@ Error, UINTPTR_MAX is undefined #elif defined(__ELF__) || defined(__wasm__) -// On ELF, weak aliases work properly, so we can have all weak MiniTables point -// to the same empty singleton MiniTable. This reduces code size if many -// MiniTables are tree shaken. + // On ELF, weak aliases work properly, so we can have all weak MiniTables + // point to the same empty singleton MiniTable. This reduces code size if many + // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ @@ -14902,6 +14955,7 @@ bool upb_DefPool_ImplicitFieldPresenceDisabled(const upb_DefPool* s); #include #include +#include // Must be last. @@ -14914,6 +14968,12 @@ bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num); const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e); int32_t upb_EnumDef_Default(const upb_EnumDef* e); UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e); +UPB_API const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize( + const upb_EnumDef* e, const char* name, size_t size); +UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindByJsonName( + const upb_EnumDef* e, const char* name) { + return upb_EnumDef_FindByJsonNameWithSize(e, name, strlen(name)); +} const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name); UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( @@ -14956,6 +15016,8 @@ UPB_API int upb_EnumDef_ValueCount(const upb_EnumDef* e); #ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_ #define UPB_REFLECTION_ENUM_VALUE_DEF_H_ +#include + // Must be last. @@ -14967,6 +15029,7 @@ const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v); const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v); bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v); uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v); +UPB_API const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v); UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v); UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v); const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options( @@ -15651,6 +15714,68 @@ UPB_INLINE const upb_MessageDef *google_protobuf_GeneratedCodeInfo_Annotation_ge #endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPBDEFS_H_ */ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init; +extern const upb_MiniTableExtension* pb_enumvalue_json_ext; + +extern const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ */ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + + + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPBDEFS_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPBDEFS_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _upb_DefPool_Init google_protobuf_json_enumvalue_options_proto_upbdefinit; + +UPB_INLINE const upb_MessageDef *pb_enumvalue_JsonEnumValueOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_json_enumvalue_options_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "pb.enumvalue.JsonEnumValueOptions"); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPBDEFS_H_ */ #ifndef UPB_BASE_INTERNAL_LOG2_H_ #define UPB_BASE_INTERNAL_LOG2_H_ @@ -18285,7 +18410,8 @@ extern "C" { #endif upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i); -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a); +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v); const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e); // Allocate and initialize an array of |n| enum defs. @@ -18379,6 +18505,151 @@ char* upb_strdup2(const char* s, size_t len, upb_Arena* a); #endif /* UPB_REFLECTION_INTERNAL_STRDUP2_H_ */ +#ifndef GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ +#define GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ + +// IWYU pragma: begin_exports + +#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 +// This header is checked in. +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 1 +// This header is generated at build time by the bootstrapping process. +#else +// This is the normal header, generated by upb_c_proto_library(). +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct pb_enumvalue_JsonEnumValueOptions { + upb_Message UPB_PRIVATE(base); +} pb_enumvalue_JsonEnumValueOptions; + +struct google_protobuf_EnumValueOptions; + + + +/* pb.enumvalue.JsonEnumValueOptions */ +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_new(upb_Arena* arena) { + return (pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse(const char* buf, size_t size, + upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, NULL, 0, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse_ex( + const char* buf, size_t size, const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, extreg, + options, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize(const pb_enumvalue_JsonEnumValueOptions* msg, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize_ex(const pb_enumvalue_JsonEnumValueOptions* msg, + int options, upb_Arena* arena, + size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_clear_string(pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView pb_enumvalue_JsonEnumValueOptions_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool pb_enumvalue_JsonEnumValueOptions_has_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_set_string(pb_enumvalue_JsonEnumValueOptions* msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message*)msg, &field, &value); +} + +UPB_INLINE bool pb_enumvalue_has_json(const struct google_protobuf_EnumValueOptions* msg) { + return upb_Message_HasExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} + +UPB_INLINE void pb_enumvalue_clear_json(struct google_protobuf_EnumValueOptions* msg) { + upb_Message_ClearExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} +UPB_INLINE const pb_enumvalue_JsonEnumValueOptions* +pb_enumvalue_json(const struct google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + const pb_enumvalue_JsonEnumValueOptions* default_val = NULL; + const pb_enumvalue_JsonEnumValueOptions* ret; + _upb_Message_GetExtensionField((upb_Message*)msg, ext, &default_val, &ret); + return ret; +} + +UPB_INLINE void pb_enumvalue_set_json(struct google_protobuf_EnumValueOptions* msg, + const pb_enumvalue_JsonEnumValueOptions* val, + upb_Arena* arena) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + bool ok = upb_Message_SetExtension((upb_Message*)msg, ext, &val, arena); + UPB_ASSERT(ok); +} +UPB_INLINE struct pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_mutable_json( + struct google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct pb_enumvalue_JsonEnumValueOptions* sub = (struct pb_enumvalue_JsonEnumValueOptions*)pb_enumvalue_json(msg); + if (sub == NULL) { + sub = (struct pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); + if (sub) pb_enumvalue_set_json(msg, sub, arena); + } + return sub; +} +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ */ +#endif + +// IWYU pragma: end_exports + +#endif // GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ #ifndef UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ #define UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ @@ -19133,6 +19404,7 @@ UPB_PRIVATE(upb_WireWriter_VarintUnusedSizeFromLeadingZeros64)(uint64_t clz) { #undef UPB_TSAN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN +#undef UPB_CLANG_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME #undef UPB_DESC_MINITABLE #undef UPB_IS_GOOGLE3 @@ -19159,3 +19431,6 @@ UPB_PRIVATE(upb_WireWriter_VarintUnusedSizeFromLeadingZeros64)(uint64_t clz) { #undef UPB_DEPRECATE_AND_INLINE #undef UPB_MAYBE_ASSUME #undef UPB_ATTR_CONST +#undef _UPB_STRINGIFY +#undef _UPB_STRINGIFY2 +#undef UPB_CONSTRUCTOR diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index a9dc98677a..f86cfc14c0 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -22,7 +22,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() -#define PHP_PROTOBUF_VERSION "5.36.0" +#define PHP_PROTOBUF_VERSION "5.36.0RC2" // ptr -> PHP object cache. This is a weak map that caches lazily-created // wrapper objects around upb types: diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel index f698c5db5e..2ddb85425f 100644 --- a/pkg/BUILD.bazel +++ b/pkg/BUILD.bazel @@ -13,14 +13,9 @@ package_naming( ) pkg_files( - name = "wkt_protos_files", + name = "release_all_options_protos_files", srcs = [ - "//:well_known_type_protos", - "//csharp:c_sharp_features_proto_srcs", - "//go:go_features_proto_srcs", - "//java/core:java_features_proto_srcs", - "//src/google/protobuf:cpp_features_proto_srcs", - "//src/google/protobuf:descriptor_proto_srcs", + "//src/google/protobuf:release_all_options_proto_srcs", ], prefix = "include/google/protobuf", visibility = ["//visibility:private"], @@ -92,7 +87,7 @@ pkg_zip( ":compiler_plugin_protos_files", ":protoc_files", ":protoc_readme", - ":wkt_protos_files", + ":release_all_options_protos_files", ], package_file_name = "protoc-{version}-{platform}.zip", package_variables = ":protobuf_pkg_naming", @@ -118,16 +113,9 @@ gen_file_lists( ":protoc-gen-upbdefs": "protoc-gen-upbdefs", ":protoc-gen-upb_minitable": "protoc-gen-upb_minitable", # Protos: - "//src/google/protobuf:well_known_type_protos": "wkt_protos", - "//src/google/protobuf:cpp_file_options_proto": "cpp_file_options_proto", - "//src/google/protobuf:cpp_features_proto": "cpp_features_proto", "//src/google/protobuf:descriptor_proto": "descriptor_proto", - "//src/google/protobuf:json_enumvalue_options_proto": "json_enumvalue_options_proto", - "//src/google/protobuf:json_enumvalue_options_cc_proto": "json_enumvalue_options_cc_proto", "//src/google/protobuf/compiler:plugin_proto": "plugin_proto", - "//csharp:c_sharp_features_proto": "c_sharp_features_proto", - "//java/core:java_features_proto": "java_features_proto,src/google/protobuf/compiler/java/", - "//go:go_features_proto": "go_features_proto,go/", + "//src/google/protobuf:release_all_options_proto_srcs": "release_all_options_protos", # Test libraries: ":common_test": "common_test", diff --git a/protobuf_version.bzl b/protobuf_version.bzl index 042bcb7425..4c42b59d76 100644 --- a/protobuf_version.bzl +++ b/protobuf_version.bzl @@ -1,7 +1,7 @@ """ Contains version numbers to be used in other bzl files """ -PROTOC_VERSION = "36.0" -PROTOBUF_JAVA_VERSION = "4.36.0" -PROTOBUF_PYTHON_VERSION = "7.36.0" -PROTOBUF_PHP_VERSION = "5.36.0" -PROTOBUF_RUBY_VERSION = "4.36.0" -PROTOBUF_RUST_VERSION = "4.36.0" +PROTOC_VERSION = "36.0-rc-2" +PROTOBUF_JAVA_VERSION = "4.36.0-RC2" +PROTOBUF_PYTHON_VERSION = "7.36.0rc2" +PROTOBUF_PHP_VERSION = "5.36.0RC2" +PROTOBUF_RUBY_VERSION = "4.36.0.rc.2" +PROTOBUF_RUST_VERSION = "4.36.0-rc.2" diff --git a/python/descriptor.c b/python/descriptor.c index 3df441a3a8..251fdd2b6d 100644 --- a/python/descriptor.c +++ b/python/descriptor.c @@ -141,6 +141,8 @@ static PyObject* PyUpb_DescriptorBase_GetCached(PyObject** cached, #if PROTOBUF_PY_FUTURE_FREEZE_OPTIONS upb_Message_Freeze(opts2, opts2_layout); +#else + PyUpb_Arena_SetFrozen(py_arena, true); #endif *cached = PyUpb_Message_Get(opts2, m, py_arena); Py_DECREF(py_arena); diff --git a/python/descriptor_containers.c b/python/descriptor_containers.c index 1bfbc69bf6..fec0797f4e 100644 --- a/python/descriptor_containers.c +++ b/python/descriptor_containers.c @@ -39,6 +39,21 @@ typedef enum { kPyUpb_CompareNotImplemented, } PyUpb_CompareResult; +static PyUpb_CompareResult PyUpb_CompareUnrecognized(void) { +#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED + return kPyUpb_CompareNotImplemented; +#else + if (PyErr_WarnEx( + PyExc_FutureWarning, + "Comparing descriptor containers with unrecognized types will return " + "NotImplemented in 2027.", + 3) < 0) { + return kPyUpb_CompareError; + } + return kPyUpb_CompareNotEqual; +#endif +} + // ----------------------------------------------------------------------------- // ByNameIterator // ----------------------------------------------------------------------------- @@ -234,11 +249,7 @@ static PyUpb_CompareResult PyUpb_GenericSequence_IsEqual( } if (!PyList_Check(other)) { -#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED - return kPyUpb_CompareNotImplemented; -#else - return kPyUpb_CompareNotEqual; -#endif + return PyUpb_CompareUnrecognized(); } // return list(self) == other @@ -554,11 +565,7 @@ static PyUpb_CompareResult PyUpb_ByNameMap_IsEqual(PyUpb_ByNameMap* self, } if (!PyDict_Check(other)) { -#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED - return kPyUpb_CompareNotImplemented; -#else - return kPyUpb_CompareNotEqual; -#endif + return PyUpb_CompareUnrecognized(); } PyObject* self_dict = PyDict_New(); @@ -807,11 +814,7 @@ static PyUpb_CompareResult PyUpb_ByNumberMap_IsEqual(PyUpb_ByNumberMap* self, } if (!PyDict_Check(other)) { -#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED - return kPyUpb_CompareNotImplemented; -#else - return kPyUpb_CompareNotEqual; -#endif + return PyUpb_CompareUnrecognized(); } PyObject* self_dict = PyDict_New(); diff --git a/python/dist/BUILD.bazel b/python/dist/BUILD.bazel index 1292d74dff..a87dfc4c85 100644 --- a/python/dist/BUILD.bazel +++ b/python/dist/BUILD.bazel @@ -26,21 +26,9 @@ py_dist_module( ) py_proto_library( - name = "well_known_proto_py_pb2", + name = "language_neutral_protos_py_pb2", deps = [ - "//:any_proto", - "//:api_proto", - "//:descriptor_proto", - "//:duration_proto", - "//:empty_proto", - "//:field_mask_proto", - "//:json_enumvalue_options_proto", - "//:json_options_proto", - "//:source_context_proto", - "//:struct_proto", - "//:timestamp_proto", - "//:type_proto", - "//:wrappers_proto", + "//src/google/protobuf:language_neutral_protos", ], ) @@ -246,13 +234,17 @@ selects.config_setting_group( ) pkg_files( - name = "generated_wkt", + name = "generated_bootstrap", srcs = [ - ":well_known_proto_py_pb2", + ":language_neutral_protos_py_pb2", "//src/google/protobuf:descriptor_upb_c_proto", "//src/google/protobuf:descriptor_upb_minitable_proto", "//src/google/protobuf:descriptor_upb_reflection_proto", + "//src/google/protobuf:json_enumvalue_options_upb_c_proto", + "//src/google/protobuf:json_enumvalue_options_upb_minitable_proto", + "//src/google/protobuf:json_enumvalue_options_upb_reflection_proto", "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:json_enumvalue_options_upb_proto", ], prefix = "google/protobuf", ) @@ -311,7 +303,7 @@ pkg_tar( srcs = [ ":dist_source_files", ":filegroup_source_files", - ":generated_wkt", + ":generated_bootstrap", ":generated_wkt_compiler", ":utf8_range_source_files", "//python:python_source_files", @@ -405,9 +397,9 @@ py_wheel( }), version = PROTOBUF_PYTHON_VERSION, deps = [ + ":language_neutral_protos_py_pb2", ":message_mod", ":plugin_py_pb2", - ":well_known_proto_py_pb2", "//:python_srcs", ], ) @@ -445,8 +437,8 @@ py_wheel( }), version = PROTOBUF_PYTHON_VERSION, deps = [ + ":language_neutral_protos_py_pb2", ":plugin_py_pb2", - ":well_known_proto_py_pb2", "//:python_srcs", ], ) diff --git a/python/dist/py_proto_library.bzl b/python/dist/py_proto_library.bzl index 756ef6d2fb..46b00e6c41 100644 --- a/python/dist/py_proto_library.bzl +++ b/python/dist/py_proto_library.bzl @@ -105,7 +105,11 @@ def _py_proto_library_aspect_impl(target, ctx): [_get_real_short_path(file) for file in proto_sources], progress_message = "Generating Python protos for :" + ctx.label.name, ) - outs_depset = depset(srcs) + transitive_py_sources = [dep[PyInfo].transitive_sources for dep in ctx.rule.attr.deps if PyInfo in dep] if hasattr(ctx.rule.attr, "deps") else [] + outs_depset = depset( + direct = srcs, + transitive = transitive_py_sources, + ) return [ PyInfo(transitive_sources = outs_depset), ] diff --git a/python/extension_dict.c b/python/extension_dict.c index 4783ed70ae..01e13d5c6a 100644 --- a/python/extension_dict.c +++ b/python/extension_dict.c @@ -7,6 +7,7 @@ #include "python/extension_dict.h" +#include "google/protobuf/breaking_changes.h" #include "python/message.h" #include "python/protobuf.h" #include "upb/reflection/def.h" @@ -127,8 +128,9 @@ static int PyUpb_ExtensionDict_AssignSubscript(PyObject* _self, PyObject* key, const upb_FieldDef* f = PyUpb_Message_GetExtensionDef(self->msg, key); if (!f) return -1; if (PyUpb_Message_IsFrozen(self->msg)) { - PyUpb_SetFrozenError(); - return -1; + if (!PyUpb_CheckFrozen(true, "Message is immutable.")) { + return -1; + } } if (val) { return PyUpb_Message_SetFieldValue(self->msg, f, val, PyExc_TypeError); diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py index 1223991329..cf9393a255 100755 --- a/python/google/protobuf/__init__.py +++ b/python/google/protobuf/__init__.py @@ -7,4 +7,4 @@ # Copyright 2007 Google Inc. All Rights Reserved. -__version__ = '7.36.0' +__version__ = '7.36.0rc2' diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index 6bf19d8691..6cc81441d5 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -245,6 +245,12 @@ class DescriptorBase(metaclass=DescriptorMetaclass): # If either has been reset by gencode, reload options. if not self._options or not self._loaded_options: self._LazyLoadOptions() + if ( + self._options + and hasattr(self._options, '_SetFrozen') + and not getattr(self._options, '_frozen', False) + ): + self._options._SetFrozen() return self._options diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index ba4b7a1299..896faee3ab 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -19,6 +19,7 @@ are: import collections.abc import copy import pickle +import warnings from typing import ( Any, Iterable, @@ -42,6 +43,16 @@ from google.protobuf.descriptor import FieldDescriptor from google.protobuf import message +def _CheckFrozen(is_frozen: bool, msg: str) -> None: + if is_frozen: + warnings.warn( + 'Mutating messages or containers returned by GetOptions() is' + ' deprecated and will raise an exception in a future release.', + category=FutureWarning, + stacklevel=3, + ) + + class BaseContainer(Sequence[_T]): """Base container class.""" @@ -89,8 +100,7 @@ class BaseContainer(Sequence[_T]): self._frozen = True def _AssureWritable(self) -> 'BaseContainer[_T]': - if self._frozen: - raise message.FrozenInstanceError('Container is immutable') + _CheckFrozen(self._frozen, 'Container is immutable') return self def sort(self, *args, **kwargs) -> None: @@ -447,8 +457,7 @@ class ScalarMap(MutableMapping[_K, _V]): self._frozen = True def _AssureWritable(self) -> 'ScalarMap[_K, _V]': - if self._frozen: - raise message.FrozenInstanceError('Map is immutable') + _CheckFrozen(self._frozen, 'Map is immutable') return self def __getitem__(self, key: _K) -> _V: @@ -582,8 +591,7 @@ class MessageMap(MutableMapping[_K, _V]): val._SetFrozen() def _AssureWritable(self) -> 'MessageMap[_K, _V]': - if self._frozen: - raise message.FrozenInstanceError('Map is immutable') + _CheckFrozen(self._frozen, 'Map is immutable') return self def __getitem__(self, key: _K) -> _V: diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index 25f9d970ea..53bd94f9ea 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -1606,7 +1606,12 @@ def _SetFrozen(self): def _AssureWritable(self): if self._frozen: - raise message_mod.FrozenInstanceError('Message is immutable') + warnings.warn( + 'Mutating messages or containers returned by GetOptions() is' + ' deprecated and will raise an exception in a future release.', + category=FutureWarning, + stacklevel=3, + ) return self diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 2f3bc7c799..3d0125d08b 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -313,9 +313,7 @@ static PyObject* GetOrBuildMessageInDefaultPool( } } -#if PROTOBUF_PY_FUTURE_FREEZE_OPTIONS cmsg->state = MESSAGE_FROZEN; -#endif // Cache the result. { diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc index 8e7b7d662c..d1eb1129dc 100644 --- a/python/google/protobuf/pyext/descriptor_containers.cc +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -307,6 +307,21 @@ enum class CompareResult { kNotImplemented, }; +static CompareResult CompareUnrecognized() { +#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED + return CompareResult::kNotImplemented; +#else + if (PyErr_WarnEx( + PyExc_FutureWarning, + "Comparing descriptor containers with unrecognized types will return " + "NotImplemented in 2027.", + 3) < 0) { + return CompareResult::kError; + } + return CompareResult::kNotEqual; +#endif +} + // A sequence container can only be equal to another sequence container, or (for // backward compatibility) to a list containing the same items. static CompareResult DescriptorSequence_Equal(PyContainer* self, @@ -347,13 +362,7 @@ static CompareResult DescriptorSequence_Equal(PyContainer* self, return CompareResult::kEqual; } -#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED - // Any other object is not implemented. - return CompareResult::kNotImplemented; -#else - // Any other object is different. - return CompareResult::kNotEqual; -#endif + return CompareUnrecognized(); } // A mapping container can only be equal to another mapping container, or (for @@ -401,13 +410,7 @@ static CompareResult DescriptorMapping_Equal(PyContainer* self, return CompareResult::kEqual; } -#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED - // Any other object is not implemented. - return CompareResult::kNotImplemented; -#else - // Any other object is different. - return CompareResult::kNotEqual; -#endif + return CompareUnrecognized(); } static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) { diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index 61ea2c0a39..c998256424 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -29,6 +29,7 @@ #include "absl/log/absl_check.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" +#include "google/protobuf/breaking_changes.h" #include "google/protobuf/pyext/lazy_unique_ptr.h" #ifndef PyVarObject_HEAD_INIT @@ -494,6 +495,26 @@ PyObject* SetMessageFrozenError() { return SetFrozenError("Message is immutable."); } +int WarnMessageFrozen() { + return PyErr_WarnEx( + PyExc_FutureWarning, + "Mutating messages or containers returned by GetOptions() is deprecated" + " and will raise an exception in a future release.", + 3); +} + +int CheckFrozen(CMessage* parent, const char* error_msg) { + if (parent->state == MESSAGE_FROZEN) { +#if PROTOBUF_PY_FUTURE_FREEZE_OPTIONS + SetFrozenError(error_msg); + return -1; +#else + return WarnMessageFrozen(); +#endif + } + return 0; +} + // Format an error message for unexpected types. // Always return with an exception set. void FormatTypeError(PyObject* arg, const char* expected_types) { @@ -834,8 +855,10 @@ Message* AssureWritable(CMessage* self) { case MESSAGE_MUTABLE: return const_cast(self->message); case MESSAGE_FROZEN: - SetMessageFrozenError(); - return nullptr; + if (CheckFrozen(self, "Message is immutable.") < 0) { + return nullptr; + } + return const_cast(self->message); case MESSAGE_MUTABLE_DEFAULT: break; } @@ -1025,8 +1048,7 @@ int DeleteRepeatedField(CMessage* self, const FieldDescriptor* field_descriptor, int CheckRepeatedFieldDeletion(CMessage* parent, const FieldDescriptor* field_descriptor, PyObject* slice) { - if (parent->state == python::MESSAGE_FROZEN) { - SetMessageFrozenError(); + if (CheckFrozen(parent, "Message is immutable.") < 0) { return -1; } diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index 4653fd3706..bc993e2c17 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -360,6 +360,12 @@ PyObject* SetFrozenError(const char* msg); // Sets a Python FrozenInstanceError with the default error message for messages // type and returns nullptr. PyObject* SetMessageFrozenError(); +// Emits a DeprecationWarning when mutating a frozen message or container in +// OSS. +int WarnMessageFrozen(); +// Returns 0 if writable (might have thrown warning). +// Returns -1 on error (sets Python exception). +int CheckFrozen(CMessage* parent, const char* error_msg); PyObject* PyMessage_New(const Descriptor* descriptor, PyObject* py_message_factory); diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index aef12e0037..044016cff6 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -16,6 +16,7 @@ #include "google/protobuf/dynamic_message.h" #include "google/protobuf/message.h" #include "google/protobuf/reflection.h" +#include "google/protobuf/breaking_changes.h" #include "google/protobuf/pyext/descriptor.h" #include "google/protobuf/pyext/descriptor_pool.h" #include "google/protobuf/pyext/message.h" @@ -28,9 +29,6 @@ namespace python { namespace repeated_composite_container { -static PyObject* SetContainerFrozenError() { - return SetFrozenError("Container is immutable"); -} // --------------------------------------------------------------------- // len() @@ -285,8 +283,8 @@ static PyObject* Remove(PyObject* pself, PyObject* value) { RepeatedCompositeContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } Py_ssize_t len = Length(reinterpret_cast(self)); @@ -406,8 +404,8 @@ static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { RepeatedCompositeContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } // Support the old sort_function argument for backwards @@ -455,8 +453,8 @@ static PyObject* Reverse(PyObject* pself) { RepeatedCompositeContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } // TODO: b/517235198 - Reify even for empty sequences. @@ -499,8 +497,8 @@ static PyObject* Pop(PyObject* pself, PyObject* args) { RepeatedCompositeContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } Py_ssize_t index = -1; @@ -602,7 +600,7 @@ PyTypeObject RepeatedCompositeContainer_Type = { #if PY_VERSION_HEX >= 0x03080000 0, // tp_vectorcall_offset #else - nullptr, // tp_print + nullptr, // tp_print #endif nullptr, // tp_getattr nullptr, // tp_setattr diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index a44e15d3b0..c149bf8703 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -26,6 +26,7 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" #include "google/protobuf/reflection.h" +#include "google/protobuf/breaking_changes.h" #include "google/protobuf/pyext/message.h" #include "google/protobuf/pyext/safe_numerics.h" #include "google/protobuf/pyext/scoped_pyobject_ptr.h" @@ -526,9 +527,6 @@ bool CallWithSpan(const Message* message, namespace repeated_scalar_container { -static PyObject* SetContainerFrozenError() { - return SetFrozenError("Container is immutable"); -} static int InternalAssignRepeatedField(RepeatedScalarContainer* self, PyObject* list) { @@ -1057,8 +1055,8 @@ static PyObject* Remove(PyObject* pself, PyObject* value) { // Even if the value doesn't exist in the container, raise immutability error // prior to value error if applicable. - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } Py_ssize_t match_index = -1; @@ -1306,8 +1304,8 @@ static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { RepeatedScalarContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } // Support the old sort_function argument for backwards @@ -1353,8 +1351,8 @@ static PyObject* Reverse(PyObject* pself) { RepeatedScalarContainer* self = reinterpret_cast(pself); - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } // TODO: b/517235198 - Reify even for empty sequences. @@ -1405,8 +1403,8 @@ static PyObject* Pop(PyObject* pself, PyObject* args) { // Even if the value doesn't exist in the container, raise immutability error // prior to value error. - if (self->parent->state == python::MESSAGE_FROZEN) { - return SetContainerFrozenError(); + if (CheckFrozen(self->parent, "Container is immutable") < 0) { + return nullptr; } Py_ssize_t index = -1; diff --git a/python/google/protobuf/runtime_version.py b/python/google/protobuf/runtime_version.py index 45950bff17..9fbfcb6169 100644 --- a/python/google/protobuf/runtime_version.py +++ b/python/google/protobuf/runtime_version.py @@ -30,7 +30,7 @@ OSS_DOMAIN = Domain.PUBLIC OSS_MAJOR = 7 OSS_MINOR = 36 OSS_PATCH = 0 -OSS_SUFFIX = '-dev' +OSS_SUFFIX = '-rc2' DOMAIN = OSS_DOMAIN MAJOR = OSS_MAJOR diff --git a/python/map.c b/python/map.c index 98ea09366a..6217e06a3b 100644 --- a/python/map.c +++ b/python/map.c @@ -7,6 +7,7 @@ #include "python/map.h" +#include "google/protobuf/breaking_changes.h" #include "python/convert.h" #include "python/message.h" #include "python/protobuf.h" @@ -130,14 +131,16 @@ bool PyUpb_MapContainer_IsFrozen(PyUpb_MapContainer* self) { if (PyUpb_MapContainer_IsStub(self)) { return PyUpb_Message_IsFrozen(self->ptr.parent); } else { - return upb_Map_IsFrozen(self->ptr.map); + return upb_Map_IsFrozen(self->ptr.map) || PyUpb_Arena_IsFrozen(self->arena); } } upb_Map* PyUpb_MapContainer_AssureWritable(PyObject* _self) { PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self; if (PyUpb_MapContainer_IsFrozen(self)) { - return (upb_Map*)PyUpb_SetFrozenErrorWithMsg("Map is immutable"); + if (!PyUpb_CheckFrozen(true, "Map is immutable")) { + return NULL; + } } self->version++; diff --git a/python/message.c b/python/message.c index 4db8c0157e..e559c08ebb 100644 --- a/python/message.c +++ b/python/message.c @@ -13,6 +13,7 @@ #include #include +#include "google/protobuf/breaking_changes.h" #include "python/convert.h" #include "python/descriptor.h" #include "python/extension_dict.h" @@ -673,8 +674,9 @@ static void PyUpb_Message_SetField(PyUpb_Message* parent, const upb_FieldDef* f, */ bool PyUpb_Message_AssureWritable(PyUpb_Message* self) { if (PyUpb_Message_IsFrozen((PyObject*)self)) { - PyUpb_SetFrozenError(); - return false; + if (!PyUpb_CheckFrozen(true, "Message is immutable.")) { + return false; + } } if (!PyUpb_Message_IsStub(self)) return true; @@ -1061,7 +1063,8 @@ bool PyUpb_Message_IsFrozen(PyObject* _self) { while (PyUpb_Message_IsStub(self)) { self = self->ptr.parent; } - bool is_frozen = upb_Message_IsFrozen(self->ptr.msg); + bool is_frozen = + upb_Message_IsFrozen(self->ptr.msg) || PyUpb_Arena_IsFrozen(self->arena); // Invariant: Since we only store the parent *message* (and not any parent // repeated field or map) in a stub's `ptr.parent`, we wouldn't correctly // handle the case where a parent message is unfrozen but a containing diff --git a/python/protobuf.c b/python/protobuf.c index 5be18043df..6a72273015 100644 --- a/python/protobuf.c +++ b/python/protobuf.c @@ -12,6 +12,7 @@ #include #include +#include "google/protobuf/breaking_changes.h" #include "python/descriptor.h" #include "python/descriptor_containers.h" #include "python/descriptor_pool.h" @@ -342,6 +343,7 @@ typedef struct { PyObject_HEAD upb_Arena* arena; // clang-format on + bool frozen; } PyUpb_Arena; #ifdef __GLIBC__ @@ -386,6 +388,7 @@ PyObject* PyUpb_Arena_New(void) { PyUpb_ModuleState* state = PyUpb_ModuleState_Get(); PyUpb_Arena* arena = (void*)PyType_GenericAlloc(state->arena_type, 0); arena->arena = PyUpb_NewArena(); + arena->frozen = false; return &arena->ob_base; } @@ -398,6 +401,14 @@ upb_Arena* PyUpb_Arena_Get(PyObject* arena) { return ((PyUpb_Arena*)arena)->arena; } +bool PyUpb_Arena_IsFrozen(PyObject* arena) { + return ((PyUpb_Arena*)arena)->frozen; +} + +void PyUpb_Arena_SetFrozen(PyObject* arena, bool frozen) { + ((PyUpb_Arena*)arena)->frozen = frozen; +} + static PyType_Slot PyUpb_Arena_Slots[] = { {Py_tp_dealloc, PyUpb_Arena_Dealloc}, {0, NULL}, @@ -546,6 +557,26 @@ PyObject* PyUpb_SetFrozenError(void) { return PyUpb_SetFrozenErrorWithMsg("Message is immutable."); } +int PyUpb_WarnFrozen(void) { + return PyErr_WarnEx( + PyExc_FutureWarning, + "Mutating messages or containers returned by GetOptions() is deprecated" + " and will raise an exception in a future release.", + 3); +} + +bool PyUpb_CheckFrozen(bool is_frozen, const char* error_msg) { + if (is_frozen) { +#if PROTOBUF_PY_FUTURE_FREEZE_OPTIONS + PyUpb_SetFrozenErrorWithMsg(error_msg); + return false; +#else + return PyUpb_WarnFrozen() >= 0; +#endif + } + return true; +} + // ----------------------------------------------------------------------------- // Module Entry Point // ----------------------------------------------------------------------------- diff --git a/python/protobuf.h b/python/protobuf.h index cd14039fe4..240c7d6f11 100644 --- a/python/protobuf.h +++ b/python/protobuf.h @@ -173,6 +173,8 @@ PyUpb_WeakMap* PyUpb_ObjCache_Instance(void); PyObject* PyUpb_Arena_New(void); upb_Arena* PyUpb_Arena_Get(PyObject* arena); +bool PyUpb_Arena_IsFrozen(PyObject* arena); +void PyUpb_Arena_SetFrozen(PyObject* arena, bool frozen); // ----------------------------------------------------------------------------- // Utilities @@ -234,5 +236,9 @@ PyObject* PyUpb_SetFrozenError(void); // Sets a Python FrozenInstanceError with the given custom message and returns // NULL. PyObject* PyUpb_SetFrozenErrorWithMsg(const char* msg); +// Emits a DeprecationWarning when mutating a frozen message or container in +// OSS. +int PyUpb_WarnFrozen(void); +bool PyUpb_CheckFrozen(bool is_frozen, const char* error_msg); #endif // PYUPB_PROTOBUF_H__ diff --git a/python/repeated.c b/python/repeated.c index 5608e5bda4..30dc3e0679 100644 --- a/python/repeated.c +++ b/python/repeated.c @@ -108,14 +108,17 @@ bool PyUpb_RepeatedContainer_IsFrozen(PyUpb_RepeatedContainer* self) { if (PyUpb_RepeatedContainer_IsStub(self)) { return PyUpb_Message_IsFrozen(self->ptr.parent); } else { - return upb_Array_IsFrozen(self->ptr.arr); + return upb_Array_IsFrozen(self->ptr.arr) || + PyUpb_Arena_IsFrozen(self->arena); } } upb_Array* PyUpb_RepeatedContainer_AssureWritable(PyObject* _self) { PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self; if (PyUpb_RepeatedContainer_IsFrozen(self)) { - return (upb_Array*)PyUpb_SetFrozenErrorWithMsg("Container is immutable"); + if (!PyUpb_CheckFrozen(true, "Container is immutable")) { + return NULL; + } } upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self); @@ -967,7 +970,9 @@ static PyObject* PyUpb_RepeatedContainer_Sort(PyObject* pself, PyObject* args, } if (PyUpb_RepeatedContainer_IsFrozen((PyUpb_RepeatedContainer*)pself)) { - return PyUpb_SetFrozenErrorWithMsg("Container is immutable"); + if (!PyUpb_CheckFrozen(true, "Container is immutable")) { + return NULL; + } } // TODO:b/517235198 - Reify even for empty sequences. diff --git a/regenerate_stale_files.sh b/regenerate_stale_files.sh index 4c6f981576..0aa7d3d931 100755 --- a/regenerate_stale_files.sh +++ b/regenerate_stale_files.sh @@ -24,6 +24,7 @@ STALENESS_TESTS=( "php:proto_staleness_test" "ruby/ext/google/protobuf_c:test_amalgamation_staleness" "upb/reflection:descriptor_upb_proto_staleness_test" + "upb/reflection:json_enumvalue_options_upb_proto_staleness_test" "upb_generator:plugin_upb_proto_staleness_test" ) diff --git a/ruby/BUILD.bazel b/ruby/BUILD.bazel index 8e1c85343c..8d2d1ab506 100755 --- a/ruby/BUILD.bazel +++ b/ruby/BUILD.bazel @@ -93,8 +93,8 @@ selects.config_setting_group( internal_copy_files( name = "copied_wkt_proto_files", srcs = [ - "//:well_known_type_protos", "//src/google/protobuf:descriptor_proto_srcs", + "//src/google/protobuf:language_neutral_proto_srcs", "//src/google/protobuf/compiler:plugin.proto", ], strip_prefix = "src", diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index 33ee082ab1..22eed466ae 100644 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -38,6 +38,13 @@ #define UPB_GNUC_MIN(x, y) 0 #endif +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define UPB_CLANG_MIN(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define UPB_CLANG_MIN(x, y) 0 +#endif + // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. @@ -602,10 +609,12 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name; \ - extern type __stop_linkarr_##name; \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name; \ + extern type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -616,13 +625,15 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name __asm( \ - "section$start$__DATA$__la_" #name); \ - extern type __stop_linkarr_##name __asm( \ - "section$end$__DATA$" \ - "__la_" #name); \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -660,7 +671,9 @@ Error, UINTPTR_MAX is undefined // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) -#define UPB_LINKARR_DECLARE(name, type) +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) @@ -677,11 +690,46 @@ Error, UINTPTR_MAX is undefined #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif -#if defined(__ELF__) || defined(__wasm__) || defined(__MACH__) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define _UPB_STRINGIFY2(x) #x +#define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) + +#if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) +/* + * Workaround for b/456308964 and b/456317163. Although weak constructors + * resolve to a single function body, Clang still emits a pointer into + * .init_array for every translation unit, causing the constructor to be + * executed multiple times and inflating binary size. We wrap the .init_array + * entry in a COMDAT group (using inline assembly) to force the linker to + * deduplicate the pointer to exactly one instance. %cc is used in preference to + * the more widely available %c because %c may under some circumstances still + * output a function name including relocation information, which will then + * confuse the linker. This was only a problem on gcc; when %cc was introduced + * to clang it was just an alias to %c, and clang's %c had already done the + * checks that %cc introduced to gcc. + * References: + * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa + * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 + */ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ + __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ + void) { \ + __asm__ volatile( \ + ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ + ".dc.a %cc0\n" \ + ".popsection\n" \ + : \ + : "X"(UPB_PRIVATE(name))); \ + __VA_ARGS__ \ + } +#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ + defined(__MINGW32__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ - name)(void) + name)(void) { \ + __VA_ARGS__ \ + } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 @@ -692,17 +740,22 @@ Error, UINTPTR_MAX is undefined * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ - static void __cdecl UPB_PRIVATE(name)(void) - + static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. -#define UPB_CONSTRUCTOR(name, unique_name) static void UPB_PRIVATE(name)(void) +#if defined(__GNUC__) || defined(__clang__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#else +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#endif #endif // @@ -740,9 +793,9 @@ Error, UINTPTR_MAX is undefined #elif defined(__ELF__) || defined(__wasm__) -// On ELF, weak aliases work properly, so we can have all weak MiniTables point -// to the same empty singleton MiniTable. This reduces code size if many -// MiniTables are tree shaken. + // On ELF, weak aliases work properly, so we can have all weak MiniTables + // point to the same empty singleton MiniTable. This reduces code size if many + // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ @@ -2389,7 +2442,7 @@ const upb_MiniTableEnum google__protobuf__SymbolVisibility_enum_init = { }, }; -static const upb_MiniTable *messages_layout[35] = { +static const upb_MiniTable *messages_layout_google_protobuf_descriptor_proto_upb_file_layout[35] = { &google__protobuf__FileDescriptorSet_msg_init, &google__protobuf__FileDescriptorProto_msg_init, &google__protobuf__DescriptorProto_msg_init, @@ -2427,7 +2480,7 @@ static const upb_MiniTable *messages_layout[35] = { &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, }; -static const upb_MiniTableEnum *enums_layout[21] = { +static const upb_MiniTableEnum *enums_layout_google_protobuf_descriptor_proto_upb_file_layout[21] = { &google__protobuf__Edition_enum_init, &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init, &google__protobuf__FeatureSet__EnforceNamingStyle_enum_init, @@ -2452,8 +2505,8 @@ static const upb_MiniTableEnum *enums_layout[21] = { }; const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { - messages_layout, - enums_layout, + messages_layout_google_protobuf_descriptor_proto_upb_file_layout, + enums_layout_google_protobuf_descriptor_proto_upb_file_layout, NULL, 35, 21, @@ -2462,6 +2515,81 @@ const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#include + +// Must be last. + +extern const UPB_PRIVATE(upb_GeneratedExtensionListEntry)* UPB_PRIVATE(upb_generated_extension_list); +typedef struct { + upb_MiniTableField fields[1]; +} pb__enumvalue__JsonEnumValueOptions_msg_init_Fields; + +static const pb__enumvalue__JsonEnumValueOptions_msg_init_Fields pb_enumvalue_JsonEnumValueOptions__fields = {{ + {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}}; + +const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init = { + &pb_enumvalue_JsonEnumValueOptions__fields.fields[0], + UPB_SIZE(24, 32), 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "pb.enumvalue.JsonEnumValueOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeUnknown}, + {0x001000000000000a, &upb_DecodeFast_String_Scalar_Tag1Byte}, + }) +}; + +static const upb_MiniTableExtension pb_enumvalue_json_ext_obj = { + {998, 0, 0, UPB_SIZE(3, 4), 11, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsExtension | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {.UPB_PRIVATE(submsg) = &pb__enumvalue__JsonEnumValueOptions_msg_init}, + &google__protobuf__EnumValueOptions_msg_init, + +}; +UPB_LINKARR_APPEND(upb_AllExts) +const upb_MiniTableExtension* pb_enumvalue_json_ext = &pb_enumvalue_json_ext_obj; + static const upb_MiniTable *messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb__enumvalue__JsonEnumValueOptions_msg_init, +}; + + +static const upb_MiniTableExtension *extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb_enumvalue_json_ext_obj, +}; + +UPB_LINKARR_DECLARE(upb_AllExts, const upb_MiniTableExtension*); +UPB_CONSTRUCTOR(upb_GeneratedRegistry_Constructor, google_protobuf_json_enumvalue_options_proto_ext_constructor, { + static bool finished = false; + if (finished) return; + finished = true; + static UPB_PRIVATE(upb_GeneratedExtensionListEntry) entry = { + UPB_LINKARR_START(upb_AllExts), + UPB_LINKARR_STOP(upb_AllExts), + NULL + }; + UPB_ASSERT(entry.next == NULL); + entry.next = UPB_PRIVATE(upb_generated_extension_list); + UPB_PRIVATE(upb_generated_extension_list) = &entry; +}) +const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout = { + messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + NULL, + extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + 1, + 0, + 1, +}; + + + #include #include @@ -4208,7 +4336,7 @@ static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { upb_StringView str = jsondec_string(d); const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); const upb_EnumValueDef* ev = - upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); + upb_EnumDef_FindByJsonNameWithSize(e, str.data, str.size); upb_JsonMessageValue val = {.ignore = false}; if (ev) { val.value.int32_val = upb_EnumValueDef_Number(ev); @@ -4986,11 +5114,12 @@ int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, } -#include #include #include #include +#include #include +#include #include @@ -5017,6 +5146,7 @@ static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m, bool first); static void jsonenc_value(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m); +static void jsonenc_string(jsonenc* e, upb_StringView str); UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { upb_Status_SetErrorMessage(e->status, msg); @@ -5178,7 +5308,8 @@ static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { : upb_EnumDef_FindValueByNumber(e_def, val); if (ev) { - jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); + const char* name = upb_EnumValueDef_JsonName(ev); + jsonenc_string(e, upb_StringView_FromString(name)); } else { jsonenc_printf(e, "%" PRId32, val); } @@ -11515,6 +11646,28 @@ struct upb_EnumDef { bool is_sorted; // Whether all of the values are defined in ascending order. }; +// We store both regular proto enum names and custom JSON enum names in the +// same strtable (ntoi). This is safe because protoc enforces that custom JSON +// enum names never conflict with default enum names across different enum +// values (or are identical, in which case we leave the entry untagged). Because +// upb_EnumValueDef pointers are arena-aligned to at least 4 bytes (bit 0 is +// always 0 for untagged pointers), we set bit 0 to tag custom JSON-only names +// so that regular name lookups can ignore them. +static const uintptr_t kUpb_EnumDef_JsonOnlyTag = 1ULL; + +static upb_value _upb_EnumDef_TagJsonOnly(upb_value v) { + v.val |= kUpb_EnumDef_JsonOnlyTag; + return v; +} + +static bool _upb_EnumDef_IsJsonOnly(upb_value v) { + return (v.val & kUpb_EnumDef_JsonOnlyTag) != 0; +} + +static const upb_EnumValueDef* _upb_EnumDef_Untag(upb_value v) { + return (const upb_EnumValueDef*)(v.val & ~kUpb_EnumDef_JsonOnlyTag); +} + upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) { return (upb_EnumDef*)&e[i]; } @@ -11523,18 +11676,43 @@ const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) { return e->layout; } -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) { +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v) { const char* name = upb_EnumValueDef_Name(v); const upb_value val = upb_value_constptr(v); - bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a); - if (!ok) return false; + bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, ctx->arena); + if (!ok) _upb_DefBuilder_OomErr(ctx); - // Multiple enumerators can have the same number, first one wins. + // Aliased enum values can share the same custom JSON name, first one wins. + const char* json_name = upb_EnumValueDef_JsonName(v); + size_t json_len = strlen(json_name); + if (strcmp(json_name, name) != 0) { + upb_value existing_value; + if (upb_strtable_lookup2(&e->ntoi, json_name, json_len, &existing_value)) { + const upb_EnumValueDef* enumval = _upb_EnumDef_Untag(existing_value); + if (upb_EnumValueDef_Number(enumval) != upb_EnumValueDef_Number(v)) { + // If the custom JSON name exists, but points to a value with a + // different number, then this is a parse/conflict error. + _upb_DefBuilder_Errf(ctx, + "duplicate custom json_name (%s) in enum (%s)", + json_name, upb_EnumDef_FullName(e)); + } + } else { + upb_value json_val = _upb_EnumDef_TagJsonOnly(val); + if (!upb_strtable_insert(&e->ntoi, json_name, json_len, json_val, + ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } + } + } + + // Multiple enum values can have the same number, first one wins. const int number = upb_EnumValueDef_Number(v); if (!upb_inttable_lookup(&e->iton, number, NULL)) { - return upb_inttable_insert(&e->iton, number, val, a); + if (!upb_inttable_insert(&e->iton, number, val, ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } } - return true; } const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) { @@ -11591,6 +11769,16 @@ upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) { int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; } +const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize(const upb_EnumDef* e, + const char* name, + size_t size) { + upb_value v; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + return _upb_EnumDef_Untag(v); +} + const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name) { return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name)); @@ -11599,9 +11787,13 @@ const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( const upb_EnumDef* e, const char* name, size_t size) { upb_value v; - return upb_strtable_lookup2(&e->ntoi, name, size, &v) - ? upb_value_getconstptr(v) - : NULL; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + if (_upb_EnumDef_IsJsonOnly(v)) { + return NULL; + } + return upb_value_getconstptr(v); } const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e, @@ -11742,7 +11934,7 @@ static void create_enumdef(upb_DefBuilder* ctx, const char* prefix, upb_EnumDef_FullName(e)); } - bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena); + bool ok = upb_strtable_init(&e->ntoi, n_value * 2, ctx->arena); if (!ok) _upb_DefBuilder_OomErr(ctx); ok = upb_inttable_init(&e->iton, ctx->arena); @@ -11859,6 +12051,7 @@ struct upb_EnumValueDef { const google_protobuf_FeatureSet* resolved_features; const upb_EnumDef* parent; const char* full_name; + const char* json_name; int32_t number; }; @@ -11880,7 +12073,7 @@ const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v, (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*)); if (!out) return NULL; - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { out[i] = (upb_EnumValueDef*)&v[i]; } qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare); @@ -11910,6 +12103,10 @@ const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) { return v->full_name; } +const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v) { + return v->json_name ? v->json_name : upb_EnumValueDef_Name(v); +} + const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) { return _upb_DefBuilder_FullToShort(v->full_name); } @@ -11921,6 +12118,19 @@ uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) { return v - upb_EnumDef_Value(v->parent, 0); } +static const char* _upb_EnumValueDef_ExtractJsonName( + upb_DefBuilder* ctx, const upb_EnumValueDef* v) { + if (!upb_EnumValueDef_HasOptions(v)) return NULL; + const google_protobuf_EnumValueOptions* opts = (const google_protobuf_EnumValueOptions*)v->opts; + if (!pb_enumvalue_has_json(opts)) return NULL; + const pb_enumvalue_JsonEnumValueOptions* json_opts = pb_enumvalue_json(opts); + if (!json_opts || !pb_enumvalue_JsonEnumValueOptions_has_string(json_opts)) { + return NULL; + } + upb_StringView str = pb_enumvalue_JsonEnumValueOptions_string(json_opts); + return upb_strdup2(str.data, str.size, ctx->arena); +} + static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, const google_protobuf_EnumValueDescriptorProto* val_proto, const google_protobuf_FeatureSet* parent_features, @@ -11935,11 +12145,11 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, v->parent = e; // Must happen prior to _upb_DefBuilder_Add() v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name); v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto); + v->json_name = _upb_EnumValueDef_ExtractJsonName(ctx, v); _upb_DefBuilder_Add(ctx, v->full_name, _upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL)); - bool ok = _upb_EnumDef_Insert(e, v, ctx->arena); - if (!ok) _upb_DefBuilder_OomErr(ctx); + _upb_EnumDef_Insert(ctx, e, v); } // Allocate and initialize an array of |n| enum value defs owned by |e|. @@ -18602,6 +18812,7 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( #undef UPB_TSAN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN +#undef UPB_CLANG_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME #undef UPB_DESC_MINITABLE #undef UPB_IS_GOOGLE3 @@ -18628,3 +18839,6 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( #undef UPB_DEPRECATE_AND_INLINE #undef UPB_MAYBE_ASSUME #undef UPB_ATTR_CONST +#undef _UPB_STRINGIFY +#undef _UPB_STRINGIFY2 +#undef UPB_CONSTRUCTOR diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index 92128cdccc..71dfff57d6 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -37,6 +37,13 @@ #define UPB_GNUC_MIN(x, y) 0 #endif +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define UPB_CLANG_MIN(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define UPB_CLANG_MIN(x, y) 0 +#endif + // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. @@ -601,10 +608,12 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name; \ - extern type __stop_linkarr_##name; \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name; \ + extern type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -615,13 +624,15 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name __asm( \ - "section$start$__DATA$__la_" #name); \ - extern type __stop_linkarr_##name __asm( \ - "section$end$__DATA$" \ - "__la_" #name); \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -659,7 +670,9 @@ Error, UINTPTR_MAX is undefined // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) -#define UPB_LINKARR_DECLARE(name, type) +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) @@ -676,11 +689,46 @@ Error, UINTPTR_MAX is undefined #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif -#if defined(__ELF__) || defined(__wasm__) || defined(__MACH__) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define _UPB_STRINGIFY2(x) #x +#define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) + +#if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) +/* + * Workaround for b/456308964 and b/456317163. Although weak constructors + * resolve to a single function body, Clang still emits a pointer into + * .init_array for every translation unit, causing the constructor to be + * executed multiple times and inflating binary size. We wrap the .init_array + * entry in a COMDAT group (using inline assembly) to force the linker to + * deduplicate the pointer to exactly one instance. %cc is used in preference to + * the more widely available %c because %c may under some circumstances still + * output a function name including relocation information, which will then + * confuse the linker. This was only a problem on gcc; when %cc was introduced + * to clang it was just an alias to %c, and clang's %c had already done the + * checks that %cc introduced to gcc. + * References: + * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa + * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 + */ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ + __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ + void) { \ + __asm__ volatile( \ + ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ + ".dc.a %cc0\n" \ + ".popsection\n" \ + : \ + : "X"(UPB_PRIVATE(name))); \ + __VA_ARGS__ \ + } +#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ + defined(__MINGW32__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ - name)(void) + name)(void) { \ + __VA_ARGS__ \ + } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 @@ -691,17 +739,22 @@ Error, UINTPTR_MAX is undefined * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ - static void __cdecl UPB_PRIVATE(name)(void) - + static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. -#define UPB_CONSTRUCTOR(name, unique_name) static void UPB_PRIVATE(name)(void) +#if defined(__GNUC__) || defined(__clang__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#else +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#endif #endif // @@ -739,9 +792,9 @@ Error, UINTPTR_MAX is undefined #elif defined(__ELF__) || defined(__wasm__) -// On ELF, weak aliases work properly, so we can have all weak MiniTables point -// to the same empty singleton MiniTable. This reduces code size if many -// MiniTables are tree shaken. + // On ELF, weak aliases work properly, so we can have all weak MiniTables + // point to the same empty singleton MiniTable. This reduces code size if many + // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ @@ -6845,6 +6898,35 @@ extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; #endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ */ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init; +extern const upb_MiniTableExtension* pb_enumvalue_json_ext; + +extern const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ */ #ifndef UPB_BASE_INTERNAL_LOG2_H_ #define UPB_BASE_INTERNAL_LOG2_H_ @@ -15019,6 +15101,7 @@ bool upb_DefPool_ImplicitFieldPresenceDisabled(const upb_DefPool* s); #include #include +#include // Must be last. @@ -15031,6 +15114,12 @@ bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num); const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e); int32_t upb_EnumDef_Default(const upb_EnumDef* e); UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e); +UPB_API const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize( + const upb_EnumDef* e, const char* name, size_t size); +UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindByJsonName( + const upb_EnumDef* e, const char* name) { + return upb_EnumDef_FindByJsonNameWithSize(e, name, strlen(name)); +} const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name); UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( @@ -15073,6 +15162,8 @@ UPB_API int upb_EnumDef_ValueCount(const upb_EnumDef* e); #ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_ #define UPB_REFLECTION_ENUM_VALUE_DEF_H_ +#include + // Must be last. @@ -15084,6 +15175,7 @@ const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v); const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v); bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v); uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v); +UPB_API const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v); UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v); UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v); const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options( @@ -18082,7 +18174,8 @@ extern "C" { #endif upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i); -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a); +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v); const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e); // Allocate and initialize an array of |n| enum defs. @@ -18176,6 +18269,151 @@ char* upb_strdup2(const char* s, size_t len, upb_Arena* a); #endif /* UPB_REFLECTION_INTERNAL_STRDUP2_H_ */ +#ifndef GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ +#define GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ + +// IWYU pragma: begin_exports + +#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 +// This header is checked in. +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 1 +// This header is generated at build time by the bootstrapping process. +#else +// This is the normal header, generated by upb_c_proto_library(). +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct pb_enumvalue_JsonEnumValueOptions { + upb_Message UPB_PRIVATE(base); +} pb_enumvalue_JsonEnumValueOptions; + +struct google_protobuf_EnumValueOptions; + + + +/* pb.enumvalue.JsonEnumValueOptions */ +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_new(upb_Arena* arena) { + return (pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse(const char* buf, size_t size, + upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, NULL, 0, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse_ex( + const char* buf, size_t size, const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, extreg, + options, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize(const pb_enumvalue_JsonEnumValueOptions* msg, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize_ex(const pb_enumvalue_JsonEnumValueOptions* msg, + int options, upb_Arena* arena, + size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_clear_string(pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView pb_enumvalue_JsonEnumValueOptions_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool pb_enumvalue_JsonEnumValueOptions_has_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_set_string(pb_enumvalue_JsonEnumValueOptions* msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message*)msg, &field, &value); +} + +UPB_INLINE bool pb_enumvalue_has_json(const struct google_protobuf_EnumValueOptions* msg) { + return upb_Message_HasExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} + +UPB_INLINE void pb_enumvalue_clear_json(struct google_protobuf_EnumValueOptions* msg) { + upb_Message_ClearExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} +UPB_INLINE const pb_enumvalue_JsonEnumValueOptions* +pb_enumvalue_json(const struct google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + const pb_enumvalue_JsonEnumValueOptions* default_val = NULL; + const pb_enumvalue_JsonEnumValueOptions* ret; + _upb_Message_GetExtensionField((upb_Message*)msg, ext, &default_val, &ret); + return ret; +} + +UPB_INLINE void pb_enumvalue_set_json(struct google_protobuf_EnumValueOptions* msg, + const pb_enumvalue_JsonEnumValueOptions* val, + upb_Arena* arena) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + bool ok = upb_Message_SetExtension((upb_Message*)msg, ext, &val, arena); + UPB_ASSERT(ok); +} +UPB_INLINE struct pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_mutable_json( + struct google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct pb_enumvalue_JsonEnumValueOptions* sub = (struct pb_enumvalue_JsonEnumValueOptions*)pb_enumvalue_json(msg); + if (sub == NULL) { + sub = (struct pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); + if (sub) pb_enumvalue_set_json(msg, sub, arena); + } + return sub; +} +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ */ +#endif + +// IWYU pragma: end_exports + +#endif // GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ #ifndef UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ #define UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ @@ -18990,6 +19228,7 @@ UPB_PRIVATE(upb_WireWriter_VarintUnusedSizeFromLeadingZeros64)(uint64_t clz) { #undef UPB_TSAN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN +#undef UPB_CLANG_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME #undef UPB_DESC_MINITABLE #undef UPB_IS_GOOGLE3 @@ -19016,3 +19255,6 @@ UPB_PRIVATE(upb_WireWriter_VarintUnusedSizeFromLeadingZeros64)(uint64_t clz) { #undef UPB_DEPRECATE_AND_INLINE #undef UPB_MAYBE_ASSUME #undef UPB_ATTR_CONST +#undef _UPB_STRINGIFY +#undef _UPB_STRINGIFY2 +#undef UPB_CONSTRUCTOR diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 09569635f6..47aabed7f6 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "4.36.0" + s.version = "4.36.0.rc.2" 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" diff --git a/ruby/pom.xml b/ruby/pom.xml index b96c464223..c044254c4d 100644 --- a/ruby/pom.xml +++ b/ruby/pom.xml @@ -9,7 +9,7 @@ com.google.protobuf.jruby protobuf-jruby - 4.36.0 + 4.36.0-RC2 Protocol Buffer JRuby native extension Protocol Buffers are a way of encoding structured data in an efficient yet @@ -76,7 +76,7 @@ com.google.protobuf protobuf-java-util - 4.36.0 + 4.36.0-RC2 org.jruby diff --git a/src/file_lists.cmake b/src/file_lists.cmake index d6a6947228..0029947822 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -848,6 +848,7 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/reflection/internal/oneof_def.h ${protobuf_SOURCE_DIR}/upb/reflection/internal/service_def.h ${protobuf_SOURCE_DIR}/upb/reflection/internal/upb_edition_defaults.h + ${protobuf_SOURCE_DIR}/upb/reflection/json_enumvalue_options_bootstrap.h ${protobuf_SOURCE_DIR}/upb/reflection/message.h ${protobuf_SOURCE_DIR}/upb/reflection/message.hpp ${protobuf_SOURCE_DIR}/upb/reflection/message_def.h @@ -988,60 +989,6 @@ set(protoc-gen-upb_minitable_hdrs ${protobuf_SOURCE_DIR}/upb_generator/plugin_bootstrap.h ) -# @//src/google/protobuf:well_known_type_protos -set(wkt_protos_files - ${protobuf_SOURCE_DIR}/src/google/protobuf/any.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/api.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/type.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.proto -) - -# @//src/google/protobuf:cpp_file_options_proto -set(cpp_file_options_proto_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_file_options.proto -) - -# @//src/google/protobuf:cpp_file_options_proto -set(cpp_file_options_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_file_options.proto.pb.cc -) - -# @//src/google/protobuf:cpp_file_options_proto -set(cpp_file_options_proto_hdrs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_file_options.proto.pb.h -) - -# @//src/google/protobuf:cpp_file_options_proto -set(cpp_file_options_proto_files - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_file_options_proto-descriptor-set.proto.bin -) - -# @//src/google/protobuf:cpp_features_proto -set(cpp_features_proto_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_features.proto -) - -# @//src/google/protobuf:cpp_features_proto -set(cpp_features_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_features.proto.pb.cc -) - -# @//src/google/protobuf:cpp_features_proto -set(cpp_features_proto_hdrs - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_features.proto.pb.h -) - -# @//src/google/protobuf:cpp_features_proto -set(cpp_features_proto_files - ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_features_proto-descriptor-set.proto.bin -) - # @//src/google/protobuf:descriptor_proto set(descriptor_proto_proto_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.proto @@ -1062,34 +1009,6 @@ set(descriptor_proto_files ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_proto-descriptor-set.proto.bin ) -# @//src/google/protobuf:json_enumvalue_options_proto -set(json_enumvalue_options_proto_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options.proto -) - -# @//src/google/protobuf:json_enumvalue_options_proto -set(json_enumvalue_options_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options.proto.pb.cc -) - -# @//src/google/protobuf:json_enumvalue_options_proto -set(json_enumvalue_options_proto_hdrs - ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options.proto.pb.h -) - -# @//src/google/protobuf:json_enumvalue_options_proto -set(json_enumvalue_options_proto_files - ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options_proto-descriptor-set.proto.bin -) - -# @//src/google/protobuf:json_enumvalue_options_cc_proto -set(json_enumvalue_options_cc_proto_files - ${protobuf_SOURCE_DIR}/src/google/protobuf/_virtual_imports/json_enumvalue_options_proto/google/protobuf/json_enumvalue_options.pb.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/_virtual_imports/json_enumvalue_options_proto/google/protobuf/json_enumvalue_options.pb.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/libjson_enumvalue_options_proto.a - ${protobuf_SOURCE_DIR}/src/google/protobuf/libjson_enumvalue_options_proto.so -) - # @//src/google/protobuf/compiler:plugin_proto set(plugin_proto_proto_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.proto @@ -1110,64 +1029,27 @@ set(plugin_proto_files ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin_proto-descriptor-set.proto.bin ) -# @//csharp:c_sharp_features_proto -set(c_sharp_features_proto_proto_srcs +# @//src/google/protobuf:release_all_options_proto_srcs +set(release_all_options_protos_files ${protobuf_SOURCE_DIR}/csharp/google/protobuf/c_sharp_features.proto -) - -# @//csharp:c_sharp_features_proto -set(c_sharp_features_proto_srcs - ${protobuf_SOURCE_DIR}/csharp/google/protobuf/c_sharp_features.proto.pb.cc -) - -# @//csharp:c_sharp_features_proto -set(c_sharp_features_proto_hdrs - ${protobuf_SOURCE_DIR}/csharp/google/protobuf/c_sharp_features.proto.pb.h -) - -# @//csharp:c_sharp_features_proto -set(c_sharp_features_proto_files - ${protobuf_SOURCE_DIR}/csharp/c_sharp_features_proto-descriptor-set.proto.bin -) - -# @//java/core:java_features_proto -set(java_features_proto_proto_srcs - ${protobuf_SOURCE_DIR}/java/core/src/main/resources/google/protobuf/java_features.proto -) - -# @//java/core:java_features_proto -set(java_features_proto_srcs - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_features.proto.pb.cc -) - -# @//java/core:java_features_proto -set(java_features_proto_hdrs - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_features.proto.pb.h -) - -# @//java/core:java_features_proto -set(java_features_proto_files - ${protobuf_SOURCE_DIR}/java/core/java_features_proto-descriptor-set.proto.bin -) - -# @//go:go_features_proto -set(go_features_proto_proto_srcs ${protobuf_SOURCE_DIR}/go/google/protobuf/go_features.proto -) - -# @//go:go_features_proto -set(go_features_proto_srcs - ${protobuf_SOURCE_DIR}/go/go_features.proto.pb.cc -) - -# @//go:go_features_proto -set(go_features_proto_hdrs - ${protobuf_SOURCE_DIR}/go/go_features.proto.pb.h -) - -# @//go:go_features_proto -set(go_features_proto_files - ${protobuf_SOURCE_DIR}/go/go_features_proto-descriptor-set.proto.bin + ${protobuf_SOURCE_DIR}/java/core/src/main/resources/google/protobuf/java_features.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/any.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/api.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_features.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_file_options.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/cpp_options.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/json_options.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/type.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.proto ) # @//pkg:common_test @@ -1288,6 +1170,9 @@ set(upb_test_protos_files ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/json/json_enumval_custom_string.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/json_enumvalue_options.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/json_options.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 9fc9be8032..4db3c4e951 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -405,6 +405,24 @@ cc_proto_library( deps = [":json_enumvalue_options_proto"], ) +upb_c_proto_library( + name = "json_enumvalue_options_upb_c_proto", + visibility = ["//:__subpackages__"], + deps = [":json_enumvalue_options_proto"], +) + +upb_minitable_proto_library( + name = "json_enumvalue_options_upb_minitable_proto", + visibility = ["//:__subpackages__"], + deps = [":json_enumvalue_options_proto"], +) + +upb_proto_reflection_library( + name = "json_enumvalue_options_upb_reflection_proto", + visibility = ["//:__subpackages__"], + deps = [":json_enumvalue_options_proto"], +) + ################################################################################ # C++ Runtime Library ################################################################################ @@ -1202,12 +1220,111 @@ filegroup( visibility = ["//:__subpackages__"], ) +filegroup( + name = "json_enumvalue_options_proto_srcs", + srcs = ["json_enumvalue_options.proto"], + visibility = ["//:__subpackages__"], +) + filegroup( name = "cpp_features_proto_srcs", srcs = ["cpp_features.proto"], visibility = ["//:__subpackages__"], ) +# TODO: Revisit location of aggregate rules +filegroup( + name = "language_neutral_proto_srcs", + srcs = [ + ":json_options_proto_srcs", + ":well_known_type_protos", + ], + visibility = [ + "//ruby:__pkg__", + ], +) + +filegroup( + name = "release_all_options_proto_srcs", + srcs = [ + ":cpp_release_options_proto_srcs", + ":descriptor_proto_srcs", + ":language_neutral_proto_srcs", + "//csharp:c_sharp_features_proto_srcs", + "//go:go_features_proto_srcs", + "//java/core:java_features_proto_srcs", + ], + visibility = [ + "//java/core:__pkg__", + "//pkg:__pkg__", + "//python/dist:__pkg__", + ], +) + +proto_library( + name = "language_neutral_protos", + srcs = [":language_neutral_proto_srcs"], + strip_import_prefix = "/src", + visibility = [ + "//python/dist:__pkg__", + ], + exports = [ + ":descriptor_proto", + ], + deps = [ + ":descriptor_proto", + ], +) + +proto_library( + name = "release_all_options_protos", + srcs = [], + strip_import_prefix = "/src", + visibility = [ + "//java/core:__pkg__", + "//pkg:__pkg__", + "//python/dist:__pkg__", + ], + exports = [ + ":cpp_release_options_protos", + ":descriptor_proto", + ":language_neutral_protos", + # TODO: Create //lang:lang_release_options_protos targets for each language and + # depend on those instead. + "//csharp:c_sharp_features_proto", + "//go:go_features_proto", + "//java/core:java_features_proto", + ], + deps = [ + ":cpp_release_options_protos", + ":descriptor_proto", + ":language_neutral_protos", + # TODO: Create //lang:lang_release_options_protos targets for each language and + # depend on those instead. + "//csharp:c_sharp_features_proto", + "//go:go_features_proto", + "//java/core:java_features_proto", + ], +) + +filegroup( + name = "cpp_release_options_proto_srcs", + srcs = glob(["cpp_*options.proto"]) + ["cpp_features.proto"], +) + +proto_library( + name = "cpp_release_options_protos", + srcs = [":cpp_release_options_proto_srcs"], + strip_import_prefix = "/src", + deps = [":descriptor_proto"], +) + +filegroup( + name = "json_options_proto_srcs", + srcs = glob(["json_*options.proto"]), + visibility = ["//:__subpackages__"], +) + filegroup( name = "testdata", srcs = glob(["testdata/**/*"]) + [ @@ -1554,7 +1671,7 @@ exports_files( "//:__pkg__", "//python:__pkg__", "//ruby:__pkg__", - "//upb:__pkg__", + "//upb:__subpackages__", ], ) diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index b9d0279ed1..4d42009c77 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/any.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/any.pb.h" diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index c37af3ccc9..1500e855d3 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/any.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fany_2eproto_2epb_2eh #define google_2fprotobuf_2fany_2eproto_2epb_2eh diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index e3f85e4a92..f9411836a3 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/api.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/api.pb.h" diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index 38af1c21ca..f90d4f2f65 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/api.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fapi_2eproto_2epb_2eh #define google_2fprotobuf_2fapi_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc index 6a6686982b..71bbbf4860 100755 --- a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc +++ b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/csharp/c_sharp_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/compiler/csharp/c_sharp_features.pb.h" diff --git a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h index be8f038217..285921e70b 100755 --- a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h +++ b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/csharp/c_sharp_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fcompiler_2fcsharp_2fc_5fsharp_5ffeatures_2eproto_2epb_2eh #define google_2fprotobuf_2fcompiler_2fcsharp_2fc_5fsharp_5ffeatures_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index 542f784144..0cc2fab11e 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/java/java_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/compiler/java/java_features.pb.h" diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h index fb850f1868..765a509468 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.h +++ b/src/google/protobuf/compiler/java/java_features.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/java/java_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh #define google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/php/generator_unittest.cc b/src/google/protobuf/compiler/php/generator_unittest.cc index 79d4b10faa..1cfa10bf1a 100644 --- a/src/google/protobuf/compiler/php/generator_unittest.cc +++ b/src/google/protobuf/compiler/php/generator_unittest.cc @@ -137,6 +137,22 @@ TEST_F(PhpGeneratorTest, ImportPublic) { ExpectNoErrors(); } +// TODO Remove this test once full Edition 2026 support is in PHP +TEST_F(PhpGeneratorTest, Edition2026Fails) { + CreateTempFile("foo.proto", + R"schema( + edition = "2026"; + enum Foo { + BAR = 0; + })schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --php_out=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "PHP does not yet fully support Edition 2026, but is coming soon."); +} + } // namespace } // namespace php } // namespace compiler diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 4d85acf18b..66d9966e56 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -2212,6 +2212,12 @@ bool Generator::Generate(const FileDescriptor* file, const Options& options, "Can only generate PHP code for google/protobuf/descriptor.proto.\n"; return false; } + // TODO Remove once full Edition 2026 support is in PHP + if (GetEdition(*file) >= Edition::EDITION_2026) { + *error = + "PHP does not yet fully support Edition 2026, but is coming soon.\n"; + return false; + } return GenerateFile(file, options, generator_context, error); } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index a7b4f668bf..19b66dedf5 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/plugin.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/compiler/plugin.pb.h" diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index af8a1d8294..bfe9c4709a 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/plugin.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh #define google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/versions.h b/src/google/protobuf/compiler/versions.h index e099cca1ba..0d3825606d 100644 --- a/src/google/protobuf/compiler/versions.h +++ b/src/google/protobuf/compiler/versions.h @@ -53,10 +53,10 @@ // // Please avoid changing them manually, as they should be updated automatically // by Protobuf release process. -#define PROTOBUF_CPP_VERSION_STRING "7.36.0-dev" -#define PROTOBUF_JAVA_VERSION_STRING "4.36.0-dev" -#define PROTOBUF_PYTHON_VERSION_STRING "7.36.0-dev" -#define PROTOBUF_RUST_VERSION_STRING "4.36.0-dev" +#define PROTOBUF_CPP_VERSION_STRING "7.36.0-rc2" +#define PROTOBUF_JAVA_VERSION_STRING "4.36.0-rc2" +#define PROTOBUF_PYTHON_VERSION_STRING "7.36.0-rc2" +#define PROTOBUF_RUST_VERSION_STRING "4.36.0-rc2" namespace google { diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index 9659bac7d9..067ebb9879 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/cpp_features.pb.h" diff --git a/src/google/protobuf/cpp_features.pb.h b/src/google/protobuf/cpp_features.pb.h index de11ec0398..73e8d23107 100644 --- a/src/google/protobuf/cpp_features.pb.h +++ b/src/google/protobuf/cpp_features.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_features.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh #define google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh diff --git a/src/google/protobuf/cpp_file_options.pb.cc b/src/google/protobuf/cpp_file_options.pb.cc index f349dd8dcd..f9653bf2cd 100644 --- a/src/google/protobuf/cpp_file_options.pb.cc +++ b/src/google/protobuf/cpp_file_options.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_file_options.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/cpp_file_options.pb.h" diff --git a/src/google/protobuf/cpp_file_options.pb.h b/src/google/protobuf/cpp_file_options.pb.h index 606f838360..5df9f78bc8 100644 --- a/src/google/protobuf/cpp_file_options.pb.h +++ b/src/google/protobuf/cpp_file_options.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_file_options.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fcpp_5ffile_5foptions_2eproto_2epb_2eh #define google_2fprotobuf_2fcpp_5ffile_5foptions_2eproto_2epb_2eh diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 237e4d69bf..b6e391ea94 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -9288,19 +9288,7 @@ void internal::DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo( } if (loc_matches) { - if (loc->path_size() == static_cast(match_src.size() + 1)) { - int uninterpreted_field = loc->path(match_src.size()); - - SourceCodeInfo_Location* mapped_loc = new_locs.Add(); - *mapped_loc = *loc; - mapped_loc->mutable_path()->Assign(match_dest.begin(), - match_dest.end()); - mapped_loc->add_path(uninterpreted_field); - - // TODO: b/168903973 - recursively process options with aggregate - // values and add locations. Example: [(my_opt) = {a: 1, b: 2}] - // Locations of `a` and `b` are not added yet. - } + // TODO: b/168903973 - Remove once we update the format. // don't copy this row since it is a sub-location that we're removing // (or we already mapped it if it's a direct child) continue; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index b4ba33f626..0a7ac37ddb 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/descriptor.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/descriptor.pb.h" diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index cd47e1d6a9..1416175c04 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/descriptor.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh #define google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 472ae944cd..e0e7f68082 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -16274,6 +16274,8 @@ TEST_F(SourceLocationTest, GetSourceLocation) { "rpc Method(A) returns (A.B);")); } +// TODO: b/168903973 - Remove once we update the format. + TEST_F(SourceLocationTest, ExtensionSourceLocation) { SourceLocation loc; @@ -16330,19 +16332,7 @@ TEST_F(SourceLocationTest, InterpretedOptionSourceLocation) { EXPECT_FALSE(file_desc->GetSourceLocation(unint, &loc)); - SourceCodePath name_path = {FileDescriptorProto::kOptionsFieldNumber, - FileOptions::kJavaPackageFieldNumber, - UninterpretedOption::kNameFieldNumber}; - EXPECT_TRUE(file_desc->GetSourceLocation(name_path, &loc)); - EXPECT_THAT(loc, - MatchesSubstring(kSourceLocationTestInput, "java_package")); - - SourceCodePath val_path = {FileDescriptorProto::kOptionsFieldNumber, - FileOptions::kJavaPackageFieldNumber, - UninterpretedOption::kStringValueFieldNumber}; - EXPECT_TRUE(file_desc->GetSourceLocation(val_path, &loc)); - EXPECT_THAT(loc, - MatchesSubstring(kSourceLocationTestInput, "\"com.foo.bar\"")); +// TODO: b/168903973 - Remove once we update the format. } { SourceCodePath path = {FileDescriptorProto::kOptionsFieldNumber, @@ -16355,18 +16345,7 @@ TEST_F(SourceLocationTest, InterpretedOptionSourceLocation) { EXPECT_FALSE(file_desc->GetSourceLocation(unint, &loc)); - SourceCodePath name_path = {FileDescriptorProto::kOptionsFieldNumber, - kCustomOptionFieldNumber, - UninterpretedOption::kNameFieldNumber}; - EXPECT_TRUE(file_desc->GetSourceLocation(name_path, &loc)); - EXPECT_THAT(loc, - MatchesSubstring(kSourceLocationTestInput, "(test_file_opt)")); - - SourceCodePath val_path = {FileDescriptorProto::kOptionsFieldNumber, - kCustomOptionFieldNumber, - UninterpretedOption::kStringValueFieldNumber}; - EXPECT_TRUE(file_desc->GetSourceLocation(val_path, &loc)); - EXPECT_THAT(loc, MatchesSubstring(kSourceLocationTestInput, "\"foobar\"")); +// TODO: b/168903973 - Remove once we update the format. } // Message option diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index a99539aa07..74b19f5615 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/duration.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/duration.pb.h" diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index 575f3d3595..d8abeac48b 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/duration.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fduration_2eproto_2epb_2eh #define google_2fprotobuf_2fduration_2eproto_2epb_2eh diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 851ad8ac4b..087a4232a3 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/empty.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/empty.pb.h" diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h index f20b653a2c..c98ee5a30e 100644 --- a/src/google/protobuf/empty.pb.h +++ b/src/google/protobuf/empty.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/empty.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fempty_2eproto_2epb_2eh #define google_2fprotobuf_2fempty_2eproto_2epb_2eh diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index bb68a2931c..035e9604c2 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/field_mask.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/field_mask.pb.h" diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index 9d3f333097..18aeceb1a9 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/field_mask.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh #define google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh diff --git a/src/google/protobuf/json/BUILD b/src/google/protobuf/json/BUILD index 2ab38bce82..1823c07baf 100644 --- a/src/google/protobuf/json/BUILD +++ b/src/google/protobuf/json/BUILD @@ -111,7 +111,6 @@ cc_library( "//src/google/protobuf/stubs", "@abseil-cpp//absl/algorithm:container", "@abseil-cpp//absl/log:absl_check", - "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/status", "@abseil-cpp//absl/status:statusor", "@abseil-cpp//absl/strings", @@ -293,7 +292,6 @@ cc_library( "//src/google/protobuf/io:zero_copy_sink", "//src/google/protobuf/stubs", "//src/google/protobuf/util:type_resolver", - "@abseil-cpp//absl/container:flat_hash_map", "@abseil-cpp//absl/log:absl_check", "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/status", @@ -316,6 +314,11 @@ proto_library( testonly = True, srcs = ["json_enumval_custom_string.proto"], strip_import_prefix = "/src", + visibility = [ + "//:__subpackages__", + "//src/google/protobuf:__subpackages__", + "//upb:__subpackages__", + ], deps = ["//src/google/protobuf:json_options_proto"], ) diff --git a/src/google/protobuf/json/json_enumval_custom_string.proto b/src/google/protobuf/json/json_enumval_custom_string.proto index 317d19a805..980e091454 100644 --- a/src/google/protobuf/json/json_enumval_custom_string.proto +++ b/src/google/protobuf/json/json_enumval_custom_string.proto @@ -24,6 +24,7 @@ enum Armor { ARMOR_SABATON = 7 [(pb.enumvalue.json).string = "sabaton"]; ARMOR_SOLLERET = 7 [(pb.enumvalue.json).string = "sabaton"]; ARMOR_HACHI_MAI_DO = 8 [(pb.enumvalue.json).string = "8"]; + ARMOR_GREAVES = 9 [(pb.enumvalue.json).string = "ARMOR_GREAVES"]; } message Knight { diff --git a/src/google/protobuf/json_enumvalue_options.pb.cc b/src/google/protobuf/json_enumvalue_options.pb.cc index 9a01a0ff9b..4cbfbdc47f 100644 --- a/src/google/protobuf/json_enumvalue_options.pb.cc +++ b/src/google/protobuf/json_enumvalue_options.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/json_enumvalue_options.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/json_enumvalue_options.pb.h" @@ -212,8 +212,8 @@ const char descriptor_table_protodef_google_2fprotobuf_2fjson_5fenumvalue_5fopti "scriptor.proto\"(\n\024JsonEnumValueOptions\022\016" "\n\006string\030\001 \001(\tX\001:\\\n\004json\022!.google.protob" "uf.EnumValueOptions\030\346\007 \001(\0132\".pb.enumvalu" - "e.JsonEnumValueOptionsB\006\262\001\003\010\352\007b\010editions" - "p\351\007" + "e.JsonEnumValueOptionsB\006\262\001\003\010\352\007B\032\n\030com.go" + "ogle.protobuf.utilb\010editionsp\351\007" }; static const ::_pbi::DescriptorTable* PROTOBUF_NONNULL const descriptor_table_google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto_deps[1] = { @@ -223,7 +223,7 @@ static ::absl::once_flag descriptor_table_google_2fprotobuf_2fjson_5fenumvalue_5 PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto = { false, false, - 243, + 271, descriptor_table_protodef_google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto, "google/protobuf/json_enumvalue_options.proto", &descriptor_table_google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto_once, diff --git a/src/google/protobuf/json_enumvalue_options.pb.h b/src/google/protobuf/json_enumvalue_options.pb.h index dbe7360e9d..03097f94a5 100644 --- a/src/google/protobuf/json_enumvalue_options.pb.h +++ b/src/google/protobuf/json_enumvalue_options.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/json_enumvalue_options.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto_2epb_2eh #define google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto_2epb_2eh diff --git a/src/google/protobuf/json_enumvalue_options.proto b/src/google/protobuf/json_enumvalue_options.proto index 34056f7b70..831919b978 100644 --- a/src/google/protobuf/json_enumvalue_options.proto +++ b/src/google/protobuf/json_enumvalue_options.proto @@ -11,6 +11,8 @@ package pb.enumvalue; import "google/protobuf/descriptor.proto"; +option java_package = "com.google.protobuf.util"; + local message JsonEnumValueOptions { // Allows user to specify a custom string to use when serializing an enum // value to JSON. diff --git a/src/google/protobuf/json_options.proto b/src/google/protobuf/json_options.proto index 60b03e2d4c..db5c745dac 100644 --- a/src/google/protobuf/json_options.proto +++ b/src/google/protobuf/json_options.proto @@ -12,3 +12,5 @@ edition = "2024"; package pb; import public "google/protobuf/json_enumvalue_options.proto"; + +option java_package = "com.google.protobuf.util"; diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index e881b85753..e0dc16e425 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -633,8 +633,10 @@ class PROTOBUF_EXPORT Reflection final { const FieldDescriptor* field) const; [[nodiscard]] std::string GetString(const Message& message, const FieldDescriptor* field) const; - [[nodiscard]] const EnumValueDescriptor* GetEnum( - const Message& message, const FieldDescriptor* field) const; + [[nodiscard]] [[deprecated( + "Please use GetEnumValue() instead. GetEnum() will be " + "removed in Q1 2027.")]] const EnumValueDescriptor* + GetEnum(const Message& message, const FieldDescriptor* field) const; // GetEnumValue() returns an enum field's value as an integer rather than // an EnumValueDescriptor*. If the integer value does not correspond to a @@ -818,8 +820,11 @@ class PROTOBUF_EXPORT Reflection final { [[nodiscard]] std::string GetRepeatedString(const Message& message, const FieldDescriptor* field, int index) const; - [[nodiscard]] const EnumValueDescriptor* GetRepeatedEnum( - const Message& message, const FieldDescriptor* field, int index) const; + [[nodiscard]] [[deprecated( + "Please use GetRepeatedEnumValue() instead. GetRepeatedEnum() will be " + "removed in Q1 2027.")]] const EnumValueDescriptor* + GetRepeatedEnum(const Message& message, const FieldDescriptor* field, + int index) const; // GetRepeatedEnumValue() returns an enum field's value as an integer rather // than an EnumValueDescriptor*. If the integer value does not correspond to a // known value descriptor, a new value descriptor is created. (Such a value diff --git a/src/google/protobuf/retention_test.cc b/src/google/protobuf/retention_test.cc index 4e0e2e0c3f..ebcf1c16d8 100644 --- a/src/google/protobuf/retention_test.cc +++ b/src/google/protobuf/retention_test.cc @@ -226,9 +226,10 @@ TEST(RetentionTest, StripSourceRetentionOptionsWithSourceCodeInfo) { *pool.FindFileByName("retention.proto"), /*include_source_code_info=*/true); + // TODO: b/168903973 - Remove once we update the format. // The number of locations is reduced by the number of stripped elements. EXPECT_EQ(file_descriptor.source_code_info().location_size(), 88); - EXPECT_EQ(stripped_file.source_code_info().location_size(), 73); + EXPECT_EQ(stripped_file.source_code_info().location_size(), 63); } TEST(RetentionTest, RemoveEmptyOptions) { diff --git a/src/google/protobuf/runtime_version.h b/src/google/protobuf/runtime_version.h index 2977328a8e..687407a384 100644 --- a/src/google/protobuf/runtime_version.h +++ b/src/google/protobuf/runtime_version.h @@ -19,7 +19,7 @@ // The OSS versions are not stripped to avoid merging conflicts. #define PROTOBUF_OSS_VERSION 7036000 -#define PROTOBUF_OSS_VERSION_SUFFIX "-dev" +#define PROTOBUF_OSS_VERSION_SUFFIX "-rc2" #define PROTOBUF_VERSION PROTOBUF_OSS_VERSION #define PROTOBUF_VERSION_SUFFIX PROTOBUF_OSS_VERSION_SUFFIX diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index bd88c64b77..adc8af801e 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/source_context.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/source_context.pb.h" diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index 51fdf67503..acc9812f57 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/source_context.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh #define google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index b239ade12f..769e29aabe 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/struct.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/struct.pb.h" diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index c1d392209b..c85bc9d31d 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/struct.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fstruct_2eproto_2epb_2eh #define google_2fprotobuf_2fstruct_2eproto_2epb_2eh diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index b8930fa066..fd8a304455 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -47,7 +47,7 @@ namespace internal { #define GOOGLE_PROTOBUF_VERSION 7036000 // A suffix string for alpha, beta or rc releases. Empty for stable releases. -#define GOOGLE_PROTOBUF_VERSION_SUFFIX "-dev" +#define GOOGLE_PROTOBUF_VERSION_SUFFIX "-rc2" // Verifies that the protobuf version a program was compiled with matches what // it is linked/running with. Use the macro below to call this function. diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index b8b6380057..91cf842808 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/timestamp.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/timestamp.pb.h" diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index 0d5026f944..8bdb7f5ddc 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/timestamp.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh #define google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index a4ea02938d..001d734062 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/type.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/type.pb.h" diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index c3f5272238..a022a43ff2 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/type.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2ftype_2eproto_2epb_2eh #define google_2fprotobuf_2ftype_2eproto_2epb_2eh diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index 56d76d8c4f..e345a3aaa0 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/wrappers.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #include "google/protobuf/wrappers.pb.h" diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index 4b1b67b7f4..53edfcf909 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/wrappers.proto -// Protobuf C++ Version: 7.36.0-dev +// Protobuf C++ Version: 7.36.0-rc2 #ifndef google_2fprotobuf_2fwrappers_2eproto_2epb_2eh #define google_2fprotobuf_2fwrappers_2eproto_2epb_2eh diff --git a/upb/BUILD b/upb/BUILD index 46e15d01a5..b33477efda 100644 --- a/upb/BUILD +++ b/upb/BUILD @@ -32,8 +32,10 @@ UPB_CONFIG_VISIBILITY = [ "//hpb_generator:__subpackages__", "//lua:__pkg__", "//python:__pkg__", + "//src/google/protobuf/compiler:__subpackages__", "//upb:__subpackages__", "//upb_generator:__subpackages__", + "//src/google/protobuf/compiler:__subpackages__", ] config_setting( @@ -159,6 +161,8 @@ upb_amalgamation( ":generated_code_support", "//src/google/protobuf:descriptor_upb_c_proto", "//src/google/protobuf:descriptor_upb_minitable_proto", + "//src/google/protobuf:json_enumvalue_options_upb_c_proto", + "//src/google/protobuf:json_enumvalue_options_upb_minitable_proto", "//upb/base", "//upb/base:internal", "//upb/hash:hash", @@ -179,6 +183,7 @@ upb_amalgamation( "//upb/port", "//upb/reflection", "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:json_enumvalue_options_upb_proto", "//upb/reflection:internal", "//upb/text:debug", "//upb/text:internal", @@ -216,6 +221,9 @@ upb_amalgamation( "//src/google/protobuf:descriptor_upb_c_proto", "//src/google/protobuf:descriptor_upb_minitable_proto", "//src/google/protobuf:descriptor_upb_reflection_proto", + "//src/google/protobuf:json_enumvalue_options_upb_c_proto", + "//src/google/protobuf:json_enumvalue_options_upb_minitable_proto", + "//src/google/protobuf:json_enumvalue_options_upb_reflection_proto", "//upb/base", "//upb/base:internal", "//upb/hash:hash", @@ -237,6 +245,7 @@ upb_amalgamation( "//upb/port", "//upb/reflection", "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:json_enumvalue_options_upb_proto", "//upb/reflection:internal", "//upb/wire", "//upb/wire:back_alloc", @@ -271,6 +280,8 @@ upb_amalgamation( ":generated_code_support", "//src/google/protobuf:descriptor_upb_c_proto", "//src/google/protobuf:descriptor_upb_minitable_proto", + "//src/google/protobuf:json_enumvalue_options_upb_c_proto", + "//src/google/protobuf:json_enumvalue_options_upb_minitable_proto", "//upb/base", "//upb/base:internal", "//upb/hash:hash", @@ -292,6 +303,7 @@ upb_amalgamation( "//upb/port", "//upb/reflection", "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:json_enumvalue_options_upb_proto", "//upb/reflection:internal", "//upb/util:def_to_proto", "//upb/wire", @@ -336,6 +348,7 @@ filegroup( filegroup( name = "test_protos", + testonly = 1, srcs = [ "//src/google/protobuf:test_messages_proto2.proto", "//src/google/protobuf:test_messages_proto3.proto", diff --git a/upb/cmake/BUILD.bazel b/upb/cmake/BUILD.bazel index 7a574374ed..d035a12c33 100644 --- a/upb/cmake/BUILD.bazel +++ b/upb/cmake/BUILD.bazel @@ -26,11 +26,16 @@ genrule( srcs = [ "//src/google/protobuf:descriptor_upb_c_proto", "//src/google/protobuf:descriptor_upb_minitable_proto", + "//src/google/protobuf:json_enumvalue_options_upb_c_proto", + "//src/google/protobuf:json_enumvalue_options_upb_minitable_proto", ], outs = [ "generated-in/google/protobuf/descriptor.upb.h", "generated-in/google/protobuf/descriptor.upb_minitable.c", "generated-in/google/protobuf/descriptor.upb_minitable.h", + "generated-in/google/protobuf/json_enumvalue_options.upb.h", + "generated-in/google/protobuf/json_enumvalue_options.upb_minitable.c", + "generated-in/google/protobuf/json_enumvalue_options.upb_minitable.h", ], cmd = "cp $(SRCS) $(@D)/generated-in/google/protobuf", ) diff --git a/upb/json/BUILD b/upb/json/BUILD index 1c766f2c0d..d41037ecb1 100644 --- a/upb/json/BUILD +++ b/upb/json/BUILD @@ -42,6 +42,8 @@ cc_test( srcs = ["decode_test.cc"], deps = [ ":json", + ":json_enumval_custom_string_upb_proto", + ":json_enumval_custom_string_upb_reflection_proto", ":test_upb_proto", ":test_upb_proto_reflection", "//:any_upb_proto", @@ -49,6 +51,7 @@ cc_test( "//:struct_upb_proto", "//upb/base", "//upb/mem", + "//upb/message", "//upb/reflection", "@googletest//:gtest", "@googletest//:gtest_main", @@ -60,6 +63,8 @@ cc_test( srcs = ["encode_test.cc"], deps = [ ":json", + ":json_enumval_custom_string_upb_proto", + ":json_enumval_custom_string_upb_reflection_proto", ":test_upb_proto", ":test_upb_proto_reflection", "//:any_upb_proto", @@ -67,6 +72,7 @@ cc_test( "//:struct_upb_proto", "//upb/base", "//upb/mem", + "//upb/message", "//upb/reflection", "@googletest//:gtest", "@googletest//:gtest_main", @@ -96,6 +102,18 @@ upb_proto_reflection_library( deps = [":test_proto"], ) +upb_c_proto_library( + name = "json_enumval_custom_string_upb_proto", + testonly = 1, + deps = ["//src/google/protobuf/json:json_enumval_custom_string_proto"], +) + +upb_proto_reflection_library( + name = "json_enumval_custom_string_upb_reflection_proto", + testonly = 1, + deps = ["//src/google/protobuf/json:json_enumval_custom_string_proto"], +) + filegroup( name = "test_srcs", srcs = glob( @@ -109,10 +127,15 @@ filegroup( filegroup( name = "test_protos", + testonly = 1, srcs = glob( [ "**/*test.proto", ], - ), + ) + [ + "//src/google/protobuf:json_enumvalue_options.proto", + "//src/google/protobuf:json_options.proto", + "//src/google/protobuf/json:json_enumval_custom_string_proto_srcs", + ], visibility = ["//upb:__pkg__"], ) diff --git a/upb/json/decode.c b/upb/json/decode.c index 39fcdf124b..d168797ab2 100644 --- a/upb/json/decode.c +++ b/upb/json/decode.c @@ -830,7 +830,7 @@ static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { upb_StringView str = jsondec_string(d); const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); const upb_EnumValueDef* ev = - upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); + upb_EnumDef_FindByJsonNameWithSize(e, str.data, str.size); upb_JsonMessageValue val = {.ignore = false}; if (ev) { val.value.int32_val = upb_EnumValueDef_Number(ev); diff --git a/upb/json/decode_test.cc b/upb/json/decode_test.cc index 719296da0c..777484d1ad 100644 --- a/upb/json/decode_test.cc +++ b/upb/json/decode_test.cc @@ -7,38 +7,61 @@ #include "upb/json/decode.h" +#include #include #include -#include "google/protobuf/struct.upb.h" #include +#include "google/protobuf/json/json_enumval_custom_string.upb.h" +#include "google/protobuf/json/json_enumval_custom_string.upbdefs.h" #include "upb/base/status.hpp" #include "upb/base/upcast.h" #include "upb/json/test.upb.h" #include "upb/json/test.upbdefs.h" #include "upb/mem/arena.h" #include "upb/mem/arena.hpp" +#include "upb/message/message.h" +#include "upb/reflection/def.h" #include "upb/reflection/def.hpp" -static upb_test_Box* JsonDecode(const char* json, upb_Arena* a) { +static bool JsonDecodeGeneric(const char* json, upb_Message* msg, + const upb_MessageDef* (*getmsgdef)(upb_DefPool*), + upb_Arena* arena) { upb::Status status; upb::DefPool defpool; - upb::MessageDefPtr m(upb_test_Box_getmsgdef(defpool.ptr())); - EXPECT_TRUE(m.ptr() != nullptr); + const upb_MessageDef* m = getmsgdef(defpool.ptr()); + EXPECT_TRUE(m != nullptr); - upb_test_Box* box = upb_test_Box_new(a); int options = 0; - bool ok = upb_JsonDecode(json, strlen(json), UPB_UPCAST(box), m.ptr(), - defpool.ptr(), options, a, status.ptr()); - return ok ? box : nullptr; + return upb_JsonDecode(json, strlen(json), msg, m, defpool.ptr(), options, + arena, status.ptr()); +} + +static upb_test_Box* JsonDecode(const char* json, upb_Arena* a) { + upb_test_Box* box = upb_test_Box_new(a); + if (JsonDecodeGeneric(json, UPB_UPCAST(box), upb_test_Box_getmsgdef, a)) { + return box; + } + return nullptr; +} + +static json_enumval_custom_string_Knight* JsonDecodeKnight(const char* json, + upb_Arena* a) { + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a); + if (JsonDecodeGeneric(json, UPB_UPCAST(knight), + json_enumval_custom_string_Knight_getmsgdef, a)) { + return knight; + } + return nullptr; } struct FloatTest { - const std::string json; + const char* json; float f; }; -static const std::vector FloatTestsPass = { +static const FloatTest kFloatTestsPass[] = { {R"({"f": 0})", 0}, {R"({"f": 1})", 1}, {R"({"f": 1.000000})", 1}, @@ -53,7 +76,7 @@ static const std::vector FloatTestsPass = { -340282346638528859811704183484516925440.0}, }; -static const std::vector FloatTestsFail = { +static const FloatTest kFloatTestsFail[] = { {R"({"f": 1z})", 0}, {R"({"f": 3.4028236e+38})", 0}, {R"({"f": -3.4028236e+38})", 0}, @@ -63,15 +86,15 @@ static const std::vector FloatTestsFail = { TEST(JsonTest, DecodeFloats) { upb::Arena a; - for (const auto& test : FloatTestsPass) { - upb_test_Box* box = JsonDecode(test.json.c_str(), a.ptr()); + for (const auto& test : kFloatTestsPass) { + upb_test_Box* box = JsonDecode(test.json, a.ptr()); EXPECT_NE(box, nullptr); float f = upb_test_Box_f(box); EXPECT_EQ(f, test.f); } - for (const auto& test : FloatTestsFail) { - upb_test_Box* box = JsonDecode(test.json.c_str(), a.ptr()); + for (const auto& test : kFloatTestsFail) { + upb_test_Box* box = JsonDecode(test.json, a.ptr()); EXPECT_EQ(box, nullptr); } } @@ -111,6 +134,181 @@ TEST(JsonTest, RejectsBase64WithHighBitBytes) { EXPECT_EQ(box, nullptr); } +// Test decoding when the enum value has no custom string option set, falling +// back to the default enum value name. +TEST(JsonTest, DecodeEnumMissingCustomStringOption) { + upb::Arena a; + std::string json = R"({"armor":"ARMOR_GORGET"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GORGET, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when a standard custom string option is provided. +TEST(JsonTest, DecodeEnumWithCustomString) { + upb::Arena a; + std::string json = R"({"armor":"gr8 helm"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when the custom string option contains escaped double quotes. +TEST(JsonTest, DecodeEnumCustomStringWithEscapedQuotes) { + upb::Arena a; + std::string json = "{\"armor\":\"a\\\"b\"}"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GAUNTLET, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when the custom string option is an empty string (""). +TEST(JsonTest, DecodeEnumEmptyCustomString) { + upb::Arena a; + std::string json = R"({"armor":""})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_COIF, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when the custom string option contains escaped control +// characters (tab and newline). +TEST(JsonTest, DecodeEnumCustomStringWithEscapedControlChars) { + upb::Arena a; + std::string json = R"({"armor":"p\taul\ndron"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_PAULDRON, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding an enum value passed as a raw integer literal. +TEST(JsonTest, DecodeEnumFromIntegerLiteral) { + upb::Arena a; + std::string json = R"({"armor":1})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding by raw enum name even when a custom string option is defined. +TEST(JsonTest, DecodeEnumRawNameWhenCustomStringDefined) { + upb::Arena a; + std::string json = R"({"armor":"ARMOR_GREAT_HELM"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when the custom string option is enclosed within double quotes. +TEST(JsonTest, DecodeEnumCustomStringEnclosedInQuotes) { + upb::Arena a; + std::string json = "{\"armor\":\"\\\"plate\\\"\"}"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_PLATE, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding a custom string that maps to aliased enum values. +TEST(JsonTest, DecodeEnumAliasedCustomString) { + upb::Arena a; + std::string json = R"({"armor":"sabaton"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_SABATON, + json_enumval_custom_string_Knight_armor(knight)); + EXPECT_EQ(json_enumval_custom_string_ARMOR_SOLLERET, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding when the custom string option consists of numeric digits ("8"). +TEST(JsonTest, DecodeEnumNumericCustomString) { + upb::Arena a; + std::string json = R"({"armor":"8"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_HACHI_MAI_DO, + json_enumval_custom_string_Knight_armor(knight)); +} + +// Test decoding an enum value whose custom string option is identical to its +// original enum value name. Also verify that normal name lookup by original +// name is not marked as JSON-only. +TEST(JsonTest, DecodeEnumCustomStringSameAsName) { + upb::Arena a; + std::string json = R"({"armor":"ARMOR_GREAVES"})"; + json_enumval_custom_string_Knight* knight = + JsonDecodeKnight(json.c_str(), a.ptr()); + EXPECT_NE(knight, nullptr); + EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAVES, + json_enumval_custom_string_Knight_armor(knight)); + + upb::DefPool defpool; + const upb_MessageDef* m = + json_enumval_custom_string_Knight_getmsgdef(defpool.ptr()); + ASSERT_NE(m, nullptr); + const upb_FieldDef* f = upb_MessageDef_FindFieldByName(m, "armor"); + ASSERT_NE(f, nullptr); + const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); + ASSERT_NE(e, nullptr); + const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, "ARMOR_GREAVES"); + ASSERT_NE(ev, nullptr); + EXPECT_EQ(upb_EnumValueDef_Number(ev), + json_enumval_custom_string_ARMOR_GREAVES); +} + +// Test that decoding fails on case mismatch against a custom string. +TEST(JsonTest, DecodeEnumCustomStringCaseMismatchFails) { + upb::Arena a; + std::string json = "{\"armor\":\"A\\\"b\"}"; + EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr); +} + +// Test that decoding fails on case mismatch against a raw enum name. +TEST(JsonTest, DecodeEnumRawNameCaseMismatchFails) { + upb::Arena a; + std::string json = R"({"armor":"armor_GAUNtlet"})"; + EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr); +} + +// Test that decoding fails on an unknown enum value string. +TEST(JsonTest, DecodeEnumUnknownStringFails) { + upb::Arena a; + std::string json = R"({"armor":"UNKNOWN_1"})"; + EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr); +} + +// Test that decoding fails when the JSON payload is an array. +TEST(JsonTest, DecodeEnumInvalidArrayPayloadFails) { + upb::Arena a; + std::string json = R"({"armor":["gr8 helm"]})"; + EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr); +} + +// Test that decoding fails when the JSON payload is a boolean. +TEST(JsonTest, DecodeEnumInvalidBooleanPayloadFails) { + upb::Arena a; + std::string json = R"({"armor":true})"; + EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr); +} + #include "upb/mem/alloc.h" struct FailAfterAlloc { diff --git a/upb/json/encode.c b/upb/json/encode.c index 3bc2f04d58..c0cd54f82f 100644 --- a/upb/json/encode.c +++ b/upb/json/encode.c @@ -7,16 +7,25 @@ #include "upb/json/encode.h" -#include #include #include #include +#include #include +#include #include +#include "upb/base/descriptor_constants.h" +#include "upb/base/status.h" +#include "upb/base/string_view.h" #include "upb/lex/round_trip.h" +#include "upb/mem/arena.h" +#include "upb/message/array.h" #include "upb/message/map.h" +#include "upb/message/message.h" +#include "upb/mini_table/message.h" #include "upb/port/vsnprintf_compat.h" +#include "upb/reflection/def.h" #include "upb/reflection/message.h" #include "upb/wire/decode.h" @@ -44,6 +53,7 @@ static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m, bool first); static void jsonenc_value(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m); +static void jsonenc_string(jsonenc* e, upb_StringView str); UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { upb_Status_SetErrorMessage(e->status, msg); @@ -205,7 +215,8 @@ static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { : upb_EnumDef_FindValueByNumber(e_def, val); if (ev) { - jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); + const char* name = upb_EnumValueDef_JsonName(ev); + jsonenc_string(e, upb_StringView_FromString(name)); } else { jsonenc_printf(e, "%" PRId32, val); } diff --git a/upb/json/encode_test.cc b/upb/json/encode_test.cc index 42ce6dde4d..9f2b30f0c8 100644 --- a/upb/json/encode_test.cc +++ b/upb/json/encode_test.cc @@ -12,31 +12,47 @@ #include "google/protobuf/struct.upb.h" #include +#include "google/protobuf/json/json_enumval_custom_string.upb.h" +#include "google/protobuf/json/json_enumval_custom_string.upbdefs.h" #include "upb/base/status.hpp" #include "upb/base/upcast.h" #include "upb/json/test.upb.h" #include "upb/json/test.upbdefs.h" #include "upb/mem/arena.h" #include "upb/mem/arena.hpp" +#include "upb/message/message.h" +#include "upb/reflection/def.h" #include "upb/reflection/def.hpp" -static std::string JsonEncode(const upb_test_Box* msg, int options) { +static std::string JsonEncodeGeneric( + const upb_Message* msg, const upb_MessageDef* (*getmsgdef)(upb_DefPool*), + int options) { upb::Arena a; upb::Status status; upb::DefPool defpool; - upb::MessageDefPtr m(upb_test_Box_getmsgdef(defpool.ptr())); - EXPECT_TRUE(m.ptr() != nullptr); + const upb_MessageDef* m = getmsgdef(defpool.ptr()); + EXPECT_TRUE(m != nullptr); - size_t json_size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(), - options, nullptr, 0, status.ptr()); + size_t json_size = + upb_JsonEncode(msg, m, defpool.ptr(), options, nullptr, 0, status.ptr()); char* json_buf = (char*)upb_Arena_Malloc(a.ptr(), json_size + 1); - size_t size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(), options, - json_buf, json_size + 1, status.ptr()); + size_t size = upb_JsonEncode(msg, m, defpool.ptr(), options, json_buf, + json_size + 1, status.ptr()); EXPECT_EQ(size, json_size); return std::string(json_buf, json_size); } +static std::string JsonEncode(const upb_test_Box* msg, int options) { + return JsonEncodeGeneric(UPB_UPCAST(msg), upb_test_Box_getmsgdef, options); +} + +static std::string JsonEncodeKnight( + const json_enumval_custom_string_Knight* msg, int options) { + return JsonEncodeGeneric( + UPB_UPCAST(msg), json_enumval_custom_string_Knight_getmsgdef, options); +} + // Encode a single optional enum. TEST(JsonTest, EncodeEnum) { upb::Arena a; @@ -96,3 +112,111 @@ TEST(JsonTest, EncodeConflictJsonName) { upb_test_Box_set_new_value(new_box, 2); EXPECT_EQ(R"({"value":2})", JsonEncode(new_box, 0)); } + +// Test encoding when the enum value has no custom string option set, verifying +// it falls back to the default enum value name ("ARMOR_GORGET"). +TEST(JsonTest, EncodeEnumMissingCustomStringOption) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_GORGET); + EXPECT_EQ(R"({"armor":"ARMOR_GORGET"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when a standard custom string option is defined ("gr8 helm"). +TEST(JsonTest, EncodeEnumWithCustomString) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_GREAT_HELM); + EXPECT_EQ(R"({"armor":"gr8 helm"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when the custom string option contains double quotes requiring +// escaping ("a\"b"). +TEST(JsonTest, EncodeEnumCustomStringWithEscapedQuotes) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_GAUNTLET); + EXPECT_EQ("{\"armor\":\"a\\\"b\"}", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when the custom string option is enclosed within double quotes +// ("\"plate\""). +TEST(JsonTest, EncodeEnumCustomStringEnclosedInQuotes) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_PLATE); + EXPECT_EQ("{\"armor\":\"\\\"plate\\\"\"}", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when the custom string option is an empty string (""). +TEST(JsonTest, EncodeEnumEmptyCustomString) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_COIF); + EXPECT_EQ(R"({"armor":""})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when the custom string option contains control characters (tab +// and newline) requiring escaping ("p\taul\ndron"). +TEST(JsonTest, EncodeEnumCustomStringWithEscapedControlChars) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_PAULDRON); + EXPECT_EQ(R"({"armor":"p\taul\ndron"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding an enum value that has aliased values sharing a custom string +// option ("sabaton"). +TEST(JsonTest, EncodeEnumAliasedCustomString) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_SABATON); + EXPECT_EQ(R"({"armor":"sabaton"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when the custom string option consists of numeric digits ("8"). +TEST(JsonTest, EncodeEnumNumericCustomString) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_HACHI_MAI_DO); + EXPECT_EQ(R"({"armor":"8"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding an enum value whose custom string option is identical to its +// original enum value name. +TEST(JsonTest, EncodeEnumCustomStringSameAsName) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_GREAVES); + EXPECT_EQ(R"({"armor":"ARMOR_GREAVES"})", JsonEncodeKnight(knight, 0)); +} + +// Test encoding when upb_JsonEncode_FormatEnumsAsIntegers is set, verifying +// integer format option overrides the custom string option. +TEST(JsonTest, EncodeEnumWithIntegerFormatOverride) { + upb::Arena a; + json_enumval_custom_string_Knight* knight = + json_enumval_custom_string_Knight_new(a.ptr()); + json_enumval_custom_string_Knight_set_armor( + knight, json_enumval_custom_string_ARMOR_GREAT_HELM); + EXPECT_EQ(R"({"armor":1})", + JsonEncodeKnight(knight, upb_JsonEncode_FormatEnumsAsIntegers)); +} diff --git a/upb/port/def.inc b/upb/port/def.inc index 621ff38349..00446964f9 100644 --- a/upb/port/def.inc +++ b/upb/port/def.inc @@ -42,6 +42,13 @@ #define UPB_GNUC_MIN(x, y) 0 #endif +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define UPB_CLANG_MIN(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define UPB_CLANG_MIN(x, y) 0 +#endif + // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. @@ -606,10 +613,12 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name; \ - extern type __stop_linkarr_##name; \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name; \ + extern type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -620,13 +629,15 @@ Error, UINTPTR_MAX is undefined #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS -#define UPB_LINKARR_DECLARE(name, type) \ - extern type __start_linkarr_##name __asm( \ - "section$start$__DATA$__la_" #name); \ - extern type __stop_linkarr_##name __asm( \ - "section$end$__DATA$" \ - "__la_" #name); \ - UPB_LINKARR_APPEND(name) \ +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)"); \ + extern type __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) @@ -664,7 +675,9 @@ Error, UINTPTR_MAX is undefined // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) -#define UPB_LINKARR_DECLARE(name, type) +#define UPB_LINKARR_DECLARE(name, type) \ + UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ + "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) @@ -681,11 +694,46 @@ Error, UINTPTR_MAX is undefined #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif -#if defined(__ELF__) || defined(__wasm__) || defined(__MACH__) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define _UPB_STRINGIFY2(x) #x +#define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) + +#if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) +/* + * Workaround for b/456308964 and b/456317163. Although weak constructors + * resolve to a single function body, Clang still emits a pointer into + * .init_array for every translation unit, causing the constructor to be + * executed multiple times and inflating binary size. We wrap the .init_array + * entry in a COMDAT group (using inline assembly) to force the linker to + * deduplicate the pointer to exactly one instance. %cc is used in preference to + * the more widely available %c because %c may under some circumstances still + * output a function name including relocation information, which will then + * confuse the linker. This was only a problem on gcc; when %cc was introduced + * to clang it was just an alias to %c, and clang's %c had already done the + * checks that %cc introduced to gcc. + * References: + * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa + * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 + */ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ + __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ + void) { \ + __asm__ volatile( \ + ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ + ".dc.a %cc0\n" \ + ".popsection\n" \ + : \ + : "X"(UPB_PRIVATE(name))); \ + __VA_ARGS__ \ + } +#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ + defined(__MINGW32__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ - name)(void) + name)(void) { \ + __VA_ARGS__ \ + } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 @@ -696,17 +744,22 @@ Error, UINTPTR_MAX is undefined * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) -#define UPB_CONSTRUCTOR(name, unique_name) \ +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ - static void __cdecl UPB_PRIVATE(name)(void) - + static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. -#define UPB_CONSTRUCTOR(name, unique_name) static void UPB_PRIVATE(name)(void) +#if defined(__GNUC__) || defined(__clang__) +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#else +#define UPB_CONSTRUCTOR(name, unique_name, ...) \ + static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } +#endif #endif // @@ -744,9 +797,9 @@ Error, UINTPTR_MAX is undefined #elif defined(__ELF__) || defined(__wasm__) -// On ELF, weak aliases work properly, so we can have all weak MiniTables point -// to the same empty singleton MiniTable. This reduces code size if many -// MiniTables are tree shaken. + // On ELF, weak aliases work properly, so we can have all weak MiniTables + // point to the same empty singleton MiniTable. This reduces code size if many + // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ diff --git a/upb/port/undef.inc b/upb/port/undef.inc index 79391ba03c..a2bf8a6be0 100644 --- a/upb/port/undef.inc +++ b/upb/port/undef.inc @@ -64,6 +64,7 @@ #undef UPB_TSAN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN +#undef UPB_CLANG_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME #undef UPB_DESC_MINITABLE #undef UPB_IS_GOOGLE3 @@ -90,3 +91,6 @@ #undef UPB_DEPRECATE_AND_INLINE #undef UPB_MAYBE_ASSUME #undef UPB_ATTR_CONST +#undef _UPB_STRINGIFY +#undef _UPB_STRINGIFY2 +#undef UPB_CONSTRUCTOR diff --git a/upb/reflection/BUILD b/upb/reflection/BUILD index 8c99c216c7..ea67a152d4 100644 --- a/upb/reflection/BUILD +++ b/upb/reflection/BUILD @@ -34,6 +34,19 @@ bootstrap_upb_proto_library( strip_prefix = "third_party/protobuf/github/bootstrap/src", ) +bootstrap_upb_proto_library( + name = "json_enumvalue_options_upb_proto", + bootstrap_hdr = "json_enumvalue_options_bootstrap.h", + proto_lib_deps = ["//src/google/protobuf:json_enumvalue_options_proto"], + src_files = ["google/protobuf/json_enumvalue_options.proto"], + src_rules = [ + "//:descriptor_proto_srcs", + "//:json_enumvalue_options_proto_srcs", + ], + strip_prefix = "third_party/protobuf/github/bootstrap/src", + deps = [":descriptor_upb_proto"], +) + bootstrap_cc_library( name = "reflection", hdrs = [ @@ -122,7 +135,10 @@ bootstrap_cc_library( "oneof_def.h", "service_def.h", ], - bootstrap_deps = [":descriptor_upb_proto"], + bootstrap_deps = [ + ":descriptor_upb_proto", + ":json_enumvalue_options_upb_proto", + ], copts = UPB_DEFAULT_COPTS, features = UPB_DEFAULT_FEATURES, visibility = ["//visibility:public"], diff --git a/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.c b/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.c index ca3672b1db..7cb063b8f0 100644 --- a/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.c +++ b/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.c @@ -1620,7 +1620,7 @@ const upb_MiniTableEnum google__protobuf__SymbolVisibility_enum_init = { }, }; -static const upb_MiniTable *messages_layout[35] = { +static const upb_MiniTable *messages_layout_google_protobuf_descriptor_proto_upb_file_layout[35] = { &google__protobuf__FileDescriptorSet_msg_init, &google__protobuf__FileDescriptorProto_msg_init, &google__protobuf__DescriptorProto_msg_init, @@ -1658,7 +1658,7 @@ static const upb_MiniTable *messages_layout[35] = { &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, }; -static const upb_MiniTableEnum *enums_layout[21] = { +static const upb_MiniTableEnum *enums_layout_google_protobuf_descriptor_proto_upb_file_layout[21] = { &google__protobuf__Edition_enum_init, &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init, &google__protobuf__FeatureSet__EnforceNamingStyle_enum_init, @@ -1683,8 +1683,8 @@ static const upb_MiniTableEnum *enums_layout[21] = { }; const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { - messages_layout, - enums_layout, + messages_layout_google_protobuf_descriptor_proto_upb_file_layout, + enums_layout_google_protobuf_descriptor_proto_upb_file_layout, NULL, 35, 21, diff --git a/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb.h b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb.h new file mode 100644 index 0000000000..5aa718f41e --- /dev/null +++ b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb.h @@ -0,0 +1,134 @@ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ + +#include "upb/generated_code_support.h" +#include "google/protobuf/json_enumvalue_options.upb_minitable.h" +#include "google/protobuf/descriptor.upb_minitable.h" + +// Must be last. +#include "upb/port/def.inc" + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct pb_enumvalue_JsonEnumValueOptions { + upb_Message UPB_PRIVATE(base); +} pb_enumvalue_JsonEnumValueOptions; + +struct google_protobuf_EnumValueOptions; + + + +/* pb.enumvalue.JsonEnumValueOptions */ +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_new(upb_Arena* arena) { + return (pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse(const char* buf, size_t size, + upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, NULL, 0, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse_ex( + const char* buf, size_t size, const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &pb__enumvalue__JsonEnumValueOptions_msg_init, extreg, + options, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize(const pb_enumvalue_JsonEnumValueOptions* msg, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize_ex(const pb_enumvalue_JsonEnumValueOptions* msg, + int options, upb_Arena* arena, + size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &pb__enumvalue__JsonEnumValueOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_clear_string(pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView pb_enumvalue_JsonEnumValueOptions_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool pb_enumvalue_JsonEnumValueOptions_has_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_set_string(pb_enumvalue_JsonEnumValueOptions* msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message*)msg, &field, &value); +} + +UPB_INLINE bool pb_enumvalue_has_json(const struct google_protobuf_EnumValueOptions* msg) { + return upb_Message_HasExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} + +UPB_INLINE void pb_enumvalue_clear_json(struct google_protobuf_EnumValueOptions* msg) { + upb_Message_ClearExtension((upb_Message*)msg, pb_enumvalue_json_ext); +} +UPB_INLINE const pb_enumvalue_JsonEnumValueOptions* +pb_enumvalue_json(const struct google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + const pb_enumvalue_JsonEnumValueOptions* default_val = NULL; + const pb_enumvalue_JsonEnumValueOptions* ret; + _upb_Message_GetExtensionField((upb_Message*)msg, ext, &default_val, &ret); + return ret; +} + +UPB_INLINE void pb_enumvalue_set_json(struct google_protobuf_EnumValueOptions* msg, + const pb_enumvalue_JsonEnumValueOptions* val, + upb_Arena* arena) { + const upb_MiniTableExtension* ext = pb_enumvalue_json_ext; + UPB_ASSUME(upb_MiniTableField_IsScalar(&ext->UPB_PRIVATE(field))); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)( + &ext->UPB_PRIVATE(field)) == UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + bool ok = upb_Message_SetExtension((upb_Message*)msg, ext, &val, arena); + UPB_ASSERT(ok); +} +UPB_INLINE struct pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_mutable_json( + struct google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct pb_enumvalue_JsonEnumValueOptions* sub = (struct pb_enumvalue_JsonEnumValueOptions*)pb_enumvalue_json(msg); + if (sub == NULL) { + sub = (struct pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(&pb__enumvalue__JsonEnumValueOptions_msg_init, arena); + if (sub) pb_enumvalue_set_json(msg, sub, arena); + } + return sub; +} +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#include "upb/port/undef.inc" + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ */ diff --git a/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.c b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.c new file mode 100644 index 0000000000..0b22505851 --- /dev/null +++ b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.c @@ -0,0 +1,79 @@ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#include +#include "upb/generated_code_support.h" +#include "google/protobuf/json_enumvalue_options.upb_minitable.h" +#include "google/protobuf/descriptor.upb_minitable.h" + +// Must be last. +#include "upb/port/def.inc" + +extern const UPB_PRIVATE(upb_GeneratedExtensionListEntry)* UPB_PRIVATE(upb_generated_extension_list); +typedef struct { + upb_MiniTableField fields[1]; +} pb__enumvalue__JsonEnumValueOptions_msg_init_Fields; + +static const pb__enumvalue__JsonEnumValueOptions_msg_init_Fields pb_enumvalue_JsonEnumValueOptions__fields = {{ + {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}}; + +const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init = { + &pb_enumvalue_JsonEnumValueOptions__fields.fields[0], + UPB_SIZE(24, 32), 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "pb.enumvalue.JsonEnumValueOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeUnknown}, + {0x001000000000000a, &upb_DecodeFast_String_Scalar_Tag1Byte}, + }) +}; + +static const upb_MiniTableExtension pb_enumvalue_json_ext_obj = { + {998, 0, 0, UPB_SIZE(3, 4), 11, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsExtension | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {.UPB_PRIVATE(submsg) = &pb__enumvalue__JsonEnumValueOptions_msg_init}, + &google__protobuf__EnumValueOptions_msg_init, + +}; +UPB_LINKARR_APPEND(upb_AllExts) +const upb_MiniTableExtension* pb_enumvalue_json_ext = &pb_enumvalue_json_ext_obj; + static const upb_MiniTable *messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb__enumvalue__JsonEnumValueOptions_msg_init, +}; + + +static const upb_MiniTableExtension *extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout[1] = { + &pb_enumvalue_json_ext_obj, +}; + +UPB_LINKARR_DECLARE(upb_AllExts, const upb_MiniTableExtension*); +UPB_CONSTRUCTOR(upb_GeneratedRegistry_Constructor, google_protobuf_json_enumvalue_options_proto_ext_constructor, { + static bool finished = false; + if (finished) return; + finished = true; + static UPB_PRIVATE(upb_GeneratedExtensionListEntry) entry = { + UPB_LINKARR_START(upb_AllExts), + UPB_LINKARR_STOP(upb_AllExts), + NULL + }; + UPB_ASSERT(entry.next == NULL); + entry.next = UPB_PRIVATE(upb_generated_extension_list); + UPB_PRIVATE(upb_generated_extension_list) = &entry; +}) +const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout = { + messages_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + NULL, + extensions_layout_google_protobuf_json_enumvalue_options_proto_upb_file_layout, + 1, + 0, + 1, +}; + +#include "upb/port/undef.inc" + diff --git a/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.h b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.h new file mode 100644 index 0000000000..97f94e9b3a --- /dev/null +++ b/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.h @@ -0,0 +1,32 @@ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ + +#include "upb/generated_code_support.h" + +// Must be last. +#include "upb/port/def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable pb__enumvalue__JsonEnumValueOptions_msg_init; +extern const upb_MiniTableExtension* pb_enumvalue_json_ext; + +extern const upb_MiniTableFile google_protobuf_json_enumvalue_options_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port/undef.inc" + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_MINITABLE_H_ */ diff --git a/upb/reflection/def.hpp b/upb/reflection/def.hpp index c088853f50..bdef384fb3 100644 --- a/upb/reflection/def.hpp +++ b/upb/reflection/def.hpp @@ -401,6 +401,7 @@ class EnumValDefPtr { int32_t number() const { return upb_EnumValueDef_Number(ptr_); } const char* full_name() const { return upb_EnumValueDef_FullName(ptr_); } + const char* json_name() const { return upb_EnumValueDef_JsonName(ptr_); } const char* name() const { return upb_EnumValueDef_Name(ptr_); } private: @@ -452,6 +453,10 @@ class EnumDefPtr { return EnumValDefPtr(upb_EnumDef_Value(ptr_, i)); } + EnumValDefPtr FindValueByJsonName(const char* name) const { + return EnumValDefPtr(upb_EnumDef_FindByJsonName(ptr_, name)); + } + // Lookups from name to integer, returning true if found. EnumValDefPtr FindValueByName(const char* name) const { return EnumValDefPtr(upb_EnumDef_FindValueByName(ptr_, name)); diff --git a/upb/reflection/enum_def.c b/upb/reflection/enum_def.c index f0b0d8069c..edf61d7f44 100644 --- a/upb/reflection/enum_def.c +++ b/upb/reflection/enum_def.c @@ -54,6 +54,28 @@ struct upb_EnumDef { bool is_sorted; // Whether all of the values are defined in ascending order. }; +// We store both regular proto enum names and custom JSON enum names in the +// same strtable (ntoi). This is safe because protoc enforces that custom JSON +// enum names never conflict with default enum names across different enum +// values (or are identical, in which case we leave the entry untagged). Because +// upb_EnumValueDef pointers are arena-aligned to at least 4 bytes (bit 0 is +// always 0 for untagged pointers), we set bit 0 to tag custom JSON-only names +// so that regular name lookups can ignore them. +static const uintptr_t kUpb_EnumDef_JsonOnlyTag = 1ULL; + +static upb_value _upb_EnumDef_TagJsonOnly(upb_value v) { + v.val |= kUpb_EnumDef_JsonOnlyTag; + return v; +} + +static bool _upb_EnumDef_IsJsonOnly(upb_value v) { + return (v.val & kUpb_EnumDef_JsonOnlyTag) != 0; +} + +static const upb_EnumValueDef* _upb_EnumDef_Untag(upb_value v) { + return (const upb_EnumValueDef*)(v.val & ~kUpb_EnumDef_JsonOnlyTag); +} + upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) { return (upb_EnumDef*)&e[i]; } @@ -62,18 +84,43 @@ const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) { return e->layout; } -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) { +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v) { const char* name = upb_EnumValueDef_Name(v); const upb_value val = upb_value_constptr(v); - bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a); - if (!ok) return false; + bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, ctx->arena); + if (!ok) _upb_DefBuilder_OomErr(ctx); - // Multiple enumerators can have the same number, first one wins. + // Aliased enum values can share the same custom JSON name, first one wins. + const char* json_name = upb_EnumValueDef_JsonName(v); + size_t json_len = strlen(json_name); + if (strcmp(json_name, name) != 0) { + upb_value existing_value; + if (upb_strtable_lookup2(&e->ntoi, json_name, json_len, &existing_value)) { + const upb_EnumValueDef* enumval = _upb_EnumDef_Untag(existing_value); + if (upb_EnumValueDef_Number(enumval) != upb_EnumValueDef_Number(v)) { + // If the custom JSON name exists, but points to a value with a + // different number, then this is a parse/conflict error. + _upb_DefBuilder_Errf(ctx, + "duplicate custom json_name (%s) in enum (%s)", + json_name, upb_EnumDef_FullName(e)); + } + } else { + upb_value json_val = _upb_EnumDef_TagJsonOnly(val); + if (!upb_strtable_insert(&e->ntoi, json_name, json_len, json_val, + ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } + } + } + + // Multiple enum values can have the same number, first one wins. const int number = upb_EnumValueDef_Number(v); if (!upb_inttable_lookup(&e->iton, number, NULL)) { - return upb_inttable_insert(&e->iton, number, val, a); + if (!upb_inttable_insert(&e->iton, number, val, ctx->arena)) { + _upb_DefBuilder_OomErr(ctx); + } } - return true; } const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) { @@ -130,6 +177,16 @@ upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) { int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; } +const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize(const upb_EnumDef* e, + const char* name, + size_t size) { + upb_value v; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + return _upb_EnumDef_Untag(v); +} + const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name) { return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name)); @@ -138,9 +195,13 @@ const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( const upb_EnumDef* e, const char* name, size_t size) { upb_value v; - return upb_strtable_lookup2(&e->ntoi, name, size, &v) - ? upb_value_getconstptr(v) - : NULL; + if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) { + return NULL; + } + if (_upb_EnumDef_IsJsonOnly(v)) { + return NULL; + } + return upb_value_getconstptr(v); } const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e, @@ -281,7 +342,7 @@ static void create_enumdef(upb_DefBuilder* ctx, const char* prefix, upb_EnumDef_FullName(e)); } - bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena); + bool ok = upb_strtable_init(&e->ntoi, n_value * 2, ctx->arena); if (!ok) _upb_DefBuilder_OomErr(ctx); ok = upb_inttable_init(&e->iton, ctx->arena); diff --git a/upb/reflection/enum_def.h b/upb/reflection/enum_def.h index 3f81ba5d18..507b9557b7 100644 --- a/upb/reflection/enum_def.h +++ b/upb/reflection/enum_def.h @@ -12,6 +12,7 @@ #include #include +#include #include "upb/base/string_view.h" #include "upb/mem/arena.h" @@ -29,6 +30,12 @@ bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num); const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e); int32_t upb_EnumDef_Default(const upb_EnumDef* e); UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e); +UPB_API const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize( + const upb_EnumDef* e, const char* name, size_t size); +UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindByJsonName( + const upb_EnumDef* e, const char* name) { + return upb_EnumDef_FindByJsonNameWithSize(e, name, strlen(name)); +} const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, const char* name); UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( diff --git a/upb/reflection/enum_value_def.c b/upb/reflection/enum_value_def.c index 0e55288a15..69499d43f6 100644 --- a/upb/reflection/enum_value_def.c +++ b/upb/reflection/enum_value_def.c @@ -20,6 +20,8 @@ #include "upb/reflection/enum_value_def.h" #include "upb/reflection/internal/def_builder.h" #include "upb/reflection/internal/enum_def.h" +#include "upb/reflection/internal/strdup2.h" +#include "upb/reflection/json_enumvalue_options_bootstrap.h" // Must be last. #include "upb/port/def.inc" @@ -29,6 +31,7 @@ struct upb_EnumValueDef { const google_protobuf_FeatureSet* resolved_features; const upb_EnumDef* parent; const char* full_name; + const char* json_name; int32_t number; }; @@ -50,7 +53,7 @@ const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v, (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*)); if (!out) return NULL; - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { out[i] = (upb_EnumValueDef*)&v[i]; } qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare); @@ -80,6 +83,10 @@ const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) { return v->full_name; } +const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v) { + return v->json_name ? v->json_name : upb_EnumValueDef_Name(v); +} + const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) { return _upb_DefBuilder_FullToShort(v->full_name); } @@ -91,6 +98,19 @@ uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) { return v - upb_EnumDef_Value(v->parent, 0); } +static const char* _upb_EnumValueDef_ExtractJsonName( + upb_DefBuilder* ctx, const upb_EnumValueDef* v) { + if (!upb_EnumValueDef_HasOptions(v)) return NULL; + const google_protobuf_EnumValueOptions* opts = (const google_protobuf_EnumValueOptions*)v->opts; + if (!pb_enumvalue_has_json(opts)) return NULL; + const pb_enumvalue_JsonEnumValueOptions* json_opts = pb_enumvalue_json(opts); + if (!json_opts || !pb_enumvalue_JsonEnumValueOptions_has_string(json_opts)) { + return NULL; + } + upb_StringView str = pb_enumvalue_JsonEnumValueOptions_string(json_opts); + return upb_strdup2(str.data, str.size, ctx->arena); +} + static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, const google_protobuf_EnumValueDescriptorProto* val_proto, const google_protobuf_FeatureSet* parent_features, @@ -105,11 +125,11 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, v->parent = e; // Must happen prior to _upb_DefBuilder_Add() v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name); v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto); + v->json_name = _upb_EnumValueDef_ExtractJsonName(ctx, v); _upb_DefBuilder_Add(ctx, v->full_name, _upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL)); - bool ok = _upb_EnumDef_Insert(e, v, ctx->arena); - if (!ok) _upb_DefBuilder_OomErr(ctx); + _upb_EnumDef_Insert(ctx, e, v); } // Allocate and initialize an array of |n| enum value defs owned by |e|. diff --git a/upb/reflection/enum_value_def.h b/upb/reflection/enum_value_def.h index a837236923..b3ab3ad975 100644 --- a/upb/reflection/enum_value_def.h +++ b/upb/reflection/enum_value_def.h @@ -10,6 +10,8 @@ #ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_ #define UPB_REFLECTION_ENUM_VALUE_DEF_H_ +#include + #include "upb/reflection/common.h" #include "upb/reflection/descriptor_bootstrap.h" @@ -24,6 +26,7 @@ const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v); const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v); bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v); uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v); +UPB_API const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v); UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v); UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v); const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options( diff --git a/upb/reflection/internal/enum_def.h b/upb/reflection/internal/enum_def.h index c963000526..65fa07825e 100644 --- a/upb/reflection/internal/enum_def.h +++ b/upb/reflection/internal/enum_def.h @@ -21,7 +21,8 @@ extern "C" { #endif upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i); -bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a); +void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e, + upb_EnumValueDef* v); const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e); // Allocate and initialize an array of |n| enum defs. diff --git a/upb/reflection/json_enumvalue_options_bootstrap.h b/upb/reflection/json_enumvalue_options_bootstrap.h new file mode 100644 index 0000000000..c6cefdf798 --- /dev/null +++ b/upb/reflection/json_enumvalue_options_bootstrap.h @@ -0,0 +1,19 @@ +#ifndef GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ +#define GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ + +// IWYU pragma: begin_exports + +#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 +// This header is checked in. +#include "upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.h" +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 1 +// This header is generated at build time by the bootstrapping process. +#include "upb/reflection/stage1/google/protobuf/json_enumvalue_options.upb.h" +#else +// This is the normal header, generated by upb_c_proto_library(). +#include "google/protobuf/json_enumvalue_options.upb.h" +#endif + +// IWYU pragma: end_exports + +#endif // GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__ diff --git a/upb/reflection/reflection_test.cc b/upb/reflection/reflection_test.cc index b64fd6b103..4dd55d4b4a 100644 --- a/upb/reflection/reflection_test.cc +++ b/upb/reflection/reflection_test.cc @@ -389,5 +389,77 @@ TEST(ReflectionTest, ZeroWeakDependencyIndexWithNoDeps) { EXPECT_THAT(std::string(status.message()), HasSubstr("out of range")); } +// Sets (pb.enumvalue.json).string option (extension field 998) on +// EnumValueOptions. +static void SetCustomJsonOption(google::protobuf::EnumValueOptions* options, + absl::string_view json_name) { + // Wire format for JsonEnumValueOptions { string string = 1 }: + // Field 1 (string, length-delimited): tag = (1 << 3) | 2 = 0x0a. + std::string payload; + payload.push_back('\x0a'); + payload.push_back(static_cast(json_name.size())); + payload.append(json_name); + // Field 998 is extension (pb.enumvalue.json) on EnumValueOptions. + options->mutable_unknown_fields()->AddLengthDelimited(998, payload); +} + +struct TestEnumValueSpec { + std::string name; + int number; + std::string json_name; +}; + +static absl::StatusOr LoadEnumDescriptorWithValues( + absl::Span values) { + google::protobuf::FileDescriptorProto file_proto; + file_proto.set_name("test.proto"); + file_proto.set_syntax("editions"); + file_proto.set_edition(google::protobuf::EDITION_2026); + + google::protobuf::EnumDescriptorProto* enum_proto = file_proto.add_enum_type(); + enum_proto->set_name("TestEnum"); + + for (const TestEnumValueSpec& v : values) { + google::protobuf::EnumValueDescriptorProto* val_proto = enum_proto->add_value(); + val_proto->set_name(v.name); + val_proto->set_number(v.number); + if (!v.json_name.empty()) { + SetCustomJsonOption(val_proto->mutable_options(), v.json_name); + } + } + + google::protobuf::FileDescriptorSet set; + *set.add_file() = file_proto; + return LoadDescriptorSetFromProto(set); +} + +TEST(ReflectionTest, EnumCustomJsonNameConflictDifferentNumberFails) { + // Two enum values with DIFFERENT numbers (1 and 2) sharing the same custom + // JSON name must fail descriptor validation. + absl::Status status = + LoadEnumDescriptorWithValues({ + {"VAL_ZERO", 0, ""}, + {"VAL_A", 1, "custom_name"}, + {"VAL_B", 2, "custom_name"}, + }) + .status(); + EXPECT_FALSE(status.ok()); + EXPECT_THAT(std::string(status.message()), + HasSubstr("duplicate custom json_name (custom_name) in enum")); +} + +TEST(ReflectionTest, EnumCustomJsonNameAliasedSameNumberSucceeds) { + // Two aliased enum values with the SAME number (1 and 1) sharing the same + // custom JSON name must succeed descriptor validation. + absl::Status status = + LoadEnumDescriptorWithValues({ + {"VAL_ZERO", 0, ""}, + {"VAL_A", 1, "custom_name"}, + {"VAL_B", 1, "custom_name"}, + }) + .status(); + EXPECT_TRUE(status.ok()) << status.message(); +} + } // namespace } // namespace upb_test diff --git a/upb/reflection/stage0/google/protobuf/descriptor.upb.c b/upb/reflection/stage0/google/protobuf/descriptor.upb.c index 76a3b47ed5..efe2dd7977 100644 --- a/upb/reflection/stage0/google/protobuf/descriptor.upb.c +++ b/upb/reflection/stage0/google/protobuf/descriptor.upb.c @@ -2,13 +2,13 @@ #include "upb/generated_code_support.h" #include "upb/reflection/descriptor_bootstrap.h" -static upb_Arena* upb_BootstrapArena() { +static upb_Arena* upb_BootstrapArena(void) { static upb_Arena* arena = NULL; if (!arena) arena = upb_Arena_New(); return arena; } -const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init() { +const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$PG"; if (mini_table) return mini_table; @@ -32,7 +32,7 @@ const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$11EGGGG33<<1a4E"; if (mini_table) return mini_table; @@ -104,7 +104,7 @@ const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__DescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__DescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1GGGGG3GGE4"; if (mini_table) return mini_table; @@ -192,7 +192,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init() { +const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$((3"; if (mini_table) return mini_table; @@ -216,7 +216,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init( return mini_table; } -const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init() { +const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$(("; if (mini_table) return mini_table; @@ -232,7 +232,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init() return mini_table; } -const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init() { +const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$PaG4n`3t|G"; if (mini_table) return mini_table; @@ -280,7 +280,7 @@ const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init() { +const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$(11a//"; if (mini_table) return mini_table; @@ -296,7 +296,7 @@ const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_in return mini_table; } -const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$11(44113(1f/"; if (mini_table) return mini_table; @@ -336,7 +336,7 @@ const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$13"; if (mini_table) return mini_table; @@ -360,7 +360,7 @@ const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1G3GE4"; if (mini_table) return mini_table; @@ -408,7 +408,7 @@ const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init() { +const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$(("; if (mini_table) return mini_table; @@ -424,7 +424,7 @@ const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_ms return mini_table; } -const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1(3"; if (mini_table) return mini_table; @@ -448,7 +448,7 @@ const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1G3"; if (mini_table) return mini_table; @@ -480,7 +480,7 @@ const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init() { +const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1113//"; if (mini_table) return mini_table; @@ -504,7 +504,7 @@ const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FileOptions_msg_init() { +const upb_MiniTable* google__protobuf__FileOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P1f14/1d///a/b/c/c/d11a111b11d3t|G"; if (mini_table) return mini_table; @@ -544,7 +544,7 @@ const upb_MiniTable* google__protobuf__FileOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__MessageOptions_msg_init() { +const upb_MiniTable* google__protobuf__MessageOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P///c/c/3z}G"; if (mini_table) return mini_table; @@ -576,7 +576,7 @@ const upb_MiniTable* google__protobuf__MessageOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FieldOptions_msg_init() { +const upb_MiniTable* google__protobuf__FieldOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P4//a/4c/d//4aHG33p}G"; if (mini_table) return mini_table; @@ -656,7 +656,7 @@ const upb_MiniTable* google__protobuf__FieldOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init() { +const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$a14"; if (mini_table) return mini_table; @@ -680,7 +680,7 @@ const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init() { +const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$44141"; if (mini_table) return mini_table; @@ -720,7 +720,7 @@ const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__OneofOptions_msg_init() { +const upb_MiniTable* google__protobuf__OneofOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P3e~G"; if (mini_table) return mini_table; @@ -752,7 +752,7 @@ const upb_MiniTable* google__protobuf__OneofOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__EnumOptions_msg_init() { +const upb_MiniTable* google__protobuf__EnumOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$Pa//b/3_~G"; if (mini_table) return mini_table; @@ -784,7 +784,7 @@ const upb_MiniTable* google__protobuf__EnumOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() { +const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P/3/3b~G"; if (mini_table) return mini_table; @@ -824,7 +824,7 @@ const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__ServiceOptions_msg_init() { +const upb_MiniTable* google__protobuf__ServiceOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P``/3d}G"; if (mini_table) return mini_table; @@ -856,7 +856,7 @@ const upb_MiniTable* google__protobuf__ServiceOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__MethodOptions_msg_init() { +const upb_MiniTable* google__protobuf__MethodOptions_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P``/43c}G"; if (mini_table) return mini_table; @@ -896,7 +896,7 @@ const upb_MiniTable* google__protobuf__MethodOptions_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init() { +const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$aG1,+ 01"; if (mini_table) return mini_table; @@ -920,7 +920,7 @@ const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init() { +const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1N/N"; if (mini_table) return mini_table; @@ -936,7 +936,7 @@ const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init() return mini_table; } -const upb_MiniTable* google__protobuf__FeatureSet_msg_init() { +const upb_MiniTable* google__protobuf__FeatureSet_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$P444444444"; if (mini_table) return mini_table; @@ -1024,7 +1024,7 @@ const upb_MiniTable* google__protobuf__FeatureSet_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init() { +const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$"; if (mini_table) return mini_table; @@ -1040,7 +1040,7 @@ const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init() return mini_table; } -const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init() { +const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$"; if (mini_table) return mini_table; @@ -1056,7 +1056,7 @@ const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init() return mini_table; } -const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init() { +const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$Gb44"; if (mini_table) return mini_table; @@ -1096,7 +1096,7 @@ const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init() { +const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$b433"; if (mini_table) return mini_table; @@ -1136,7 +1136,7 @@ const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefa return mini_table; } -const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init() { +const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$PG"; if (mini_table) return mini_table; @@ -1160,7 +1160,7 @@ const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init() { +const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$N<<11aE"; if (mini_table) return mini_table; @@ -1176,7 +1176,7 @@ const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init() { +const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$G"; if (mini_table) return mini_table; @@ -1200,7 +1200,7 @@ const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init() { +const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$N<1((4"; if (mini_table) return mini_table; @@ -1224,7 +1224,7 @@ const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init() return mini_table; } -const upb_MiniTableEnum* google__protobuf__Edition_enum_init() { +const upb_MiniTableEnum* google__protobuf__Edition_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)~z!|aAcxg!h{va)|i}{~~`!"; if (mini_table) return mini_table; @@ -1234,7 +1234,7 @@ const upb_MiniTableEnum* google__protobuf__Edition_enum_init() { return mini_table; } -const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationState_enum_init() { +const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationState_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!$"; if (mini_table) return mini_table; @@ -1244,7 +1244,7 @@ const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationSt return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!1"; if (mini_table) return mini_table; @@ -1254,7 +1254,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_i return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1264,7 +1264,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init() { return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!1"; if (mini_table) return mini_table; @@ -1274,7 +1274,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init() return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1284,7 +1284,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init() { return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1294,7 +1294,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__EnforceProtoLimits_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__EnforceProtoLimits_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1304,7 +1304,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__Enfor return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1314,7 +1314,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enu return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!/"; if (mini_table) return mini_table; @@ -1324,7 +1324,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init( return mini_table; } -const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__DefaultSymbolVisibility_enum_init() { +const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__DefaultSymbolVisibility_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!A"; if (mini_table) return mini_table; @@ -1334,7 +1334,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__Defaul return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!0"; if (mini_table) return mini_table; @@ -1344,7 +1344,7 @@ const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!@AA1"; if (mini_table) return mini_table; @@ -1354,7 +1354,7 @@ const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init( return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1364,7 +1364,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init() { return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1374,7 +1374,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init() { return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1384,7 +1384,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_in return mini_table; } -const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_init() { +const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!AA"; if (mini_table) return mini_table; @@ -1394,7 +1394,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_i return mini_table; } -const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init() { +const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!0"; if (mini_table) return mini_table; @@ -1404,7 +1404,7 @@ const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init() return mini_table; } -const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init() { +const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1414,7 +1414,7 @@ const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semant return mini_table; } -const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_init() { +const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; @@ -1424,7 +1424,7 @@ const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_ return mini_table; } -const upb_MiniTableEnum* google__protobuf__SymbolVisibility_enum_init() { +const upb_MiniTableEnum* google__protobuf__SymbolVisibility_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; diff --git a/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.c b/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.c new file mode 100644 index 0000000000..685b6cf820 --- /dev/null +++ b/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.c @@ -0,0 +1,27 @@ +#include +#include "upb/generated_code_support.h" +#include "upb/reflection/json_enumvalue_options_bootstrap.h" + +#include "upb/reflection/descriptor_bootstrap.h" +static upb_Arena* upb_BootstrapArena(void) { + static upb_Arena* arena = NULL; + if (!arena) arena = upb_Arena_New(); + return arena; +} + +const upb_MiniTable* pb__enumvalue__JsonEnumValueOptions_msg_init(void) { + static upb_MiniTable* mini_table = NULL; + static const char* mini_descriptor = "$M1"; + if (mini_table) return mini_table; + upb_Status status; + mini_table = + upb_MiniTable_Build(mini_descriptor, strlen(mini_descriptor), + upb_BootstrapArena(), &status); + if (!mini_table) { + fprintf(stderr, "Failed to build mini_table for pb__enumvalue__JsonEnumValueOptions_msg_init: %s\n", + upb_Status_ErrorMessage(&status)); + abort(); + } + return mini_table; +} + diff --git a/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.h b/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.h new file mode 100644 index 0000000000..f2a7c7aa47 --- /dev/null +++ b/upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.h @@ -0,0 +1,122 @@ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/json_enumvalue_options.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ + +#include "upb/generated_code_support.h" +// Must be last. +#include "upb/port/def.inc" + +#ifdef __cplusplus +extern "C" { +#endif +extern const upb_MiniTable* pb__enumvalue__JsonEnumValueOptions_msg_init(void); +extern const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init(void); + +typedef struct pb_enumvalue_JsonEnumValueOptions { + upb_Message UPB_PRIVATE(base); +} pb_enumvalue_JsonEnumValueOptions; + +struct google_protobuf_EnumValueOptions; + + + +/* pb.enumvalue.JsonEnumValueOptions */ +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_new(upb_Arena* arena) { + return (pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(pb__enumvalue__JsonEnumValueOptions_msg_init(), arena); +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse(const char* buf, size_t size, + upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), pb__enumvalue__JsonEnumValueOptions_msg_init(), NULL, 0, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse_ex( + const char* buf, size_t size, const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), pb__enumvalue__JsonEnumValueOptions_msg_init(), extreg, + options, arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize(const pb_enumvalue_JsonEnumValueOptions* msg, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), pb__enumvalue__JsonEnumValueOptions_msg_init(), 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize_ex(const pb_enumvalue_JsonEnumValueOptions* msg, + int options, upb_Arena* arena, + size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), pb__enumvalue__JsonEnumValueOptions_msg_init(), options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_clear_string(pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1); + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView pb_enumvalue_JsonEnumValueOptions_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool pb_enumvalue_JsonEnumValueOptions_has_string(const pb_enumvalue_JsonEnumValueOptions* msg) { + const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1); + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_set_string(pb_enumvalue_JsonEnumValueOptions* msg, upb_StringView value) { + const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1); + upb_Message_SetBaseField((upb_Message*)msg, &field, &value); +} + +// In stage0 bootstrapping, extensions are not present. +UPB_INLINE bool pb_enumvalue_has_json(const struct google_protobuf_EnumValueOptions* msg) { + (void)msg; + return false; +} + +UPB_INLINE void pb_enumvalue_clear_json(struct google_protobuf_EnumValueOptions* msg) { (void)msg; } +UPB_INLINE const pb_enumvalue_JsonEnumValueOptions* +pb_enumvalue_json(const struct google_protobuf_EnumValueOptions* msg) { + (void)msg; + return NULL; +} + +UPB_INLINE void pb_enumvalue_set_json(struct google_protobuf_EnumValueOptions* msg, + const pb_enumvalue_JsonEnumValueOptions* val, + upb_Arena* arena) { + (void)msg; + (void)val; + (void)arena; +} +UPB_INLINE struct pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_mutable_json( + struct google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + (void)msg; + (void)arena; + return NULL; +} +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#include "upb/port/undef.inc" + +#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ */ diff --git a/upb_generator/bootstrap_compiler.bzl b/upb_generator/bootstrap_compiler.bzl index 4e8c53c74b..93dee5b535 100644 --- a/upb_generator/bootstrap_compiler.bzl +++ b/upb_generator/bootstrap_compiler.bzl @@ -2,6 +2,10 @@ load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:defs.bzl", "cc_library") +load( + "//upb/bazel:copts.bzl", + "UPB_DEFAULT_COPTS", +) load( "//upb/bazel:upb_minitable_proto_library.bzl", "upb_minitable_proto_library", @@ -15,6 +19,11 @@ load( "staleness_test", ) +def _c_library_with_default_copts(**kwargs): + cc_kwargs = dict(kwargs) + cc_kwargs["copts"] = UPB_DEFAULT_COPTS + cc_kwargs.get("copts", []) + cc_library(**cc_kwargs) + _stages = ["_stage0", "_stage1", ""] _protoc = "//src/google/protobuf/compiler/release:protoc_minimal" @@ -105,11 +114,11 @@ def _generated_hdrs_and_srcs(protos, stage, generator): ret += _generated_files(protos, stage, generator, "c") return ret -def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix): +def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix, third_party_dir = "3rd_party"): native.genrule( name = name + "_generate_bootstrap", srcs = src_rules, - outs = ["bootstrap_generated_sources/" + f.replace("third_party", "3rd_party") for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")], + outs = ["bootstrap_generated_sources/" + f.replace("third_party", third_party_dir) for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")], tools = [_protoc, _upbc("upb", 0)], cmd = "$(location " + _protoc + ") " + @@ -117,15 +126,18 @@ def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix): "--plugin=protoc-gen-upb=$(location " + _upbc("upb", 0) + ") " + "--upb_out=bootstrap_stage=0:$(@D)/bootstrap_generated_sources/stage0 " + " ".join(src_files) + - "; rm -rf $(@D)/bootstrap_generated_sources/stage0/3rd_party" + - "; if [ -e $(@D)/bootstrap_generated_sources/stage0/third_party ]; then mv $(@D)/bootstrap_generated_sources/stage0/third_party $(@D)/bootstrap_generated_sources/stage0/3rd_party; fi", + "; rm -rf $(@D)/bootstrap_generated_sources/stage0/" + third_party_dir + + "; if [ -e $(@D)/bootstrap_generated_sources/stage0/third_party ]; then mv $(@D)/bootstrap_generated_sources/stage0/third_party $(@D)/bootstrap_generated_sources/stage0/" + third_party_dir + "; fi", ) staleness_test( name = name + "_stage0_staleness_test", - outs = [f.replace("third_party", "3rd_party") for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")], + outs = [f.replace("third_party", third_party_dir) for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")], generated_pattern = "bootstrap_generated_sources/%s", - target_files = native.glob(["stage0/**"]), + target_files = [ + f.replace("third_party", third_party_dir) + for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb") + ], # To avoid skew problems for descriptor.proto/plugin.proto between # GitHub repos. It's not critical that the checked-in protos are up to # date for every change, they just needs to be complete enough to have @@ -194,6 +206,7 @@ def bootstrap_upb_proto_library( proto_lib_deps, deps = [], strip_prefix = "", + third_party_dir = "3rd_party", **kwargs): """A version of upb_proto_library() that is augmented to allow for bootstrapping the compiler. @@ -211,13 +224,15 @@ def bootstrap_upb_proto_library( not bootstrapping. deps: other bootstrap_upb_proto_library() rules that this one depends on. strip_prefix: Prefix that should be stripped from file names. + third_party_dir: Subdirectory name to use instead of "third_party" for stage0 checked-in + files to comply with repository structure rules. **kwargs: Other arguments that will be passed through to cc_library(), genrule(), and upb_proto_library(). """ - _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix) + _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix, third_party_dir) # stage0 uses checked-in protos, and has no MiniTable. - cc_library( + _c_library_with_default_copts( name = name + "_stage0", srcs = _generated_hdrs_and_srcs(src_files, "stage0", "upb"), hdrs = [bootstrap_hdr], @@ -233,7 +248,7 @@ def bootstrap_upb_proto_library( # Generate stage1 protos (C API and MiniTables) using stage0 compiler. _generate_stage1_proto(name, src_files, src_rules, "upb", kwargs) _generate_stage1_proto(name, src_files, src_rules, "upb_minitable", kwargs) - cc_library( + _c_library_with_default_copts( name = name + "_minitable_stage1", srcs = _generated_files(src_files, "stage1", "upb_minitable", "c"), hdrs = _generated_files(src_files, "stage1", "upb_minitable", "h"), @@ -244,7 +259,7 @@ def bootstrap_upb_proto_library( ] + [dep + "_minitable_stage1" for dep in deps], **kwargs ) - cc_library( + _c_library_with_default_copts( name = name + "_stage1", srcs = _generated_files(src_files, "stage1", "upb", "h"), hdrs = [bootstrap_hdr], @@ -263,7 +278,7 @@ def bootstrap_upb_proto_library( deps = proto_lib_deps, **kwargs ) - cc_library( + _c_library_with_default_copts( name = name, hdrs = [bootstrap_hdr], deps = [name + "_upb_proto"], diff --git a/upb_generator/c/generator.cc b/upb_generator/c/generator.cc index bafa181270..5c2caf4ce8 100644 --- a/upb_generator/c/generator.cc +++ b/upb_generator/c/generator.cc @@ -313,6 +313,72 @@ std::string GetFieldRep(const DefPoolPair& pools, upb::FieldDefPtr field) { } void GenerateExtensionInHeader(Context& c, upb::FieldDefPtr ext) { + if (c.options().bootstrap_stage == 0) { + c.Emit( + { + {"ident_base", ExtensionIdentBase(ext)}, + {"name", ext.name()}, + {"ctype", MessageType(ext.containing_type())}, + }, + R"cc( + // In stage0 bootstrapping, extensions are not present. + UPB_INLINE bool $ident_base$_has_$name$(const struct $ctype$* msg) { + (void)msg; + return false; + } + + UPB_INLINE void $ident_base$_clear_$name$(struct $ctype$* msg) { (void)msg; } + )cc"); + + if (ext.IsSequence()) { + // Repeated extensions are accessed via generic upb_Array and + // upb_Message_GetExtension APIs. + } else { + c.Emit( + { + {"ctype_const", CTypeConst(ext)}, + {"ident_base", ExtensionIdentBase(ext)}, + {"name", ext.name()}, + {"ctype", MessageType(ext.containing_type())}, + {"default", FieldDefault(ext)}, + }, + R"cc( + UPB_INLINE $ctype_const$ + $ident_base$_$name$(const struct $ctype$* msg) { + (void)msg; + return $default$; + } + + UPB_INLINE void $ident_base$_set_$name$(struct $ctype$* msg, + $ctype_const$ val, + upb_Arena* arena) { + (void)msg; + (void)val; + (void)arena; + } + )cc"); + + if (ext.IsSubMessage()) { + c.Emit( + { + {"sub_ctype", MessageType(ext.message_type())}, + {"ident_base", ExtensionIdentBase(ext)}, + {"name", ext.name()}, + {"ctype", MessageType(ext.containing_type())}, + }, + R"cc( + UPB_INLINE struct $sub_ctype$* $ident_base$_mutable_$name$( + struct $ctype$* msg, upb_Arena* arena) { + (void)msg; + (void)arena; + return NULL; + } + )cc"); + } + } + return; + } + c.Emit( { {"ident_base", ExtensionIdentBase(ext)}, @@ -331,7 +397,8 @@ void GenerateExtensionInHeader(Context& c, upb::FieldDefPtr ext) { )cc"); if (ext.IsSequence()) { - // TODO: We need generated accessors for repeated extensions. + // Repeated extensions are accessed via generic upb_Array and + // upb_Message_GetExtension APIs. } else { c.Emit( { @@ -1206,7 +1273,7 @@ void WriteMessageMiniDescriptorInitializer(Context& c, upb::MessageDefPtr msg) { {"mini_descriptor", msg.MiniDescriptorEncode()}, {"resolve_calls", [&] { WriteResolveCalls(c, msg); }}}, R"cc( - const upb_MiniTable* $name$() { + const upb_MiniTable* $name$(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$mini_descriptor$"; if (mini_table) return mini_table; @@ -1229,7 +1296,7 @@ void WriteEnumMiniDescriptorInitializer(Context& c, upb::EnumDefPtr enum_def) { c.Emit({{"name", MiniTableEnumVarName(enum_def.full_name())}, {"mini_descriptor", enum_def.MiniDescriptorEncode()}}, R"cc( - const upb_MiniTableEnum* $name$() { + const upb_MiniTableEnum* $name$(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "$mini_descriptor$"; if (mini_table) return mini_table; @@ -1262,7 +1329,7 @@ void WriteMiniDescriptorSource(Context& c, upb::FileDefPtr file) { c.Emit( R"cc( - static upb_Arena* upb_BootstrapArena() { + static upb_Arena* upb_BootstrapArena(void) { static upb_Arena* arena = NULL; if (!arena) arena = upb_Arena_New(); return arena; diff --git a/upb_generator/c/names_internal.cc b/upb_generator/c/names_internal.cc index b2f29d4401..38f346b558 100644 --- a/upb_generator/c/names_internal.cc +++ b/upb_generator/c/names_internal.cc @@ -18,7 +18,14 @@ namespace generator { std::string CApiHeaderFilename(absl::string_view proto_filename, bool bootstrap) { if (bootstrap) { - if (IsDescriptorProto(proto_filename)) { + if (proto_filename == "third_party/protobuf/json_enumvalue_options.proto" || + proto_filename == "google/protobuf/json_enumvalue_options.proto" || + proto_filename == "src/google/protobuf/json_enumvalue_options.proto") { + return "upb/reflection/" + "json_enumvalue_options_bootstrap.h"; + } else if (proto_filename == "net/proto2/proto/descriptor.proto" || + proto_filename == "google/protobuf/descriptor.proto" || + proto_filename == "src/google/protobuf/descriptor.proto") { return "upb/reflection/descriptor_bootstrap.h"; } else { return "upb_generator/plugin_bootstrap.h"; diff --git a/upb_generator/cmake/google/protobuf/compiler/plugin.upb_minitable.c b/upb_generator/cmake/google/protobuf/compiler/plugin.upb_minitable.c index 1cf1dc4894..2a144a43e0 100644 --- a/upb_generator/cmake/google/protobuf/compiler/plugin.upb_minitable.c +++ b/upb_generator/cmake/google/protobuf/compiler/plugin.upb_minitable.c @@ -212,20 +212,20 @@ const upb_MiniTableEnum google__protobuf__compiler__CodeGeneratorResponse__Featu }, }; -static const upb_MiniTable *messages_layout[4] = { +static const upb_MiniTable *messages_layout_google_protobuf_compiler_plugin_proto_upb_file_layout[4] = { &google__protobuf__compiler__Version_msg_init, &google__protobuf__compiler__CodeGeneratorRequest_msg_init, &google__protobuf__compiler__CodeGeneratorResponse_msg_init, &google__protobuf__compiler__CodeGeneratorResponse__File_msg_init, }; -static const upb_MiniTableEnum *enums_layout[1] = { +static const upb_MiniTableEnum *enums_layout_google_protobuf_compiler_plugin_proto_upb_file_layout[1] = { &google__protobuf__compiler__CodeGeneratorResponse__Feature_enum_init, }; const upb_MiniTableFile google_protobuf_compiler_plugin_proto_upb_file_layout = { - messages_layout, - enums_layout, + messages_layout_google_protobuf_compiler_plugin_proto_upb_file_layout, + enums_layout_google_protobuf_compiler_plugin_proto_upb_file_layout, NULL, 4, 1, diff --git a/upb_generator/common/names.cc b/upb_generator/common/names.cc index 8cec63fdbe..63e47a0865 100644 --- a/upb_generator/common/names.cc +++ b/upb_generator/common/names.cc @@ -31,9 +31,13 @@ std::string ToPreproc(absl::string_view str) { } // namespace -bool IsDescriptorProto(absl::string_view filename) { +bool IsReflectionBootstrapProto(absl::string_view filename) { return filename == "net/proto2/proto/descriptor.proto" || - filename == "google/protobuf/descriptor.proto"; + filename == "google/protobuf/descriptor.proto" || + filename == "src/google/protobuf/descriptor.proto" || + filename == "third_party/protobuf/json_enumvalue_options.proto" || + filename == "google/protobuf/json_enumvalue_options.proto" || + filename == "src/google/protobuf/json_enumvalue_options.proto"; } std::string StripExtension(absl::string_view fname) { diff --git a/upb_generator/common/names.h b/upb_generator/common/names.h index 793b5d2cf1..78a2411210 100644 --- a/upb_generator/common/names.h +++ b/upb_generator/common/names.h @@ -18,7 +18,7 @@ namespace upb { namespace generator { -bool IsDescriptorProto(absl::string_view filename); +bool IsReflectionBootstrapProto(absl::string_view filename); std::string StripExtension(absl::string_view fname); std::string IncludeGuard(absl::string_view filename); std::string FileWarning(absl::string_view filename); diff --git a/upb_generator/minitable/generator.cc b/upb_generator/minitable/generator.cc index 54f8490ce4..c074e724e1 100644 --- a/upb_generator/minitable/generator.cc +++ b/upb_generator/minitable/generator.cc @@ -309,7 +309,7 @@ void WriteExtension(const DefPoolPair& pools, upb::FieldDefPtr ext, void RegisterExtensions(Output& output, absl::string_view unique_name) { output("UPB_LINKARR_DECLARE(upb_AllExts, const upb_MiniTableExtension*);\n"); - output("UPB_CONSTRUCTOR(upb_GeneratedRegistry_Constructor, $0) {\n", + output("UPB_CONSTRUCTOR(upb_GeneratedRegistry_Constructor, $0, {\n", unique_name); // TODO Although we define this function as weak and only one // copy will ever exist in any binary, every instance will get registered as a @@ -326,7 +326,7 @@ void RegisterExtensions(Output& output, absl::string_view unique_name) { output(" UPB_ASSERT(entry.next == NULL);\n"); output(" entry.next = UPB_PRIVATE(upb_generated_extension_list);\n"); output(" UPB_PRIVATE(upb_generated_extension_list) = &entry;\n"); - output("}\n"); + output("})\n"); } } // namespace @@ -458,9 +458,15 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file, } } + std::string messages_layout = + absl::StrCat("messages_layout_", FileVarName(file)); + std::string enums_layout = absl::StrCat("enums_layout_", FileVarName(file)); + std::string extensions_layout = + absl::StrCat("extensions_layout_", FileVarName(file)); + // Messages. if (!messages.empty()) { - output("static const upb_MiniTable *$0[$1] = {\n", kMessagesInit, + output("static const upb_MiniTable *$0[$1] = {\n", messages_layout, messages.size()); for (auto message : messages) { output(" &$0,\n", MessageVarName(message)); @@ -471,7 +477,7 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file, // Enums. if (!enums.empty()) { - output("static const upb_MiniTableEnum *$0[$1] = {\n", kEnumsInit, + output("static const upb_MiniTableEnum *$0[$1] = {\n", enums_layout, enums.size()); for (const auto e : enums) { output(" &$0,\n", EnumVarName(e)); @@ -485,7 +491,7 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file, output( "\n" "static const upb_MiniTableExtension *$0[$1] = {\n", - kExtensionsInit, extensions.size()); + extensions_layout, extensions.size()); for (auto ext : extensions) { output(" &$0_obj,\n", ExtensionVarName(ext)); @@ -503,9 +509,9 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file, } output("const upb_MiniTableFile $0 = {\n", FileVarName(file)); - output(" $0,\n", messages.empty() ? "NULL" : kMessagesInit); - output(" $0,\n", enums.empty() ? "NULL" : kEnumsInit); - output(" $0,\n", extensions.empty() ? "NULL" : kExtensionsInit); + output(" $0,\n", messages.empty() ? "NULL" : messages_layout); + output(" $0,\n", enums.empty() ? "NULL" : enums_layout); + output(" $0,\n", extensions.empty() ? "NULL" : extensions_layout); output(" $0,\n", messages.size()); output(" $0,\n", enums.size()); output(" $0,\n", extensions.size()); diff --git a/upb_generator/minitable/names_internal.cc b/upb_generator/minitable/names_internal.cc index 86058f6fbf..390a40e0c0 100644 --- a/upb_generator/minitable/names_internal.cc +++ b/upb_generator/minitable/names_internal.cc @@ -28,7 +28,7 @@ std::string MiniTableHeaderFilename(absl::string_view proto_filename, bool bootstrap) { std::string base; if (bootstrap) { - if (IsDescriptorProto(proto_filename)) { + if (IsReflectionBootstrapProto(proto_filename)) { base = "upb/reflection/stage1/"; } else { base = "upb_generator/stage1/"; diff --git a/upb_generator/reflection/source.cc b/upb_generator/reflection/source.cc index a573f1f575..6cca2370bc 100644 --- a/upb_generator/reflection/source.cc +++ b/upb_generator/reflection/source.cc @@ -89,13 +89,15 @@ void WriteDescriptor(upb::FileDefPtr file, Context& ctx) { file_proto, arena.ptr(), &serialized_size); absl::string_view file_data(serialized, serialized_size); - ctx.Emit({{"serialized_size", file_data.size()}, - {"contents", [&] { WriteStringArray(file_data, ctx); }}}, - R"cc( - static const char descriptor[$serialized_size$] = { - $contents$, - }; - )cc"); + ctx.Emit( + {{"serialized_size", file_data.size()}, + {"defpool_init_name", ReflectionFileSymbol(file.name())}, + {"contents", [&] { WriteStringArray(file_data, ctx); }}}, + R"cc( + static const char descriptor_$defpool_init_name$[$serialized_size$] = { + $contents$, + }; + )cc"); ctx.Emit("\n"); } @@ -112,9 +114,10 @@ void WriteDependencies(upb::FileDefPtr file, Context& ctx) { }; ctx.Emit({{"dep_count", file.dependency_count() + 1}, + {"defpool_init_name", ReflectionFileSymbol(file.name())}, {google::protobuf::io::Printer::Sub("deps", write_deps).WithSuffix(",")}}, R"cc( - static _upb_DefPool_Init *deps[$dep_count$] = { + static _upb_DefPool_Init* deps_$defpool_init_name$[$dep_count$] = { $deps$, NULL, }; @@ -131,10 +134,11 @@ void WriteDefPoolInitStruct(upb::FileDefPtr file, Context& ctx) { }, R"cc( _upb_DefPool_Init $defpool_init_name$ = { - deps, + deps_$defpool_init_name$, &$mini_table_file_var_name$, "$file_name$", - UPB_STRINGVIEW_INIT(descriptor, sizeof(descriptor)), + UPB_STRINGVIEW_INIT(descriptor_$defpool_init_name$, + sizeof(descriptor_$defpool_init_name$)), }; )cc"); } diff --git a/upb_generator/stage0/google/protobuf/compiler/plugin.upb.c b/upb_generator/stage0/google/protobuf/compiler/plugin.upb.c index f3996fb8fb..9d8e3837c3 100644 --- a/upb_generator/stage0/google/protobuf/compiler/plugin.upb.c +++ b/upb_generator/stage0/google/protobuf/compiler/plugin.upb.c @@ -3,13 +3,13 @@ #include "upb_generator/plugin_bootstrap.h" #include "upb/reflection/descriptor_bootstrap.h" -static upb_Arena* upb_BootstrapArena() { +static upb_Arena* upb_BootstrapArena(void) { static upb_Arena* arena = NULL; if (!arena) arena = upb_Arena_New(); return arena; } -const upb_MiniTable* google__protobuf__compiler__Version_msg_init() { +const upb_MiniTable* google__protobuf__compiler__Version_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$(((1"; if (mini_table) return mini_table; @@ -25,7 +25,7 @@ const upb_MiniTable* google__protobuf__compiler__Version_msg_init() { return mini_table; } -const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init() { +const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$E13kGaG"; if (mini_table) return mini_table; @@ -65,7 +65,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init() return mini_table; } -const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init() { +const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$1,((jG"; if (mini_table) return mini_table; @@ -89,7 +89,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init( return mini_table; } -const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg_init() { +const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg_init(void) { static upb_MiniTable* mini_table = NULL; static const char* mini_descriptor = "$11l13"; if (mini_table) return mini_table; @@ -113,7 +113,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg return mini_table; } -const upb_MiniTableEnum* google__protobuf__compiler__CodeGeneratorResponse__Feature_enum_init() { +const upb_MiniTableEnum* google__protobuf__compiler__CodeGeneratorResponse__Feature_enum_init(void) { static const upb_MiniTableEnum* mini_table = NULL; static const char* mini_descriptor = "!)"; if (mini_table) return mini_table; diff --git a/version.json b/version.json index 2c48cb3842..db9ab44a1f 100644 --- a/version.json +++ b/version.json @@ -1,18 +1,18 @@ { - "main": { - "protoc_version": "36-dev", + "36.x": { + "protoc_version": "36.0-rc2", "lts": false, - "date": "2026-04-15", + "date": "2026-08-03", "languages": { - "cpp": "7.36-dev", - "csharp": "3.36-dev", - "java": "4.36-dev", - "javascript": "3.36-dev", - "objectivec": "5.36-dev", - "php": "5.36-dev", - "python": "7.36-dev", - "ruby": "4.36-dev", - "rust": "4.36-dev" + "cpp": "7.36.0-rc2", + "csharp": "3.36.0-rc2", + "java": "4.36.0-rc2", + "javascript": "3.36.0-rc2", + "objectivec": "5.36.0-rc2", + "php": "5.36.0-rc2", + "python": "7.36.0-rc2", + "ruby": "4.36.0-rc2", + "rust": "4.36.0-rc2" } } } \ No newline at end of file