Lock down ctype=CORD in proto file.

ctype can not be used for none string/bytes fields. ctye=CORD can not be used for extensions. A new macro PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE is added that will be flipped for our next breaking release.

PiperOrigin-RevId: 555615362
diff --git a/csharp/protos/unittest.proto b/csharp/protos/unittest.proto
index 03e1978..03527f7 100644
--- a/csharp/protos/unittest.proto
+++ b/csharp/protos/unittest.proto
@@ -258,7 +258,7 @@
       optional_import_enum_extension = 23;
 
   optional string optional_string_piece_extension = 24 [ctype = STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype = CORD];
+  optional string optional_cord_extension = 25;
 
   optional protobuf_unittest_import_proto2.PublicImportMessage
       optional_public_import_message_extension = 26;
@@ -298,7 +298,7 @@
       repeated_import_enum_extension = 53;
 
   repeated string repeated_string_piece_extension = 54 [ctype = STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype = CORD];
+  repeated string repeated_cord_extension = 55;
 
   repeated TestAllTypes.NestedMessage repeated_lazy_message_extension = 57
       [lazy = true];
@@ -329,7 +329,7 @@
 
   optional string default_string_piece_extension = 84
       [ctype = STRING_PIECE, default = "abc"];
-  optional string default_cord_extension = 85 [ctype = CORD, default = "123"];
+  optional string default_cord_extension = 85 [default = "123"];
 
   // For oneof test
   optional uint32 oneof_uint32_extension = 111;
diff --git a/objectivec/Tests/unittest.proto b/objectivec/Tests/unittest.proto
index 3c90fd9..9550c55 100644
--- a/objectivec/Tests/unittest.proto
+++ b/objectivec/Tests/unittest.proto
@@ -244,7 +244,7 @@
     optional_import_enum_extension = 23;
 
   optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype=CORD];
+  optional string optional_cord_extension = 25;
 
   optional objc.protobuf.tests.public_import.Message
     optional_public_import_message_extension = 26;
@@ -286,7 +286,7 @@
     repeated_import_enum_extension = 53;
 
   repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype=CORD];
+  repeated string repeated_cord_extension = 55;
 
   repeated TestAllTypes.NestedMessage
     repeated_lazy_message_extension = 57 [lazy=true];
@@ -317,7 +317,7 @@
 
   optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
                                                        default="abc"];
-  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
+  optional string default_cord_extension = 85 [default="123"];
 
   // For oneof test
   optional uint32 oneof_uint32_extension = 111;
diff --git a/src/google/protobuf/compiler/cpp/generator.cc b/src/google/protobuf/compiler/cpp/generator.cc
index c23a71b..d5b39aa 100644
--- a/src/google/protobuf/compiler/cpp/generator.cc
+++ b/src/google/protobuf/compiler/cpp/generator.cc
@@ -379,6 +379,22 @@
           absl::StrCat("Field ", field.full_name(),
                        " has a closed enum type with implicit presence."));
     }
+#ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE
+    if (field.options().has_ctype()) {
+      if (field.cpp_type() != FieldDescriptor::CPPTYPE_STRING) {
+        status = absl::FailedPreconditionError(absl::StrCat(
+            "Field ", field.full_name(),
+            " specifies ctype, but is not a string nor bytes field."));
+      }
+      if (field.options().ctype() == FieldOptions::CORD) {
+        if (field.is_extension()) {
+          status = absl::FailedPreconditionError(absl::StrCat(
+              "Extension ", field.full_name(),
+              " specifies ctype=CORD which is not supported for extensions."));
+        }
+      }
+    }
+#endif  // !PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE
   });
   return status;
 }
diff --git a/src/google/protobuf/compiler/cpp/generator_unittest.cc b/src/google/protobuf/compiler/cpp/generator_unittest.cc
index 0eabb09..b5ac6bc 100644
--- a/src/google/protobuf/compiler/cpp/generator_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/generator_unittest.cc
@@ -172,6 +172,40 @@
       "Field Foo.bar has a closed enum type with implicit presence.");
 }
 
+#ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE
+TEST_F(CppGeneratorTest, CtypeOnNoneStringFieldTest) {
+  CreateTempFile("foo.proto",
+                 R"schema(
+    edition = "2023";
+    message Foo {
+      int32 bar = 1 [ctype=STRING];
+    })schema");
+  RunProtoc(
+      "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
+      "--experimental_editions foo.proto");
+  ExpectErrorSubstring(
+      "Field Foo.bar specifies ctype, but is not "
+      "a string nor bytes field.");
+}
+
+TEST_F(CppGeneratorTest, CtypeOnExtensionTest) {
+  CreateTempFile("foo.proto",
+                 R"schema(
+    edition = "2023";
+    message Foo {
+      extensions 1 to max;
+    }
+    extend Foo {
+      bytes bar = 1 [ctype=CORD];
+    })schema");
+  RunProtoc(
+      "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
+      "--experimental_editions foo.proto");
+  ExpectErrorSubstring(
+      "Extension bar specifies ctype=CORD which is "
+      "not supported for extensions.");
+}
+#endif  // !PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE
 }  // namespace
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 155997f..a831265 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -246,6 +246,10 @@
 // Owner: mkruskal@
 #define PROTOBUF_FUTURE_EXTENSION_RANGE_CLASS 1
 
+// Used to lock down wrong ctype usages in proto file.
+// Owner: jieluo@
+#define PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE 1
+
 #endif
 
 #ifdef PROTOBUF_VERSION
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index b40749a..ec71dc7 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -267,7 +267,9 @@
     optional_import_enum_extension = 23;
 
   optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype=CORD];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  optional string optional_cord_extension = 25;
 
   optional protobuf_unittest_import.PublicImportMessage
     optional_public_import_message_extension = 26;
@@ -309,7 +311,9 @@
     repeated_import_enum_extension = 53;
 
   repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype=CORD];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  repeated string repeated_cord_extension = 55;
 
   repeated TestAllTypes.NestedMessage
     repeated_lazy_message_extension = 57 [lazy=true];
@@ -340,7 +344,9 @@
 
   optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
                                                        default="abc"];
-  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  optional string default_cord_extension = 85 [default="123"];
 
   // For oneof test
   optional uint32 oneof_uint32_extension = 111;
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index b594b6f..7cfba28 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -243,7 +243,9 @@
 
   optional string optional_string_piece_extension_lite = 24
       [ctype = STRING_PIECE];
-  optional string optional_cord_extension_lite = 25 [ctype = CORD];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  optional string optional_cord_extension_lite = 25;
 
   optional protobuf_unittest_import.PublicImportMessageLite
       optional_public_import_message_extension_lite = 26;
@@ -288,7 +290,9 @@
 
   repeated string repeated_string_piece_extension_lite = 54
       [ctype = STRING_PIECE];
-  repeated string repeated_cord_extension_lite = 55 [ctype = CORD];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  repeated string repeated_cord_extension_lite = 55;
 
   repeated TestAllTypesLite.NestedMessage repeated_lazy_message_extension_lite =
       57 [lazy = true];
@@ -319,8 +323,9 @@
 
   optional string default_string_piece_extension_lite = 84
       [ctype = STRING_PIECE, default = "abc"];
-  optional string default_cord_extension_lite = 85
-      [ctype = CORD, default = "123"];
+  // TODO(b/294946958): ctype=CORD is not supported for extension. Add
+  // ctype=CORD option back after it is supported.
+  optional string default_cord_extension_lite = 85 [default = "123"];
 
   // For oneof test
   optional uint32 oneof_uint32_extension_lite = 111;