diff --git a/BUILD b/BUILD index 2ad94c583d..46f4b08dcf 100644 --- a/BUILD +++ b/BUILD @@ -439,6 +439,25 @@ upb_proto_library( deps = [":msg_test_proto"], ) +proto_library( + name = "proto3_test_proto", + testonly = 1, + srcs = ["upb/proto3_test.proto"], + deps = ["@com_google_protobuf//:descriptor_proto"], +) + +upb_proto_library( + name = "proto3_test_upb_proto", + testonly = 1, + deps = [":proto3_test_proto"], +) + +upb_proto_reflection_library( + name = "proto3_test_upb_proto_reflection", + testonly = 1, + deps = [":proto3_test_proto"], +) + upb_proto_reflection_library( name = "msg_test_upb_proto_reflection", testonly = 1, @@ -471,6 +490,18 @@ upb_proto_reflection_library( deps = ["@com_google_protobuf//:timestamp_proto"], ) +cc_test( + name = "proto3_test", + srcs = ["upb/proto3_test.cc"], + copts = UPB_DEFAULT_CPPOPTS, + deps = [ + ":proto3_test_upb_proto", + ":proto3_test_upb_proto_reflection", + ":reflection", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "test_cpp", srcs = ["upb/test_cpp.cc"], diff --git a/upb/def.c b/upb/def.c index 2f216bbfb9..4c855d001e 100644 --- a/upb/def.c +++ b/upb/def.c @@ -2515,7 +2515,7 @@ static void create_fielddef( CHK_OOM( upb_strtable_insert(&oneof->ntof, name.data, name.size, v, ctx->arena)); } else { - if (f->proto3_optional_) { + if (f->proto3_optional_ && !is_extension) { symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)", f->full_name); } diff --git a/upb/proto3_test.cc b/upb/proto3_test.cc new file mode 100644 index 0000000000..2d12d7bb4f --- /dev/null +++ b/upb/proto3_test.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2009-2021, Google LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google LLC nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "upb/proto3_test.upb.h" +#include "upb/proto3_test.upbdefs.h" +#include "upb/def.hpp" + +TEST(Proto3Test, SyntheticOneofExtension) { + upb::SymbolTable defpool; + upb::MessageDefPtr md(upb_test_TestMessage3_getmsgdef(defpool.ptr())); + ASSERT_EQ(md.field_count(), 6); +} diff --git a/upb/proto3_test.proto b/upb/proto3_test.proto new file mode 100644 index 0000000000..f83a8b8c4b --- /dev/null +++ b/upb/proto3_test.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package upb.test; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.MessageOptions { + optional string my_option = 51235; +} + +message MyMessage3 { + option (my_option) = "Hello world!"; +} + +message TestMessage3 { + optional int32 i32 = 1; + repeated int32 r_i32 = 2; + optional string str = 3; + repeated string r_str = 4; + optional TestMessage3 msg = 5; + repeated TestMessage3 r_msg = 6; +}