protogen: fix name mangling for fields with identical GoCamelCase

This turns the nameclash testprotos ending in 3 into .proto
files which use syntax = "proto3". Prior to the Opaque API release,
we changed these .proto files to use editions, but using editions
with proto3 semantics is not exactly the same as using proto3,
so we need these .proto files to use syntax = "proto3";

Fixes golang/protobuf#1675

Change-Id: I0ebb37d4e1bf0fc830bbe613148429ec6ff5c46d
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/644437
Reviewed-by: Chressie Himpel <chressie@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid.proto
index d15394c..dbb4229 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid.proto
@@ -331,3 +331,9 @@
     int32 which_which_foo = 2;
   }
 }
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid.pb.go
index 607ba7b..197f9b2 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid.pb.go
@@ -3585,6 +3585,139 @@
 
 func (*M20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state         protoimpl.MessageState `protogen:"hybrid.v1"`
+	XFoo          *string                `protobuf:"bytes,1,opt,name=_foo,json=Foo" json:"_foo,omitempty"`
+	XFoo_         *string                `protobuf:"bytes,2,opt,name=X_foo,json=XFoo" json:"X_foo,omitempty"`
+	GetXFoo__     *string                `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo" json:"get_x_foo,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes[20]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes[20]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil && x.XFoo != nil {
+		return *x.XFoo
+	}
+	return ""
+}
+
+// Deprecated: Use GetXFoo_1 instead.
+func (x *M21) GetXFoo() string {
+	return x.GetXFoo_1()
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil && x.XFoo_ != nil {
+		return *x.XFoo_
+	}
+	return ""
+}
+
+// Deprecated: Use GetXFoo_2 instead.
+func (x *M21) GetXFoo_() string {
+	return x.GetXFoo_2()
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil && x.GetXFoo__ != nil {
+		return *x.GetXFoo__
+	}
+	return ""
+}
+
+// Deprecated: Use GetGetXFoo instead.
+func (x *M21) GetGetXFoo__() string {
+	return x.GetGetXFoo()
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.XFoo = &v
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.XFoo_ = &v
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.GetXFoo__ = &v
+}
+
+func (x *M21) HasXFoo_1() bool {
+	if x == nil {
+		return false
+	}
+	return x.XFoo != nil
+}
+
+func (x *M21) HasXFoo_2() bool {
+	if x == nil {
+		return false
+	}
+	return x.XFoo_ != nil
+}
+
+func (x *M21) HasGetXFoo() bool {
+	if x == nil {
+		return false
+	}
+	return x.GetXFoo__ != nil
+}
+
+func (x *M21) ClearXFoo_1() {
+	x.XFoo = nil
+}
+
+func (x *M21) ClearXFoo_2() {
+	x.XFoo_ = nil
+}
+
+func (x *M21) ClearGetXFoo() {
+	x.GetXFoo__ = nil
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  *string
+	XFoo_2  *string
+	GetXFoo *string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	x.XFoo = b.XFoo_1
+	x.XFoo_ = b.XFoo_2
+	x.GetXFoo__ = b.GetXFoo
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc = string([]byte{
@@ -3695,17 +3828,22 @@
 	0x01, 0x28, 0x05, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x68, 0x69, 0x63,
 	0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28,
 	0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68, 0x46,
-	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x42,
-	0x60, 0x5a, 0x56, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
-	0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d,
-	0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f,
-	0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x5f, 0x68, 0x79, 0x62, 0x72, 0x69, 0x64, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10,
-	0x02, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
+	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x22,
+	0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f, 0x66,
+	0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12, 0x1a,
+	0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x60, 0x5a, 0x56, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64,
+	0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65,
+	0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x68, 0x79,
+	0x62, 0x72, 0x69, 0x64, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10, 0x02, 0x62, 0x08, 0x65, 0x64,
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_goTypes = []any{
 	(*M1)(nil),  // 0: net.proto2.go.testdata.nameclashhybrid.M1
 	(*M2)(nil),  // 1: net.proto2.go.testdata.nameclashhybrid.M2
@@ -3727,6 +3865,7 @@
 	(*M18)(nil), // 17: net.proto2.go.testdata.nameclashhybrid.M18
 	(*M19)(nil), // 18: net.proto2.go.testdata.nameclashhybrid.M19
 	(*M20)(nil), // 19: net.proto2.go.testdata.nameclashhybrid.M20
+	(*M21)(nil), // 20: net.proto2.go.testdata.nameclashhybrid.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_depIdxs = []int32{
 	0, // [0:0] is the sub-list for method output_type
@@ -3791,7 +3930,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   20,
+			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid_protoopaque.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid_protoopaque.pb.go
index e369008..969754a 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid_protoopaque.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid/test_name_clash_hybrid_protoopaque.pb.go
@@ -3298,6 +3298,150 @@
 
 func (*m20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state                  protoimpl.MessageState `protogen:"opaque.v1"`
+	xxx_hidden_XFoo        *string                `protobuf:"bytes,1,opt,name=_foo,json=Foo"`
+	xxx_hidden_XFoo_       *string                `protobuf:"bytes,2,opt,name=X_foo,json=XFoo"`
+	xxx_hidden_GetXFoo__   *string                `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo"`
+	XXX_raceDetectHookData protoimpl.RaceDetectHookData
+	XXX_presence           [1]uint32
+	unknownFields          protoimpl.UnknownFields
+	sizeCache              protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes[20]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes[20]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil {
+		if x.xxx_hidden_XFoo != nil {
+			return *x.xxx_hidden_XFoo
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil {
+		if x.xxx_hidden_XFoo_ != nil {
+			return *x.xxx_hidden_XFoo_
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil {
+		if x.xxx_hidden_GetXFoo__ != nil {
+			return *x.xxx_hidden_GetXFoo__
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.xxx_hidden_XFoo = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 0, 3)
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.xxx_hidden_XFoo_ = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 1, 3)
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.xxx_hidden_GetXFoo__ = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 2, 3)
+}
+
+func (x *M21) HasXFoo_1() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 0)
+}
+
+func (x *M21) HasXFoo_2() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 1)
+}
+
+func (x *M21) HasGetXFoo() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 2)
+}
+
+func (x *M21) ClearXFoo_1() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 0)
+	x.xxx_hidden_XFoo = nil
+}
+
+func (x *M21) ClearXFoo_2() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 1)
+	x.xxx_hidden_XFoo_ = nil
+}
+
+func (x *M21) ClearGetXFoo() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 2)
+	x.xxx_hidden_GetXFoo__ = nil
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  *string
+	XFoo_2  *string
+	GetXFoo *string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	if b.XFoo_1 != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 0, 3)
+		x.xxx_hidden_XFoo = b.XFoo_1
+	}
+	if b.XFoo_2 != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 1, 3)
+		x.xxx_hidden_XFoo_ = b.XFoo_2
+	}
+	if b.GetXFoo != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 2, 3)
+		x.xxx_hidden_GetXFoo__ = b.GetXFoo
+	}
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc = string([]byte{
@@ -3408,17 +3552,22 @@
 	0x01, 0x28, 0x05, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x68, 0x69, 0x63,
 	0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28,
 	0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68, 0x46,
-	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x42,
-	0x60, 0x5a, 0x56, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
-	0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d,
-	0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f,
-	0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x5f, 0x68, 0x79, 0x62, 0x72, 0x69, 0x64, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10,
-	0x02, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
+	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x22,
+	0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f, 0x66,
+	0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12, 0x1a,
+	0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x60, 0x5a, 0x56, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64,
+	0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65,
+	0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x68, 0x79,
+	0x62, 0x72, 0x69, 0x64, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10, 0x02, 0x62, 0x08, 0x65, 0x64,
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_goTypes = []any{
 	(*M1)(nil),  // 0: net.proto2.go.testdata.nameclashhybrid.M1
 	(*M2)(nil),  // 1: net.proto2.go.testdata.nameclashhybrid.M2
@@ -3440,6 +3589,7 @@
 	(*M18)(nil), // 17: net.proto2.go.testdata.nameclashhybrid.M18
 	(*M19)(nil), // 18: net.proto2.go.testdata.nameclashhybrid.M19
 	(*M20)(nil), // 19: net.proto2.go.testdata.nameclashhybrid.M20
+	(*M21)(nil), // 20: net.proto2.go.testdata.nameclashhybrid.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_depIdxs = []int32{
 	0, // [0:0] is the sub-list for method output_type
@@ -3504,7 +3654,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   20,
+			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3.proto
index 8be92f6..c5d230b 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3.proto
@@ -21,7 +21,7 @@
 // 1 - My field name clashes with their getter name
 // 2 - My getter name clashes with their field name
 
-edition = "2023";
+syntax = "proto3";
 
 package net.proto2.go.testdata.nameclashhybrid3;
 
@@ -29,9 +29,6 @@
 
 option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3";
 
-option features.field_presence = IMPLICIT;
-option features.(pb.go).api_level = API_HYBRID;
-
 message M0 {
   int32 i1 = 1;
 }
@@ -336,3 +333,9 @@
     int32 which_which_foo = 2;
   }
 }
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3.pb.go
index 48e7408..4e700e9 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3.pb.go
@@ -38,7 +38,7 @@
 
 type M0 struct {
 	state         protoimpl.MessageState `protogen:"hybrid.v1"`
-	I1            int32                  `protobuf:"varint,1,opt,name=i1" json:"i1,omitempty"`
+	I1            int32                  `protobuf:"varint,1,opt,name=i1,proto3" json:"i1,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -105,9 +105,9 @@
 	// Foo                    | get_foo            | G    | Get_Foo
 	// GetFoo                 | get_get_foo        | G    | Get_GetFoo
 	// GetGetFoo              | -                  | -    | GetGetGetFoo
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
-	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
+	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -253,9 +253,9 @@
 	// Foo                    | get_foo            | G    | Get_Foo
 	// GetFoo                 | get_get_foo        | G    | Get_GetFoo
 	// GetGetFoo              | -                  | -    | GetGetGetFoo
-	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
-	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
+	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -401,9 +401,9 @@
 	// Foo                    | get_foo            | G    | Get_Foo
 	// GetFoo                 | get_get_foo        | G    | Get_GetFoo
 	// GetGetFoo              | -                  | -    | GetGetGetFoo
-	GetFoo        *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	GetGetFoo_    *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
-	Foo_          *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo        *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	GetGetFoo_    *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
+	Foo_          *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -558,12 +558,12 @@
 	// Foo                    | get_foo            | G    | Get_Foo
 	// GetFoo                 | get_get_foo        | G    | Get_GetFoo
 	// GetGetGetFoo           | -                  | -    | GetGetGetGetFoo
-	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
+	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
 	// Types that are valid to be assigned to GetGetFoo_:
 	//
 	//	*M4_GetGetGetFoo
 	GetGetFoo_    isM4_GetGetFoo_ `protobuf_oneof:"get_get_foo"`
-	Foo_          *M0             `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo_          *M0             `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -758,7 +758,7 @@
 }
 
 type M4_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*M4_GetGetGetFoo) isM4_GetGetFoo_() {}
@@ -780,12 +780,12 @@
 	// Foo                    | get_foo            | G    | Get_Foo
 	// GetFoo                 | get_get_foo        | G    | Get_GetFoo
 	// GetGetFoo              | get_get_get_foo    | G    | Get_GetGetFoo
-	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
+	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
 	// Types that are valid to be assigned to GetGetGetFoo:
 	//
 	//	*M5_GetGetFoo_
 	GetGetGetFoo  isM5_GetGetGetFoo `protobuf_oneof:"get_get_get_foo"`
-	Foo_          *M0               `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo_          *M0               `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -986,7 +986,7 @@
 }
 
 type M5_GetGetFoo_ struct {
-	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*M5_GetGetFoo_) isM5_GetGetGetFoo() {}
@@ -1012,8 +1012,8 @@
 	//
 	//	*M6_GetGetGetFoo
 	GetGetFoo     isM6_GetGetFoo `protobuf_oneof:"get_get_foo"`
-	GetFoo_       *M0            `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0            `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo_       *M0            `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0            `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1207,7 +1207,7 @@
 }
 
 type M6_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*M6_GetGetGetFoo) isM6_GetGetFoo() {}
@@ -1234,7 +1234,7 @@
 	//	*M7_Bar
 	//	*M7_GetFoo_
 	GetGetFoo     isM7_GetGetFoo `protobuf_oneof:"get_get_foo"`
-	Foo           *M0            `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo           *M0            `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1438,11 +1438,11 @@
 }
 
 type M7_Bar struct {
-	Bar bool `protobuf:"varint,4,opt,name=bar,oneof"`
+	Bar bool `protobuf:"varint,4,opt,name=bar,proto3,oneof"`
 }
 
 type M7_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*M7_Bar) isM7_GetGetFoo() {}
@@ -1470,8 +1470,8 @@
 	//
 	//	*M8_GetGetFoo
 	GetGetGetFoo_ isM8_GetGetGetFoo_ `protobuf_oneof:"get_get_get_foo"`
-	GetFoo_       *M0                `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0                `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo_       *M0                `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0                `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1670,7 +1670,7 @@
 }
 
 type M8_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*M8_GetGetFoo) isM8_GetGetGetFoo_() {}
@@ -1697,7 +1697,7 @@
 	//	*M9_GetGetFoo
 	//	*M9_GetFoo_
 	GetGetGetFoo_ isM9_GetGetGetFoo_ `protobuf_oneof:"get_get_get_foo"`
-	Foo           *M0                `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo           *M0                `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1906,11 +1906,11 @@
 }
 
 type M9_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 type M9_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*M9_GetGetFoo) isM9_GetGetGetFoo_() {}
@@ -1924,8 +1924,8 @@
 	// initial name in Go     | Clashes with field | Setter name
 	// Foo                    | set_foo            | Set_Foo
 	// SetFoo                 | -                  | SetSetFoo
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
-	SetFoo        *M0 `protobuf:"bytes,2,opt,name=set_foo,json=setFoo" json:"set_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
+	SetFoo        *M0 `protobuf:"bytes,2,opt,name=set_foo,json=setFoo,proto3" json:"set_foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -2032,7 +2032,7 @@
 	// initial name in Go     | Clashes with field | Setter name
 	// Foo                    | set_foo            | Set_Foo
 	// SetSetFoo              | -                  | SetSetSetFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to SetFoo:
 	//
 	//	*M11_SetSetFoo
@@ -2193,7 +2193,7 @@
 }
 
 type M11_SetSetFoo struct {
-	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,oneof"`
+	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,proto3,oneof"`
 }
 
 func (*M11_SetSetFoo) isM11_SetFoo() {}
@@ -2205,7 +2205,7 @@
 	// initial name in Go     | Clashes with field | Setter name
 	// Foo                    | set_foo            | Set_Foo
 	// SetFoo                 | set_set_foo        | Set_SetFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to SetSetFoo:
 	//
 	//	*M12_SetFoo
@@ -2371,7 +2371,7 @@
 }
 
 type M12_SetFoo struct {
-	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,oneof"`
+	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,proto3,oneof"`
 }
 
 func (*M12_SetFoo) isM12_SetSetFoo() {}
@@ -2383,8 +2383,8 @@
 	// initial name in Go     | Clashes with field | Hasser name
 	// Foo                    | has_foo            | Has_Foo
 	// HasFoo                 | -                  | HasHasFoo
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
-	HasFoo        *M0 `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo" json:"has_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
+	HasFoo        *M0 `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo,proto3" json:"has_foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -2492,7 +2492,7 @@
 	// Foo                    | has_foo            | Has_Foo
 	// HasFoo                 | has_has_foo        | Has_HasFoo
 	// HasHasFoo              | -                  | HasHasHasFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to HasFoo:
 	//
 	//	*M14_HasHasFoo
@@ -2654,7 +2654,7 @@
 }
 
 type M14_HasHasFoo struct {
-	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,oneof"`
+	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,proto3,oneof"`
 }
 
 func (*M14_HasHasFoo) isM14_HasFoo() {}
@@ -2667,7 +2667,7 @@
 	// Foo                    | has_foo            | Has_Foo
 	// HasFoo                 | has_has_foo        | Has_HasFoo
 	// HasHasFoo              | -                  | HasHasHasFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to HasHasFoo:
 	//
 	//	*M15_HasFoo
@@ -2834,7 +2834,7 @@
 }
 
 type M15_HasFoo struct {
-	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,oneof"`
+	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,proto3,oneof"`
 }
 
 func (*M15_HasFoo) isM15_HasHasFoo() {}
@@ -2846,8 +2846,8 @@
 	// initial name in Go     | Clashes with field | Clearer name
 	// Foo                    | clear_foo            | Clear_Foo
 	// ClearFoo               | -                  | ClearClearFoo
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
-	ClearFoo      *M0 `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo" json:"clear_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
+	ClearFoo      *M0 `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo,proto3" json:"clear_foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -2955,7 +2955,7 @@
 	// Foo                    | clear_foo          | Clear_Foo
 	// ClearFoo               | clear_clear_foo    | Clear_ClearFoo
 	// ClearClearFoo          | -                  | ClearClearClearFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to ClearFoo:
 	//
 	//	*M17_ClearClearFoo
@@ -3117,7 +3117,7 @@
 }
 
 type M17_ClearClearFoo struct {
-	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,oneof"`
+	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,proto3,oneof"`
 }
 
 func (*M17_ClearClearFoo) isM17_ClearFoo() {}
@@ -3130,7 +3130,7 @@
 	// Foo                    | clear_foo          | Clear_Foo
 	// ClearFoo               | clear_clear_foo    | Clear_ClearFoo
 	// ClearClearFoo          | -                  | ClearClearClearFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to ClearClearFoo:
 	//
 	//	*M18_ClearFoo
@@ -3297,7 +3297,7 @@
 }
 
 type M18_ClearFoo struct {
-	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,oneof"`
+	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,proto3,oneof"`
 }
 
 func (*M18_ClearFoo) isM18_ClearClearFoo() {}
@@ -3310,7 +3310,7 @@
 	// Foo                    | -                  | -
 	// WhichFoo               | -                  | -
 	// WhichWhichFoo          | -                  | WhichWhichWhichFoo
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to WhichWhichFoo:
 	//
 	//	*M19_WhichFoo
@@ -3467,7 +3467,7 @@
 }
 
 type M19_WhichFoo struct {
-	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,oneof"`
+	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,proto3,oneof"`
 }
 
 func (*M19_WhichFoo) isM19_WhichWhichFoo() {}
@@ -3480,7 +3480,7 @@
 	// Foo                    | -                  | -
 	// WhichFoo               | which_which_foo    | Which_WhichFoo
 	// WhichWhichFoo          | -                  | -
-	Foo *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	// Types that are valid to be assigned to WhichFoo:
 	//
 	//	*M20_WhichWhichFoo
@@ -3637,11 +3637,111 @@
 }
 
 type M20_WhichWhichFoo struct {
-	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,oneof"`
+	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,proto3,oneof"`
 }
 
 func (*M20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state         protoimpl.MessageState `protogen:"hybrid.v1"`
+	XFoo          string                 `protobuf:"bytes,1,opt,name=_foo,json=Foo,proto3" json:"_foo,omitempty"`
+	XFoo_         string                 `protobuf:"bytes,2,opt,name=X_foo,json=XFoo,proto3" json:"X_foo,omitempty"`
+	GetXFoo__     string                 `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo,proto3" json:"get_x_foo,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes[21]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes[21]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil {
+		return x.XFoo
+	}
+	return ""
+}
+
+// Deprecated: Use GetXFoo_1 instead.
+func (x *M21) GetXFoo() string {
+	return x.GetXFoo_1()
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil {
+		return x.XFoo_
+	}
+	return ""
+}
+
+// Deprecated: Use GetXFoo_2 instead.
+func (x *M21) GetXFoo_() string {
+	return x.GetXFoo_2()
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil {
+		return x.GetXFoo__
+	}
+	return ""
+}
+
+// Deprecated: Use GetGetXFoo instead.
+func (x *M21) GetGetXFoo__() string {
+	return x.GetGetXFoo()
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.XFoo = v
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.XFoo_ = v
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.GetXFoo__ = v
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  string
+	XFoo_2  string
+	GetXFoo string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	x.XFoo = b.XFoo_1
+	x.XFoo_ = b.XFoo_2
+	x.GetXFoo__ = b.GetXFoo
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc = string([]byte{
@@ -3848,17 +3948,20 @@
 	0x63, 0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01,
 	0x28, 0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68,
 	0x46, 0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f,
-	0x42, 0x63, 0x5a, 0x57, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e,
-	0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63,
-	0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f,
-	0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x5f, 0x68, 0x79, 0x62, 0x72, 0x69, 0x64, 0x33, 0x92, 0x03, 0x07, 0xd2, 0x3e,
-	0x02, 0x10, 0x02, 0x08, 0x02, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70,
-	0xe8, 0x07,
+	0x22, 0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f,
+	0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12,
+	0x1a, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x59, 0x5a, 0x57, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67,
+	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74,
+	0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74,
+	0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x68,
+	0x79, 0x62, 0x72, 0x69, 0x64, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_goTypes = []any{
 	(*M0)(nil),  // 0: net.proto2.go.testdata.nameclashhybrid3.M0
 	(*M1)(nil),  // 1: net.proto2.go.testdata.nameclashhybrid3.M1
@@ -3881,6 +3984,7 @@
 	(*M18)(nil), // 18: net.proto2.go.testdata.nameclashhybrid3.M18
 	(*M19)(nil), // 19: net.proto2.go.testdata.nameclashhybrid3.M19
 	(*M20)(nil), // 20: net.proto2.go.testdata.nameclashhybrid3.M20
+	(*M21)(nil), // 21: net.proto2.go.testdata.nameclashhybrid3.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_depIdxs = []int32{
 	0,  // 0: net.proto2.go.testdata.nameclashhybrid3.M1.foo:type_name -> net.proto2.go.testdata.nameclashhybrid3.M0
@@ -3978,7 +4082,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   21,
+			NumMessages:   22,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3_protoopaque.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3_protoopaque.pb.go
index 9ad9799..2f66ef2 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3_protoopaque.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_hybrid3/test_name_clash_hybrid3_protoopaque.pb.go
@@ -38,7 +38,7 @@
 
 type M0 struct {
 	state         protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_I1 int32                  `protobuf:"varint,1,opt,name=i1"`
+	xxx_hidden_I1 int32                  `protobuf:"varint,1,opt,name=i1,proto3"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -95,9 +95,9 @@
 
 type M1 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -223,9 +223,9 @@
 
 type M2 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -351,9 +351,9 @@
 
 type M3 struct {
 	state                 protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_GetGetFoo_ *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
-	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_GetGetFoo_ *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
+	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields         protoimpl.UnknownFields
 	sizeCache             protoimpl.SizeCache
 }
@@ -479,9 +479,9 @@
 
 type M4 struct {
 	state                 protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
+	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
 	xxx_hidden_GetGetFoo_ isM4_GetGetFoo_        `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields         protoimpl.UnknownFields
 	sizeCache             protoimpl.SizeCache
 }
@@ -659,16 +659,16 @@
 }
 
 type m4_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*m4_GetGetGetFoo) isM4_GetGetFoo_() {}
 
 type M5 struct {
 	state                   protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
+	xxx_hidden_GetFoo       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
 	xxx_hidden_GetGetGetFoo isM5_GetGetGetFoo      `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_Foo_         *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo_         *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields           protoimpl.UnknownFields
 	sizeCache               protoimpl.SizeCache
 }
@@ -847,7 +847,7 @@
 }
 
 type m5_GetGetFoo_ struct {
-	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*m5_GetGetFoo_) isM5_GetGetGetFoo() {}
@@ -855,8 +855,8 @@
 type M6 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetFoo isM6_GetGetFoo         `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -1033,7 +1033,7 @@
 }
 
 type m6_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*m6_GetGetGetFoo) isM6_GetGetFoo() {}
@@ -1041,7 +1041,7 @@
 type M7 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetFoo isM7_GetGetFoo         `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -1228,11 +1228,11 @@
 }
 
 type m7_Bar struct {
-	Bar bool `protobuf:"varint,4,opt,name=bar,oneof"`
+	Bar bool `protobuf:"varint,4,opt,name=bar,proto3,oneof"`
 }
 
 type m7_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*m7_Bar) isM7_GetGetFoo() {}
@@ -1242,8 +1242,8 @@
 type M8 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetGetFoo_ isM8_GetGetGetFoo_     `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_GetFoo_       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo_       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
 }
@@ -1420,7 +1420,7 @@
 }
 
 type m8_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*m8_GetGetFoo) isM8_GetGetGetFoo_() {}
@@ -1428,7 +1428,7 @@
 type M9 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetGetFoo_ isM9_GetGetGetFoo_     `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
 }
@@ -1615,11 +1615,11 @@
 }
 
 type m9_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 type m9_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*m9_GetGetFoo) isM9_GetGetGetFoo_() {}
@@ -1628,8 +1628,8 @@
 
 type M10 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_SetFoo *M0                    `protobuf:"bytes,2,opt,name=set_foo,json=setFoo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_SetFoo *M0                    `protobuf:"bytes,2,opt,name=set_foo,json=setFoo,proto3"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
 }
@@ -1726,7 +1726,7 @@
 
 type M11 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_SetFoo isM11_SetFoo           `protobuf_oneof:"set_foo"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
@@ -1872,14 +1872,14 @@
 }
 
 type m11_SetSetFoo struct {
-	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,oneof"`
+	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,proto3,oneof"`
 }
 
 func (*m11_SetSetFoo) isM11_SetFoo() {}
 
 type M12 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_SetSetFoo isM12_SetSetFoo        `protobuf_oneof:"set_set_foo"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
@@ -2025,15 +2025,15 @@
 }
 
 type m12_SetFoo struct {
-	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,oneof"`
+	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,proto3,oneof"`
 }
 
 func (*m12_SetFoo) isM12_SetSetFoo() {}
 
 type M13 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_HasFoo *M0                    `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_HasFoo *M0                    `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo,proto3"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
 }
@@ -2130,7 +2130,7 @@
 
 type M14 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_HasFoo isM14_HasFoo           `protobuf_oneof:"has_foo"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
@@ -2277,14 +2277,14 @@
 }
 
 type m14_HasHasFoo struct {
-	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,oneof"`
+	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,proto3,oneof"`
 }
 
 func (*m14_HasHasFoo) isM14_HasFoo() {}
 
 type M15 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_HasHasFoo isM15_HasHasFoo        `protobuf_oneof:"has_has_foo"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
@@ -2431,15 +2431,15 @@
 }
 
 type m15_HasFoo struct {
-	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,oneof"`
+	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,proto3,oneof"`
 }
 
 func (*m15_HasFoo) isM15_HasHasFoo() {}
 
 type M16 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_ClearFoo *M0                    `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_ClearFoo *M0                    `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo,proto3"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
 }
@@ -2536,7 +2536,7 @@
 
 type M17 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_ClearFoo isM17_ClearFoo         `protobuf_oneof:"clear_foo"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
@@ -2683,14 +2683,14 @@
 }
 
 type m17_ClearClearFoo struct {
-	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,oneof"`
+	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,proto3,oneof"`
 }
 
 func (*m17_ClearClearFoo) isM17_ClearFoo() {}
 
 type M18 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_ClearClearFoo isM18_ClearClearFoo    `protobuf_oneof:"clear_clear_foo"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
@@ -2837,14 +2837,14 @@
 }
 
 type m18_ClearFoo struct {
-	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,oneof"`
+	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,proto3,oneof"`
 }
 
 func (*m18_ClearFoo) isM18_ClearClearFoo() {}
 
 type M19 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_WhichWhichFoo isM19_WhichWhichFoo    `protobuf_oneof:"which_which_foo"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
@@ -2991,14 +2991,14 @@
 }
 
 type m19_WhichFoo struct {
-	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,oneof"`
+	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,proto3,oneof"`
 }
 
 func (*m19_WhichFoo) isM19_WhichWhichFoo() {}
 
 type M20 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_WhichFoo isM20_WhichFoo         `protobuf_oneof:"which_foo"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
@@ -3145,11 +3145,96 @@
 }
 
 type m20_WhichWhichFoo struct {
-	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,oneof"`
+	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,proto3,oneof"`
 }
 
 func (*m20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state                protoimpl.MessageState `protogen:"opaque.v1"`
+	xxx_hidden_XFoo      string                 `protobuf:"bytes,1,opt,name=_foo,json=Foo,proto3"`
+	xxx_hidden_XFoo_     string                 `protobuf:"bytes,2,opt,name=X_foo,json=XFoo,proto3"`
+	xxx_hidden_GetXFoo__ string                 `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo,proto3"`
+	unknownFields        protoimpl.UnknownFields
+	sizeCache            protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes[21]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes[21]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil {
+		return x.xxx_hidden_XFoo
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil {
+		return x.xxx_hidden_XFoo_
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil {
+		return x.xxx_hidden_GetXFoo__
+	}
+	return ""
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.xxx_hidden_XFoo = v
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.xxx_hidden_XFoo_ = v
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.xxx_hidden_GetXFoo__ = v
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  string
+	XFoo_2  string
+	GetXFoo string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	x.xxx_hidden_XFoo = b.XFoo_1
+	x.xxx_hidden_XFoo_ = b.XFoo_2
+	x.xxx_hidden_GetXFoo__ = b.GetXFoo
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc = string([]byte{
@@ -3356,17 +3441,20 @@
 	0x63, 0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01,
 	0x28, 0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68,
 	0x46, 0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f,
-	0x42, 0x63, 0x5a, 0x57, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e,
-	0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63,
-	0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f,
-	0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x5f, 0x68, 0x79, 0x62, 0x72, 0x69, 0x64, 0x33, 0x92, 0x03, 0x07, 0xd2, 0x3e,
-	0x02, 0x10, 0x02, 0x08, 0x02, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70,
-	0xe8, 0x07,
+	0x22, 0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f,
+	0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12,
+	0x1a, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x59, 0x5a, 0x57, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67,
+	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74,
+	0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74,
+	0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x68,
+	0x79, 0x62, 0x72, 0x69, 0x64, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_goTypes = []any{
 	(*M0)(nil),  // 0: net.proto2.go.testdata.nameclashhybrid3.M0
 	(*M1)(nil),  // 1: net.proto2.go.testdata.nameclashhybrid3.M1
@@ -3389,6 +3477,7 @@
 	(*M18)(nil), // 18: net.proto2.go.testdata.nameclashhybrid3.M18
 	(*M19)(nil), // 19: net.proto2.go.testdata.nameclashhybrid3.M19
 	(*M20)(nil), // 20: net.proto2.go.testdata.nameclashhybrid3.M20
+	(*M21)(nil), // 21: net.proto2.go.testdata.nameclashhybrid3.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_depIdxs = []int32{
 	0,  // 0: net.proto2.go.testdata.nameclashhybrid3.M1.foo:type_name -> net.proto2.go.testdata.nameclashhybrid3.M0
@@ -3486,7 +3575,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_hybrid3_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   21,
+			NumMessages:   22,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque.proto
index e23674c..81e234b 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque.proto
@@ -331,3 +331,9 @@
     int32 which_which_foo = 2;
   }
 }
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque/test_name_clash_opaque.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque/test_name_clash_opaque.pb.go
index 291c4c9..a8a67d5 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque/test_name_clash_opaque.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque/test_name_clash_opaque.pb.go
@@ -3296,6 +3296,150 @@
 
 func (*m20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state                  protoimpl.MessageState `protogen:"opaque.v1"`
+	xxx_hidden_XFoo        *string                `protobuf:"bytes,1,opt,name=_foo,json=Foo"`
+	xxx_hidden_XFoo_       *string                `protobuf:"bytes,2,opt,name=X_foo,json=XFoo"`
+	xxx_hidden_GetXFoo__   *string                `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo"`
+	XXX_raceDetectHookData protoimpl.RaceDetectHookData
+	XXX_presence           [1]uint32
+	unknownFields          protoimpl.UnknownFields
+	sizeCache              protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_msgTypes[20]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_msgTypes[20]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil {
+		if x.xxx_hidden_XFoo != nil {
+			return *x.xxx_hidden_XFoo
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil {
+		if x.xxx_hidden_XFoo_ != nil {
+			return *x.xxx_hidden_XFoo_
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil {
+		if x.xxx_hidden_GetXFoo__ != nil {
+			return *x.xxx_hidden_GetXFoo__
+		}
+		return ""
+	}
+	return ""
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.xxx_hidden_XFoo = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 0, 3)
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.xxx_hidden_XFoo_ = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 1, 3)
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.xxx_hidden_GetXFoo__ = &v
+	protoimpl.X.SetPresent(&(x.XXX_presence[0]), 2, 3)
+}
+
+func (x *M21) HasXFoo_1() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 0)
+}
+
+func (x *M21) HasXFoo_2() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 1)
+}
+
+func (x *M21) HasGetXFoo() bool {
+	if x == nil {
+		return false
+	}
+	return protoimpl.X.Present(&(x.XXX_presence[0]), 2)
+}
+
+func (x *M21) ClearXFoo_1() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 0)
+	x.xxx_hidden_XFoo = nil
+}
+
+func (x *M21) ClearXFoo_2() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 1)
+	x.xxx_hidden_XFoo_ = nil
+}
+
+func (x *M21) ClearGetXFoo() {
+	protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 2)
+	x.xxx_hidden_GetXFoo__ = nil
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  *string
+	XFoo_2  *string
+	GetXFoo *string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	if b.XFoo_1 != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 0, 3)
+		x.xxx_hidden_XFoo = b.XFoo_1
+	}
+	if b.XFoo_2 != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 1, 3)
+		x.xxx_hidden_XFoo_ = b.XFoo_2
+	}
+	if b.GetXFoo != nil {
+		protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 2, 3)
+		x.xxx_hidden_GetXFoo__ = b.GetXFoo
+	}
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_rawDesc = string([]byte{
@@ -3406,17 +3550,22 @@
 	0x01, 0x28, 0x05, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x68, 0x69, 0x63,
 	0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28,
 	0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68, 0x46,
-	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x42,
-	0x60, 0x5a, 0x56, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
-	0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d,
-	0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f,
-	0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61,
-	0x73, 0x68, 0x5f, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10,
-	0x03, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
+	0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x22,
+	0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f, 0x66,
+	0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12, 0x1a,
+	0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x60, 0x5a, 0x56, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64,
+	0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65,
+	0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70,
+	0x61, 0x71, 0x75, 0x65, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10, 0x03, 0x62, 0x08, 0x65, 0x64,
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_goTypes = []any{
 	(*M1)(nil),  // 0: net.proto2.go.testdata.nameclashopaque.M1
 	(*M2)(nil),  // 1: net.proto2.go.testdata.nameclashopaque.M2
@@ -3438,6 +3587,7 @@
 	(*M18)(nil), // 17: net.proto2.go.testdata.nameclashopaque.M18
 	(*M19)(nil), // 18: net.proto2.go.testdata.nameclashopaque.M19
 	(*M20)(nil), // 19: net.proto2.go.testdata.nameclashopaque.M20
+	(*M21)(nil), // 20: net.proto2.go.testdata.nameclashopaque.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_depIdxs = []int32{
 	0, // [0:0] is the sub-list for method output_type
@@ -3502,7 +3652,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   20,
+			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3.proto
index fdafeee..7e31716 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3.proto
@@ -21,7 +21,7 @@
 // 1 - My field name clashes with their getter name
 // 2 - My getter name clashes with their field name
 
-edition = "2023";
+syntax = "proto3";
 
 package net.proto2.go.testdata.nameclashopaque3;
 
@@ -29,9 +29,6 @@
 
 option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3";
 
-option features.field_presence = IMPLICIT;
-option features.(pb.go).api_level = API_OPAQUE;
-
 message M0 {
   int32 i1 = 1;
 }
@@ -336,3 +333,9 @@
     int32 which_which_foo = 2;
   }
 }
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3/test_name_clash_opaque3.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3/test_name_clash_opaque3.pb.go
index 5f00aab..784c6ad 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3/test_name_clash_opaque3.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_opaque3/test_name_clash_opaque3.pb.go
@@ -36,7 +36,7 @@
 
 type M0 struct {
 	state         protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_I1 int32                  `protobuf:"varint,1,opt,name=i1"`
+	xxx_hidden_I1 int32                  `protobuf:"varint,1,opt,name=i1,proto3"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -93,9 +93,9 @@
 
 type M1 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -221,9 +221,9 @@
 
 type M2 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetGetFoo *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -349,9 +349,9 @@
 
 type M3 struct {
 	state                 protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_GetGetFoo_ *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo"`
-	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_GetGetFoo_ *M0                    `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3"`
+	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields         protoimpl.UnknownFields
 	sizeCache             protoimpl.SizeCache
 }
@@ -477,9 +477,9 @@
 
 type M4 struct {
 	state                 protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
+	xxx_hidden_GetFoo     *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
 	xxx_hidden_GetGetFoo_ isM4_GetGetFoo_        `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo_       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields         protoimpl.UnknownFields
 	sizeCache             protoimpl.SizeCache
 }
@@ -657,16 +657,16 @@
 }
 
 type m4_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*m4_GetGetGetFoo) isM4_GetGetFoo_() {}
 
 type M5 struct {
 	state                   protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_GetFoo       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
+	xxx_hidden_GetFoo       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
 	xxx_hidden_GetGetGetFoo isM5_GetGetGetFoo      `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_Foo_         *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo_         *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields           protoimpl.UnknownFields
 	sizeCache               protoimpl.SizeCache
 }
@@ -845,7 +845,7 @@
 }
 
 type m5_GetGetFoo_ struct {
-	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*m5_GetGetFoo_) isM5_GetGetGetFoo() {}
@@ -853,8 +853,8 @@
 type M6 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetFoo isM6_GetGetFoo         `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo_   *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -1031,7 +1031,7 @@
 }
 
 type m6_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*m6_GetGetGetFoo) isM6_GetGetFoo() {}
@@ -1039,7 +1039,7 @@
 type M7 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetFoo isM7_GetGetFoo         `protobuf_oneof:"get_get_foo"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
 }
@@ -1226,11 +1226,11 @@
 }
 
 type m7_Bar struct {
-	Bar bool `protobuf:"varint,4,opt,name=bar,oneof"`
+	Bar bool `protobuf:"varint,4,opt,name=bar,proto3,oneof"`
 }
 
 type m7_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*m7_Bar) isM7_GetGetFoo() {}
@@ -1240,8 +1240,8 @@
 type M8 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetGetFoo_ isM8_GetGetGetFoo_     `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_GetFoo_       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_GetFoo_       *M0                    `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
 }
@@ -1418,7 +1418,7 @@
 }
 
 type m8_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*m8_GetGetFoo) isM8_GetGetGetFoo_() {}
@@ -1426,7 +1426,7 @@
 type M9 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
 	xxx_hidden_GetGetGetFoo_ isM9_GetGetGetFoo_     `protobuf_oneof:"get_get_get_foo"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
 }
@@ -1613,11 +1613,11 @@
 }
 
 type m9_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 type m9_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*m9_GetGetFoo) isM9_GetGetGetFoo_() {}
@@ -1626,8 +1626,8 @@
 
 type M10 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_SetFoo *M0                    `protobuf:"bytes,2,opt,name=set_foo,json=setFoo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_SetFoo *M0                    `protobuf:"bytes,2,opt,name=set_foo,json=setFoo,proto3"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
 }
@@ -1724,7 +1724,7 @@
 
 type M11 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_SetFoo isM11_SetFoo           `protobuf_oneof:"set_foo"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
@@ -1870,14 +1870,14 @@
 }
 
 type m11_SetSetFoo struct {
-	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,oneof"`
+	SetSetFoo int32 `protobuf:"varint,2,opt,name=set_set_foo,json=setSetFoo,proto3,oneof"`
 }
 
 func (*m11_SetSetFoo) isM11_SetFoo() {}
 
 type M12 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_SetSetFoo isM12_SetSetFoo        `protobuf_oneof:"set_set_foo"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
@@ -2023,15 +2023,15 @@
 }
 
 type m12_SetFoo struct {
-	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,oneof"`
+	SetFoo int32 `protobuf:"varint,2,opt,name=set_foo,json=setFoo,proto3,oneof"`
 }
 
 func (*m12_SetFoo) isM12_SetSetFoo() {}
 
 type M13 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_HasFoo *M0                    `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_HasFoo *M0                    `protobuf:"bytes,2,opt,name=has_foo,json=hasFoo,proto3"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
 }
@@ -2128,7 +2128,7 @@
 
 type M14 struct {
 	state             protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo    *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_HasFoo isM14_HasFoo           `protobuf_oneof:"has_foo"`
 	unknownFields     protoimpl.UnknownFields
 	sizeCache         protoimpl.SizeCache
@@ -2275,14 +2275,14 @@
 }
 
 type m14_HasHasFoo struct {
-	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,oneof"`
+	HasHasFoo int32 `protobuf:"varint,2,opt,name=has_has_foo,json=hasHasFoo,proto3,oneof"`
 }
 
 func (*m14_HasHasFoo) isM14_HasFoo() {}
 
 type M15 struct {
 	state                protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo       *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_HasHasFoo isM15_HasHasFoo        `protobuf_oneof:"has_has_foo"`
 	unknownFields        protoimpl.UnknownFields
 	sizeCache            protoimpl.SizeCache
@@ -2429,15 +2429,15 @@
 }
 
 type m15_HasFoo struct {
-	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,oneof"`
+	HasFoo int32 `protobuf:"varint,2,opt,name=has_foo,json=hasFoo,proto3,oneof"`
 }
 
 func (*m15_HasFoo) isM15_HasHasFoo() {}
 
 type M16 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
-	xxx_hidden_ClearFoo *M0                    `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
+	xxx_hidden_ClearFoo *M0                    `protobuf:"bytes,2,opt,name=clear_foo,json=clearFoo,proto3"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
 }
@@ -2534,7 +2534,7 @@
 
 type M17 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_ClearFoo isM17_ClearFoo         `protobuf_oneof:"clear_foo"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
@@ -2681,14 +2681,14 @@
 }
 
 type m17_ClearClearFoo struct {
-	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,oneof"`
+	ClearClearFoo int32 `protobuf:"varint,2,opt,name=clear_clear_foo,json=clearClearFoo,proto3,oneof"`
 }
 
 func (*m17_ClearClearFoo) isM17_ClearFoo() {}
 
 type M18 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_ClearClearFoo isM18_ClearClearFoo    `protobuf_oneof:"clear_clear_foo"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
@@ -2835,14 +2835,14 @@
 }
 
 type m18_ClearFoo struct {
-	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,oneof"`
+	ClearFoo int32 `protobuf:"varint,2,opt,name=clear_foo,json=clearFoo,proto3,oneof"`
 }
 
 func (*m18_ClearFoo) isM18_ClearClearFoo() {}
 
 type M19 struct {
 	state                    protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo           *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_WhichWhichFoo isM19_WhichWhichFoo    `protobuf_oneof:"which_which_foo"`
 	unknownFields            protoimpl.UnknownFields
 	sizeCache                protoimpl.SizeCache
@@ -2989,14 +2989,14 @@
 }
 
 type m19_WhichFoo struct {
-	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,oneof"`
+	WhichFoo int32 `protobuf:"varint,2,opt,name=which_foo,json=whichFoo,proto3,oneof"`
 }
 
 func (*m19_WhichFoo) isM19_WhichWhichFoo() {}
 
 type M20 struct {
 	state               protoimpl.MessageState `protogen:"opaque.v1"`
-	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo"`
+	xxx_hidden_Foo      *M0                    `protobuf:"bytes,1,opt,name=foo,proto3"`
 	xxx_hidden_WhichFoo isM20_WhichFoo         `protobuf_oneof:"which_foo"`
 	unknownFields       protoimpl.UnknownFields
 	sizeCache           protoimpl.SizeCache
@@ -3143,11 +3143,96 @@
 }
 
 type m20_WhichWhichFoo struct {
-	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,oneof"`
+	WhichWhichFoo int32 `protobuf:"varint,2,opt,name=which_which_foo,json=whichWhichFoo,proto3,oneof"`
 }
 
 func (*m20_WhichWhichFoo) isM20_WhichFoo() {}
 
+type M21 struct {
+	state                protoimpl.MessageState `protogen:"opaque.v1"`
+	xxx_hidden_XFoo      string                 `protobuf:"bytes,1,opt,name=_foo,json=Foo,proto3"`
+	xxx_hidden_XFoo_     string                 `protobuf:"bytes,2,opt,name=X_foo,json=XFoo,proto3"`
+	xxx_hidden_GetXFoo__ string                 `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo,proto3"`
+	unknownFields        protoimpl.UnknownFields
+	sizeCache            protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_msgTypes[21]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_msgTypes[21]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+func (x *M21) GetXFoo_1() string {
+	if x != nil {
+		return x.xxx_hidden_XFoo
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_2() string {
+	if x != nil {
+		return x.xxx_hidden_XFoo_
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo() string {
+	if x != nil {
+		return x.xxx_hidden_GetXFoo__
+	}
+	return ""
+}
+
+func (x *M21) SetXFoo_1(v string) {
+	x.xxx_hidden_XFoo = v
+}
+
+func (x *M21) SetXFoo_2(v string) {
+	x.xxx_hidden_XFoo_ = v
+}
+
+func (x *M21) SetGetXFoo(v string) {
+	x.xxx_hidden_GetXFoo__ = v
+}
+
+type M21_builder struct {
+	_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.
+
+	XFoo_1  string
+	XFoo_2  string
+	GetXFoo string
+}
+
+func (b0 M21_builder) Build() *M21 {
+	m0 := &M21{}
+	b, x := &b0, m0
+	_, _ = b, x
+	x.xxx_hidden_XFoo = b.XFoo_1
+	x.xxx_hidden_XFoo_ = b.XFoo_2
+	x.xxx_hidden_GetXFoo__ = b.GetXFoo
+	return m0
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_rawDesc = string([]byte{
@@ -3354,17 +3439,20 @@
 	0x63, 0x68, 0x5f, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01,
 	0x28, 0x05, 0x48, 0x00, 0x52, 0x0d, 0x77, 0x68, 0x69, 0x63, 0x68, 0x57, 0x68, 0x69, 0x63, 0x68,
 	0x46, 0x6f, 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x63, 0x68, 0x5f, 0x66, 0x6f, 0x6f,
-	0x42, 0x63, 0x5a, 0x57, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e,
-	0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63,
-	0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f,
-	0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c,
-	0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x33, 0x92, 0x03, 0x07, 0xd2, 0x3e,
-	0x02, 0x10, 0x03, 0x08, 0x02, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70,
-	0xe8, 0x07,
+	0x22, 0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f,
+	0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12,
+	0x1a, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x59, 0x5a, 0x57, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67,
+	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74,
+	0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74,
+	0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f,
+	0x70, 0x61, 0x71, 0x75, 0x65, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 })
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_goTypes = []any{
 	(*M0)(nil),  // 0: net.proto2.go.testdata.nameclashopaque3.M0
 	(*M1)(nil),  // 1: net.proto2.go.testdata.nameclashopaque3.M1
@@ -3387,6 +3475,7 @@
 	(*M18)(nil), // 18: net.proto2.go.testdata.nameclashopaque3.M18
 	(*M19)(nil), // 19: net.proto2.go.testdata.nameclashopaque3.M19
 	(*M20)(nil), // 20: net.proto2.go.testdata.nameclashopaque3.M20
+	(*M21)(nil), // 21: net.proto2.go.testdata.nameclashopaque3.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_depIdxs = []int32{
 	0,  // 0: net.proto2.go.testdata.nameclashopaque3.M1.foo:type_name -> net.proto2.go.testdata.nameclashopaque3.M0
@@ -3484,7 +3573,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_opaque3_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   21,
+			NumMessages:   22,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open.proto
index 10775a9..4c2a0b9 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open.proto
@@ -149,3 +149,10 @@
   }
   int32 foo = 1;
 }
+
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open/test_name_clash_open.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open/test_name_clash_open.pb.go
index caa1988..7e79258 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open/test_name_clash_open.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open/test_name_clash_open.pb.go
@@ -792,6 +792,66 @@
 
 func (*M9_GetFoo_) isM9_GetGetGetFoo_() {}
 
+type M21 struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	XFoo          *string                `protobuf:"bytes,1,opt,name=_foo,json=Foo" json:"_foo,omitempty"`
+	XFoo_         *string                `protobuf:"bytes,2,opt,name=X_foo,json=XFoo" json:"X_foo,omitempty"`
+	GetXFoo__     *string                `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo" json:"get_x_foo,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_msgTypes[9]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_msgTypes[9]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use M21.ProtoReflect.Descriptor instead.
+func (*M21) Descriptor() ([]byte, []int) {
+	return file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *M21) GetXFoo() string {
+	if x != nil && x.XFoo != nil {
+		return *x.XFoo
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_() string {
+	if x != nil && x.XFoo_ != nil {
+		return *x.XFoo_
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo__() string {
+	if x != nil && x.GetXFoo__ != nil {
+		return *x.GetXFoo__
+	}
+	return ""
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_rawDesc = string([]byte{
@@ -856,14 +916,19 @@
 	0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x06, 0x67, 0x65,
 	0x74, 0x46, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x05, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x42, 0x11, 0x0a, 0x0f, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x65,
-	0x74, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x6f, 0x42, 0x5e, 0x5a, 0x54, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61,
-	0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73,
-	0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70, 0x65,
-	0x6e, 0x92, 0x03, 0x05, 0xd2, 0x3e, 0x02, 0x10, 0x01, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
+	0x74, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x6f, 0x22, 0x49, 0x0a, 0x03, 0x4d, 0x32, 0x31,
+	0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12, 0x1a, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f,
+	0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x74,
+	0x58, 0x46, 0x6f, 0x6f, 0x42, 0x5e, 0x5a, 0x54, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67,
+	0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65,
+	0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61,
+	0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d,
+	0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x92, 0x03, 0x05, 0xd2,
+	0x3e, 0x02, 0x10, 0x01, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8,
+	0x07,
 })
 
 var (
@@ -878,17 +943,18 @@
 	return file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_rawDescData
 }
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_goTypes = []any{
-	(*M1)(nil), // 0: net.proto2.go.testdata.nameclashopen.M1
-	(*M2)(nil), // 1: net.proto2.go.testdata.nameclashopen.M2
-	(*M3)(nil), // 2: net.proto2.go.testdata.nameclashopen.M3
-	(*M4)(nil), // 3: net.proto2.go.testdata.nameclashopen.M4
-	(*M5)(nil), // 4: net.proto2.go.testdata.nameclashopen.M5
-	(*M6)(nil), // 5: net.proto2.go.testdata.nameclashopen.M6
-	(*M7)(nil), // 6: net.proto2.go.testdata.nameclashopen.M7
-	(*M8)(nil), // 7: net.proto2.go.testdata.nameclashopen.M8
-	(*M9)(nil), // 8: net.proto2.go.testdata.nameclashopen.M9
+	(*M1)(nil),  // 0: net.proto2.go.testdata.nameclashopen.M1
+	(*M2)(nil),  // 1: net.proto2.go.testdata.nameclashopen.M2
+	(*M3)(nil),  // 2: net.proto2.go.testdata.nameclashopen.M3
+	(*M4)(nil),  // 3: net.proto2.go.testdata.nameclashopen.M4
+	(*M5)(nil),  // 4: net.proto2.go.testdata.nameclashopen.M5
+	(*M6)(nil),  // 5: net.proto2.go.testdata.nameclashopen.M6
+	(*M7)(nil),  // 6: net.proto2.go.testdata.nameclashopen.M7
+	(*M8)(nil),  // 7: net.proto2.go.testdata.nameclashopen.M8
+	(*M9)(nil),  // 8: net.proto2.go.testdata.nameclashopen.M9
+	(*M21)(nil), // 9: net.proto2.go.testdata.nameclashopen.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_depIdxs = []int32{
 	0, // [0:0] is the sub-list for method output_type
@@ -929,7 +995,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   9,
+			NumMessages:   10,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3.proto b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3.proto
index 442c046..14a6205 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3.proto
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3.proto
@@ -21,7 +21,7 @@
 // 1 - My field name clashes with their getter name
 // 2 - My getter name clashes with their field name
 
-edition = "2023";
+syntax = "proto3";
 
 package net.proto2.go.testdata.nameclashopen3;
 
@@ -29,9 +29,6 @@
 
 option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3";
 
-option features.field_presence = IMPLICIT;
-option features.(pb.go).api_level = API_OPEN;
-
 message M0 {
   int32 i1 = 1;
 }
@@ -162,3 +159,10 @@
 
   M0 foo = 1;
 }
+
+
+message M21 {
+  string _foo = 1;
+  string X_foo = 2;
+  string get_x_foo = 3;
+}
diff --git a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3/test_name_clash_open3.pb.go b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3/test_name_clash_open3.pb.go
index 002402e..0db45e0 100644
--- a/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3/test_name_clash_open3.pb.go
+++ b/cmd/protoc-gen-go/testdata/nameclash/test_name_clash_open3/test_name_clash_open3.pb.go
@@ -37,7 +37,7 @@
 
 type M0 struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
-	I1            int32                  `protobuf:"varint,1,opt,name=i1" json:"i1,omitempty"`
+	I1            int32                  `protobuf:"varint,1,opt,name=i1,proto3" json:"i1,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -85,9 +85,9 @@
 	// Foo                    | -                  | -    | Foo
 	// GetFoo                 | foo                | 1    | GetFoo_
 	// GetGetFoo              | -                  | -    | GetGetFoo
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
-	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
+	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -149,9 +149,9 @@
 	// GetGetFoo              | -                  | -    | GetGetFoo
 	// GetFoo                 | get_get_foo        | 2    | GetFoo_
 	// Foo                    | -                  | -    | Foo
-	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
-	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetGetFoo     *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
+	GetFoo_       *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -213,9 +213,9 @@
 	// GetFoo                 | -                  | -    | GetFoo
 	// GetGetFoo              | get_foo            | 1    | GetGetFoo_
 	// Foo                    | get_foo            | 2    | Foo_
-	GetFoo        *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	GetGetFoo_    *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo" json:"get_get_foo,omitempty"`
-	Foo_          *M0 `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo        *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	GetGetFoo_    *M0 `protobuf:"bytes,3,opt,name=get_get_foo,json=getGetFoo,proto3" json:"get_get_foo,omitempty"`
+	Foo_          *M0 `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -281,12 +281,12 @@
 	//	                      |                    |      |
 	//
 	// Foo                    | get_foo            | 2    | Foo_
-	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
+	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
 	// Types that are valid to be assigned to GetGetFoo_:
 	//
 	//	*M4_GetGetGetFoo
 	GetGetFoo_    isM4_GetGetFoo_ `protobuf_oneof:"get_get_foo"`
-	Foo_          *M0             `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo_          *M0             `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -356,7 +356,7 @@
 }
 
 type M4_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*M4_GetGetGetFoo) isM4_GetGetFoo_() {}
@@ -372,12 +372,12 @@
 	//	                      |                    |      |
 	//
 	// Foo                    | get_foo            | 2    | Foo_
-	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
+	GetFoo *M0 `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
 	// Types that are valid to be assigned to GetGetGetFoo:
 	//
 	//	*M5_GetGetFoo_
 	GetGetGetFoo  isM5_GetGetGetFoo `protobuf_oneof:"get_get_get_foo"`
-	Foo_          *M0               `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo_          *M0               `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -447,7 +447,7 @@
 }
 
 type M5_GetGetFoo_ struct {
-	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo_ int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*M5_GetGetFoo_) isM5_GetGetGetFoo() {}
@@ -468,8 +468,8 @@
 	//
 	//	*M6_GetGetGetFoo
 	GetGetFoo     isM6_GetGetFoo `protobuf_oneof:"get_get_foo"`
-	GetFoo_       *M0            `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0            `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo_       *M0            `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0            `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -539,7 +539,7 @@
 }
 
 type M6_GetGetGetFoo struct {
-	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,oneof"`
+	GetGetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_get_foo,json=getGetGetFoo,proto3,oneof"`
 }
 
 func (*M6_GetGetGetFoo) isM6_GetGetFoo() {}
@@ -561,7 +561,7 @@
 	//	*M7_Bar
 	//	*M7_GetFoo_
 	GetGetFoo     isM7_GetGetFoo `protobuf_oneof:"get_get_foo"`
-	Foo           *M0            `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo           *M0            `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -633,11 +633,11 @@
 }
 
 type M7_Bar struct {
-	Bar bool `protobuf:"varint,4,opt,name=bar,oneof"`
+	Bar bool `protobuf:"varint,4,opt,name=bar,proto3,oneof"`
 }
 
 type M7_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,3,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*M7_Bar) isM7_GetGetFoo() {}
@@ -660,8 +660,8 @@
 	//
 	//	*M8_GetGetFoo
 	GetGetGetFoo_ isM8_GetGetGetFoo_ `protobuf_oneof:"get_get_get_foo"`
-	GetFoo_       *M0                `protobuf:"bytes,2,opt,name=get_foo,json=getFoo" json:"get_foo,omitempty"`
-	Foo           *M0                `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	GetFoo_       *M0                `protobuf:"bytes,2,opt,name=get_foo,json=getFoo,proto3" json:"get_foo,omitempty"`
+	Foo           *M0                `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -731,7 +731,7 @@
 }
 
 type M8_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 func (*M8_GetGetFoo) isM8_GetGetGetFoo_() {}
@@ -753,7 +753,7 @@
 	//	*M9_GetGetFoo
 	//	*M9_GetFoo_
 	GetGetGetFoo_ isM9_GetGetGetFoo_ `protobuf_oneof:"get_get_get_foo"`
-	Foo           *M0                `protobuf:"bytes,1,opt,name=foo" json:"foo,omitempty"`
+	Foo           *M0                `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -825,17 +825,77 @@
 }
 
 type M9_GetGetFoo struct {
-	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,oneof"`
+	GetGetFoo int32 `protobuf:"varint,3,opt,name=get_get_foo,json=getGetFoo,proto3,oneof"`
 }
 
 type M9_GetFoo_ struct {
-	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,oneof"`
+	GetFoo_ int32 `protobuf:"varint,2,opt,name=get_foo,json=getFoo,proto3,oneof"`
 }
 
 func (*M9_GetGetFoo) isM9_GetGetGetFoo_() {}
 
 func (*M9_GetFoo_) isM9_GetGetGetFoo_() {}
 
+type M21 struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	XFoo          string                 `protobuf:"bytes,1,opt,name=_foo,json=Foo,proto3" json:"_foo,omitempty"`
+	XFoo_         string                 `protobuf:"bytes,2,opt,name=X_foo,json=XFoo,proto3" json:"X_foo,omitempty"`
+	GetXFoo__     string                 `protobuf:"bytes,3,opt,name=get_x_foo,json=getXFoo,proto3" json:"get_x_foo,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *M21) Reset() {
+	*x = M21{}
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_msgTypes[10]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *M21) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*M21) ProtoMessage() {}
+
+func (x *M21) ProtoReflect() protoreflect.Message {
+	mi := &file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_msgTypes[10]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use M21.ProtoReflect.Descriptor instead.
+func (*M21) Descriptor() ([]byte, []int) {
+	return file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *M21) GetXFoo() string {
+	if x != nil {
+		return x.XFoo
+	}
+	return ""
+}
+
+func (x *M21) GetXFoo_() string {
+	if x != nil {
+		return x.XFoo_
+	}
+	return ""
+}
+
+func (x *M21) GetGetXFoo__() string {
+	if x != nil {
+		return x.GetXFoo__
+	}
+	return ""
+}
+
 var File_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto protoreflect.FileDescriptor
 
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_rawDesc = string([]byte{
@@ -953,14 +1013,18 @@
 	0x6f, 0x74, 0x6f, 0x32, 0x2e, 0x67, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61,
 	0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x6f, 0x70, 0x65, 0x6e, 0x33, 0x2e,
 	0x4d, 0x30, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x42, 0x11, 0x0a, 0x0f, 0x67, 0x65, 0x74, 0x5f, 0x67,
-	0x65, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x6f, 0x42, 0x61, 0x5a, 0x55, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64,
-	0x61, 0x74, 0x61, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65,
-	0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70,
-	0x65, 0x6e, 0x33, 0x92, 0x03, 0x07, 0xd2, 0x3e, 0x02, 0x10, 0x01, 0x08, 0x02, 0x62, 0x08, 0x65,
-	0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07,
+	0x65, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x6f, 0x22, 0x49, 0x0a, 0x03, 0x4d, 0x32,
+	0x31, 0x12, 0x11, 0x0a, 0x04, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x46, 0x6f, 0x6f, 0x12, 0x13, 0x0a, 0x05, 0x58, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x58, 0x46, 0x6f, 0x6f, 0x12, 0x1a, 0x0a, 0x09, 0x67, 0x65, 0x74,
+	0x5f, 0x78, 0x5f, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65,
+	0x74, 0x58, 0x46, 0x6f, 0x6f, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67,
+	0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x6e,
+	0x61, 0x6d, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x61,
+	0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x33, 0x62, 0x06,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 })
 
 var (
@@ -975,18 +1039,19 @@
 	return file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_rawDescData
 }
 
-var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_goTypes = []any{
-	(*M0)(nil), // 0: net.proto2.go.testdata.nameclashopen3.M0
-	(*M1)(nil), // 1: net.proto2.go.testdata.nameclashopen3.M1
-	(*M2)(nil), // 2: net.proto2.go.testdata.nameclashopen3.M2
-	(*M3)(nil), // 3: net.proto2.go.testdata.nameclashopen3.M3
-	(*M4)(nil), // 4: net.proto2.go.testdata.nameclashopen3.M4
-	(*M5)(nil), // 5: net.proto2.go.testdata.nameclashopen3.M5
-	(*M6)(nil), // 6: net.proto2.go.testdata.nameclashopen3.M6
-	(*M7)(nil), // 7: net.proto2.go.testdata.nameclashopen3.M7
-	(*M8)(nil), // 8: net.proto2.go.testdata.nameclashopen3.M8
-	(*M9)(nil), // 9: net.proto2.go.testdata.nameclashopen3.M9
+	(*M0)(nil),  // 0: net.proto2.go.testdata.nameclashopen3.M0
+	(*M1)(nil),  // 1: net.proto2.go.testdata.nameclashopen3.M1
+	(*M2)(nil),  // 2: net.proto2.go.testdata.nameclashopen3.M2
+	(*M3)(nil),  // 3: net.proto2.go.testdata.nameclashopen3.M3
+	(*M4)(nil),  // 4: net.proto2.go.testdata.nameclashopen3.M4
+	(*M5)(nil),  // 5: net.proto2.go.testdata.nameclashopen3.M5
+	(*M6)(nil),  // 6: net.proto2.go.testdata.nameclashopen3.M6
+	(*M7)(nil),  // 7: net.proto2.go.testdata.nameclashopen3.M7
+	(*M8)(nil),  // 8: net.proto2.go.testdata.nameclashopen3.M8
+	(*M9)(nil),  // 9: net.proto2.go.testdata.nameclashopen3.M9
+	(*M21)(nil), // 10: net.proto2.go.testdata.nameclashopen3.M21
 }
 var file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_depIdxs = []int32{
 	0,  // 0: net.proto2.go.testdata.nameclashopen3.M1.foo:type_name -> net.proto2.go.testdata.nameclashopen3.M0
@@ -1046,7 +1111,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_rawDesc), len(file_cmd_protoc_gen_go_testdata_nameclash_test_name_clash_open3_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   10,
+			NumMessages:   11,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/compiler/protogen/protogen_opaque.go b/compiler/protogen/protogen_opaque.go
index 8b11cdb..1c84b0c 100644
--- a/compiler/protogen/protogen_opaque.go
+++ b/compiler/protogen/protogen_opaque.go
@@ -5,6 +5,8 @@
 package protogen
 
 import (
+	"strconv"
+
 	"google.golang.org/protobuf/internal/strs"
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
@@ -17,6 +19,33 @@
 	oneof.camelCase = strs.GoCamelCase(string(desc.Name()))
 }
 
+func resolveCamelCaseConflict(f *Field) {
+	suffix := "_" + strconv.Itoa(int(f.Desc.Number()))
+	f.camelCase += suffix
+	if f.Oneof != nil {
+		f.Oneof.camelCase += suffix
+	}
+}
+
+// This function finds fields with different names whose GoCamelCase() is
+// identical, for example _foo and X_foo, for both of which camelCase == "XFoo",
+// and resolves the resulting conflict by appending a _<fieldnum> suffix,
+// like the Java implementation does.
+func resolveCamelCaseConflicts(message *Message) {
+	camel2field := make(map[string]*Field)
+	for _, field := range message.Fields {
+		other, conflicting := camel2field[field.camelCase]
+		if conflicting {
+			resolveCamelCaseConflict(other)
+			resolveCamelCaseConflict(field)
+			// Assumption: at most two fields can have the same camelCase.
+			// Otherwise, the first field ends up with another suffix.
+			continue
+		}
+		camel2field[field.camelCase] = field
+	}
+}
+
 func opaqueNewMessageHook(message *Message) {
 	// New name mangling scheme: Add a '_' between method base
 	// name (Get, Set, Clear etc) and original field name if
@@ -33,17 +62,19 @@
 	// Then find all names of the original field names, we do not want the old scheme to affect
 	// how we name things.
 
+	resolveCamelCaseConflicts(message)
+
 	camelCases := map[string]bool{}
 	for _, field := range message.Fields {
 		if field.Oneof != nil {
 			// We add the name of the union here (potentially many times).
 			camelCases[field.Oneof.camelCase] = true
+			// fallthrough: The member fields of the oneof are considered fields
+			// in the struct although they are not technically there. This is to
+			// allow changing a proto2 optional to a oneof with source code
+			// compatibility.
 		}
-		// The member fields of the oneof are considered fields in the struct although
-		// they are not technically there. This is to allow changing a proto2 optional
-		// to a oneof with source code compatibility.
 		camelCases[field.camelCase] = true
-
 	}
 	// For each field, check if any of it's methods would clash with an original field name
 	for _, field := range message.Fields {
diff --git a/internal/cmd/generate-protos/main.go b/internal/cmd/generate-protos/main.go
index c42f908..81bfddc 100644
--- a/internal/cmd/generate-protos/main.go
+++ b/internal/cmd/generate-protos/main.go
@@ -389,6 +389,16 @@
 					opts += fmt.Sprintf(",apilevelM%v=%v", relPath, "API_OPAQUE")
 				}
 			}
+			if strings.HasPrefix(relPath, "cmd/protoc-gen-go/testdata/nameclash/") {
+				switch path.Base(relPath) {
+				case "test_name_clash_hybrid3.proto":
+					opts += fmt.Sprintf(",apilevelM%v=%v", relPath, "API_HYBRID")
+				case "test_name_clash_opaque3.proto":
+					opts += fmt.Sprintf(",apilevelM%v=%v", relPath, "API_OPAQUE")
+				case "test_name_clash_open3.proto":
+					opts += fmt.Sprintf(",apilevelM%v=%v", relPath, "API_OPEN")
+				}
+			}
 			protoc("-I"+filepath.Join(repoRoot, "src"), "-I"+filepath.Join(protoRoot, "src"), "-I"+repoRoot, "--go_out="+opts+":"+tmpDir, filepath.Join(repoRoot, relPath))
 			return nil
 		})