Merge pull request #8499 from haberman/sync-stage
Integrate from Piper for C++, Java, and Python
diff --git a/BUILD b/BUILD
index 07ee629..1788cfc 100644
--- a/BUILD
+++ b/BUILD
@@ -369,6 +369,7 @@
"src/google/protobuf/compiler/cpp/cpp_message.cc",
"src/google/protobuf/compiler/cpp/cpp_message_field.cc",
"src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc",
+ "src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc",
"src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
"src/google/protobuf/compiler/cpp/cpp_service.cc",
"src/google/protobuf/compiler/cpp/cpp_string_field.cc",
diff --git a/CHANGES.txt b/CHANGES.txt
index 93ee2b8..9e6eb44 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,17 @@
+
Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
C++
+ * Fix bug where `Descriptor::DebugString()` printed proto3 synthetic oneofs.
+ * Provide stable versions of `SortAndUnique()`.
+ * Make sure to cache proto3 optional message fields when they are cleared.
+
+ Kotlin
+ * Restrict extension setter and getter operators to non-nullable T.
+
+3.16.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+ C++
* The ::pb namespace is no longer exposed due to conflicts.
* Allow MessageDifferencer::TreatAsSet() (and friends) to override previous
calls instead of crashing.
diff --git a/build_files_updated_unittest.sh b/build_files_updated_unittest.sh
index c863071..87541c3 100755
--- a/build_files_updated_unittest.sh
+++ b/build_files_updated_unittest.sh
@@ -58,5 +58,5 @@
# Test whether there are any differences
for file in ${generated_files[@]}; do
- diff "${golden_dir}/${file}" "${test_dir}/${file}"
+ diff -du "${golden_dir}/${file}" "${test_dir}/${file}"
done
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index ecb5a85..899304d 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -12,6 +12,7 @@
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
+ ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -96,6 +97,7 @@
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_names.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
+ ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.h
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java
index 5319982..100bec4 100644
--- a/conformance/ConformanceJava.java
+++ b/conformance/ConformanceJava.java
@@ -54,7 +54,7 @@
while (len > 0) {
int read = System.in.read(buf, ofs, len);
if (read == -1) {
- return false; // EOF
+ return false; // EOF
}
ofs += read;
len -= read;
@@ -81,10 +81,10 @@
private void writeLittleEndianIntToStdout(int val) throws Exception {
byte[] buf = new byte[4];
- buf[0] = (byte)val;
- buf[1] = (byte)(val >> 8);
- buf[2] = (byte)(val >> 16);
- buf[3] = (byte)(val >> 24);
+ buf[0] = (byte) val;
+ buf[1] = (byte) (val >> 8);
+ buf[2] = (byte) (val >> 16);
+ buf[3] = (byte) (val >> 24);
writeToStdout(buf);
}
@@ -98,85 +98,71 @@
INPUT_STREAM_DECODER;
}
- private static class BinaryDecoder <MessageType extends AbstractMessage> {
- public MessageType decode (ByteString bytes, BinaryDecoderType type,
- Parser <MessageType> parser, ExtensionRegistry extensions)
- throws InvalidProtocolBufferException {
+ private static class BinaryDecoder<T extends AbstractMessage> {
+ public T decode(
+ ByteString bytes, BinaryDecoderType type, Parser<T> parser, ExtensionRegistry extensions)
+ throws InvalidProtocolBufferException {
switch (type) {
case BTYE_STRING_DECODER:
- return parser.parseFrom(bytes, extensions);
case BYTE_ARRAY_DECODER:
- return parser.parseFrom(bytes.toByteArray(), extensions);
- case ARRAY_BYTE_BUFFER_DECODER: {
- ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
- bytes.copyTo(buffer);
- buffer.flip();
- try {
+ return parser.parseFrom(bytes, extensions);
+ case ARRAY_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
- } catch (InvalidProtocolBufferException e) {
- throw e;
}
- }
- case READONLY_ARRAY_BYTE_BUFFER_DECODER: {
- try {
+ case READONLY_ARRAY_BYTE_BUFFER_DECODER:
+ {
return parser.parseFrom(
CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
- } catch (InvalidProtocolBufferException e) {
- throw e;
}
- }
- case DIRECT_BYTE_BUFFER_DECODER: {
- ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
- bytes.copyTo(buffer);
- buffer.flip();
- try {
+ case DIRECT_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
- } catch (InvalidProtocolBufferException e) {
- throw e;
}
- }
- case READONLY_DIRECT_BYTE_BUFFER_DECODER: {
- ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
- bytes.copyTo(buffer);
- buffer.flip();
- try {
+ case READONLY_DIRECT_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
return parser.parseFrom(
CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
- } catch (InvalidProtocolBufferException e) {
- throw e;
}
- }
- case INPUT_STREAM_DECODER: {
- try {
+ case INPUT_STREAM_DECODER:
+ {
return parser.parseFrom(bytes.newInput(), extensions);
- } catch (InvalidProtocolBufferException e) {
- throw e;
}
- }
- default :
- return null;
}
+ return null;
}
}
- private <MessageType extends AbstractMessage> MessageType parseBinary(
- ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions)
+ private <T extends AbstractMessage> T parseBinary(
+ ByteString bytes, Parser<T> parser, ExtensionRegistry extensions)
throws InvalidProtocolBufferException {
- ArrayList <MessageType> messages = new ArrayList <MessageType> ();
- ArrayList <InvalidProtocolBufferException> exceptions =
- new ArrayList <InvalidProtocolBufferException>();
+ ArrayList<T> messages = new ArrayList<>();
+ ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>();
for (int i = 0; i < BinaryDecoderType.values().length; i++) {
messages.add(null);
exceptions.add(null);
}
- BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> ();
+ if (messages.isEmpty()) {
+ throw new RuntimeException("binary decoder types missing");
+ }
+
+ BinaryDecoder<T> decoder = new BinaryDecoder<>();
boolean hasMessage = false;
boolean hasException = false;
for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
try {
- //= BinaryDecoderType.values()[i].parseProto3(bytes);
+ // = BinaryDecoderType.values()[i].parseProto3(bytes);
messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
hasMessage = true;
} catch (InvalidProtocolBufferException e) {
@@ -202,7 +188,15 @@
if (hasException) {
// We do not check if exceptions are equal. Different implementations may return different
// exception messages. Throw an arbitrary one out instead.
- throw exceptions.get(0);
+ InvalidProtocolBufferException exception = null;
+ for (InvalidProtocolBufferException e : exceptions) {
+ if (exception != null) {
+ exception.addSuppressed(e);
+ } else {
+ exception = e;
+ }
+ }
+ throw exception;
}
// Fast path comparing all the messages with the first message, assuming equality being
@@ -242,115 +236,138 @@
request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
switch (request.getPayloadCase()) {
- case PROTOBUF_PAYLOAD: {
- if (isProto3) {
- try {
- ExtensionRegistry extensions = ExtensionRegistry.newInstance();
- TestMessagesProto3.registerAllExtensions(extensions);
- testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
- } catch (InvalidProtocolBufferException e) {
- return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
- }
- } else if (isProto2) {
- try {
- ExtensionRegistry extensions = ExtensionRegistry.newInstance();
- TestMessagesProto2.registerAllExtensions(extensions);
- testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
- } catch (InvalidProtocolBufferException e) {
- return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
- }
- } else {
- throw new RuntimeException("Protobuf request doesn't have specific payload type.");
- }
- break;
- }
- case JSON_PAYLOAD: {
- try {
- JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry);
- if (request.getTestCategory()
- == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
- parser = parser.ignoringUnknownFields();
- }
+ case PROTOBUF_PAYLOAD:
+ {
if (isProto3) {
- TestMessagesProto3.TestAllTypesProto3.Builder builder =
- TestMessagesProto3.TestAllTypesProto3.newBuilder();
- parser.merge(request.getJsonPayload(), builder);
- testMessage = builder.build();
+ try {
+ ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+ TestMessagesProto3.registerAllExtensions(extensions);
+ testMessage =
+ parseBinary(
+ request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setParseError(e.getMessage())
+ .build();
+ }
} else if (isProto2) {
- TestMessagesProto2.TestAllTypesProto2.Builder builder =
- TestMessagesProto2.TestAllTypesProto2.newBuilder();
- parser.merge(request.getJsonPayload(), builder);
- testMessage = builder.build();
+ try {
+ ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+ TestMessagesProto2.registerAllExtensions(extensions);
+ testMessage =
+ parseBinary(
+ request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setParseError(e.getMessage())
+ .build();
+ }
} else {
throw new RuntimeException("Protobuf request doesn't have specific payload type.");
}
- } catch (InvalidProtocolBufferException e) {
- return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ break;
}
- break;
- }
- case TEXT_PAYLOAD: {
- if (isProto3) {
+ case JSON_PAYLOAD:
+ {
try {
- TestMessagesProto3.TestAllTypesProto3.Builder builder =
- TestMessagesProto3.TestAllTypesProto3.newBuilder();
- TextFormat.merge(request.getTextPayload(), builder);
- testMessage = builder.build();
- } catch (TextFormat.ParseException e) {
+ JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry);
+ if (request.getTestCategory()
+ == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
+ parser = parser.ignoringUnknownFields();
+ }
+ if (isProto3) {
+ TestMessagesProto3.TestAllTypesProto3.Builder builder =
+ TestMessagesProto3.TestAllTypesProto3.newBuilder();
+ parser.merge(request.getJsonPayload(), builder);
+ testMessage = builder.build();
+ } else if (isProto2) {
+ TestMessagesProto2.TestAllTypesProto2.Builder builder =
+ TestMessagesProto2.TestAllTypesProto2.newBuilder();
+ parser.merge(request.getJsonPayload(), builder);
+ testMessage = builder.build();
+ } else {
+ throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+ }
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setParseError(e.getMessage())
+ .build();
+ }
+ break;
+ }
+ case TEXT_PAYLOAD:
+ {
+ if (isProto3) {
+ try {
+ TestMessagesProto3.TestAllTypesProto3.Builder builder =
+ TestMessagesProto3.TestAllTypesProto3.newBuilder();
+ TextFormat.merge(request.getTextPayload(), builder);
+ testMessage = builder.build();
+ } catch (TextFormat.ParseException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
- }
- } else if (isProto2) {
- try {
- TestMessagesProto2.TestAllTypesProto2.Builder builder =
- TestMessagesProto2.TestAllTypesProto2.newBuilder();
- TextFormat.merge(request.getTextPayload(), builder);
- testMessage = builder.build();
- } catch (TextFormat.ParseException e) {
+ }
+ } else if (isProto2) {
+ try {
+ TestMessagesProto2.TestAllTypesProto2.Builder builder =
+ TestMessagesProto2.TestAllTypesProto2.newBuilder();
+ TextFormat.merge(request.getTextPayload(), builder);
+ testMessage = builder.build();
+ } catch (TextFormat.ParseException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
+ }
+ } else {
+ throw new RuntimeException("Protobuf request doesn't have specific payload type.");
}
- } else {
- throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+ break;
}
- break;
- }
- case PAYLOAD_NOT_SET: {
- throw new RuntimeException("Request didn't have payload.");
- }
+ case PAYLOAD_NOT_SET:
+ {
+ throw new RuntimeException("Request didn't have payload.");
+ }
- default: {
- throw new RuntimeException("Unexpected payload case.");
- }
+ default:
+ {
+ throw new RuntimeException("Unexpected payload case.");
+ }
}
switch (request.getRequestedOutputFormat()) {
case UNSPECIFIED:
throw new RuntimeException("Unspecified output format.");
- case PROTOBUF: {
- ByteString MessageString = testMessage.toByteString();
- return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build();
- }
+ case PROTOBUF:
+ {
+ ByteString messageString = testMessage.toByteString();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setProtobufPayload(messageString)
+ .build();
+ }
case JSON:
try {
- return Conformance.ConformanceResponse.newBuilder().setJsonPayload(
- JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setJsonPayload(
+ JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage))
+ .build();
} catch (InvalidProtocolBufferException | IllegalArgumentException e) {
- return Conformance.ConformanceResponse.newBuilder().setSerializeError(
- e.getMessage()).build();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setSerializeError(e.getMessage())
+ .build();
}
case TEXT_FORMAT:
- return Conformance.ConformanceResponse.newBuilder().setTextPayload(
- TextFormat.printToString(testMessage)).build();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setTextPayload(TextFormat.printToString(testMessage))
+ .build();
- default: {
- throw new RuntimeException("Unexpected request output.");
- }
+ default:
+ {
+ throw new RuntimeException("Unexpected request output.");
+ }
}
}
@@ -358,7 +375,7 @@
int bytes = readLittleEndianIntFromStdin();
if (bytes == -1) {
- return false; // EOF
+ return false; // EOF
}
byte[] serializedInput = new byte[bytes];
@@ -379,14 +396,16 @@
}
public void run() throws Exception {
- typeRegistry = TypeRegistry.newBuilder().add(
- TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build();
+ typeRegistry =
+ TypeRegistry.newBuilder()
+ .add(TestMessagesProto3.TestAllTypesProto3.getDescriptor())
+ .build();
while (doTestIo()) {
this.testCount++;
}
- System.err.println("ConformanceJava: received EOF from test runner after " +
- this.testCount + " tests");
+ System.err.println(
+ "ConformanceJava: received EOF from test runner after " + this.testCount + " tests");
}
public static void main(String[] args) throws Exception {
diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java
index 147738d..eb3d06a 100644
--- a/conformance/ConformanceJavaLite.java
+++ b/conformance/ConformanceJavaLite.java
@@ -28,8 +28,19 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.Parser;
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
class ConformanceJavaLite {
private int testCount = 0;
@@ -39,7 +50,7 @@
while (len > 0) {
int read = System.in.read(buf, ofs, len);
if (read == -1) {
- return false; // EOF
+ return false; // EOF
}
ofs += read;
len -= read;
@@ -66,36 +77,214 @@
private void writeLittleEndianIntToStdout(int val) throws Exception {
byte[] buf = new byte[4];
- buf[0] = (byte)val;
- buf[1] = (byte)(val >> 8);
- buf[2] = (byte)(val >> 16);
- buf[3] = (byte)(val >> 24);
+ buf[0] = (byte) val;
+ buf[1] = (byte) (val >> 8);
+ buf[2] = (byte) (val >> 16);
+ buf[3] = (byte) (val >> 24);
writeToStdout(buf);
}
- private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
- Conformance.TestAllTypes testMessage;
+ private enum BinaryDecoderType {
+ BTYE_STRING_DECODER,
+ BYTE_ARRAY_DECODER,
+ ARRAY_BYTE_BUFFER_DECODER,
+ READONLY_ARRAY_BYTE_BUFFER_DECODER,
+ DIRECT_BYTE_BUFFER_DECODER,
+ READONLY_DIRECT_BYTE_BUFFER_DECODER,
+ INPUT_STREAM_DECODER;
+ }
- switch (request.getPayloadCase()) {
- case PROTOBUF_PAYLOAD: {
- try {
- testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
- } catch (InvalidProtocolBufferException e) {
- return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ private static class BinaryDecoder<T extends MessageLite> {
+ public T decode(
+ ByteString bytes,
+ BinaryDecoderType type,
+ Parser<T> parser,
+ ExtensionRegistryLite extensions)
+ throws InvalidProtocolBufferException {
+ switch (type) {
+ case BTYE_STRING_DECODER:
+ case BYTE_ARRAY_DECODER:
+ return parser.parseFrom(bytes, extensions);
+ case ARRAY_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+ }
+ case READONLY_ARRAY_BYTE_BUFFER_DECODER:
+ {
+ return parser.parseFrom(
+ CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
+ }
+ case DIRECT_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+ }
+ case READONLY_DIRECT_BYTE_BUFFER_DECODER:
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ return parser.parseFrom(
+ CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
+ }
+ case INPUT_STREAM_DECODER:
+ {
+ return parser.parseFrom(bytes.newInput(), extensions);
+ }
+ }
+ return null;
+ }
+ }
+
+ private <T extends MessageLite> T parseBinary(
+ ByteString bytes, Parser<T> parser, ExtensionRegistryLite extensions)
+ throws InvalidProtocolBufferException {
+ ArrayList<T> messages = new ArrayList<>();
+ ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>();
+
+ for (int i = 0; i < BinaryDecoderType.values().length; i++) {
+ messages.add(null);
+ exceptions.add(null);
+ }
+ if (messages.isEmpty()) {
+ throw new RuntimeException("binary decoder types missing");
+ }
+
+ BinaryDecoder<T> decoder = new BinaryDecoder<>();
+
+ boolean hasMessage = false;
+ boolean hasException = false;
+ for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+ try {
+ messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
+ hasMessage = true;
+ } catch (InvalidProtocolBufferException e) {
+ exceptions.set(i, e);
+ hasException = true;
+ }
+ }
+
+ if (hasMessage && hasException) {
+ StringBuilder sb =
+ new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
+ for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+ sb.append(BinaryDecoderType.values()[i].name());
+ if (messages.get(i) != null) {
+ sb.append(" accepted the payload.\n");
+ } else {
+ sb.append(" rejected the payload.\n");
}
+ }
+ throw new RuntimeException(sb.toString());
+ }
+
+ if (hasException) {
+ // We do not check if exceptions are equal. Different implementations may return different
+ // exception messages. Throw an arbitrary one out instead.
+ InvalidProtocolBufferException exception = null;
+ for (InvalidProtocolBufferException e : exceptions) {
+ if (exception != null) {
+ exception.addSuppressed(e);
+ } else {
+ exception = e;
+ }
+ }
+ throw exception;
+ }
+
+ // Fast path comparing all the messages with the first message, assuming equality being
+ // symmetric and transitive.
+ boolean allEqual = true;
+ for (int i = 1; i < messages.size(); ++i) {
+ if (!messages.get(0).equals(messages.get(i))) {
+ allEqual = false;
break;
}
- case JSON_PAYLOAD: {
- return Conformance.ConformanceResponse.newBuilder().setSkipped(
- "Lite runtime does not support JSON format.").build();
- }
- case PAYLOAD_NOT_SET: {
- throw new RuntimeException("Request didn't have payload.");
- }
+ }
- default: {
- throw new RuntimeException("Unexpected payload case.");
+ // Slow path: compare and find out all unequal pairs.
+ if (!allEqual) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < messages.size() - 1; ++i) {
+ for (int j = i + 1; j < messages.size(); ++j) {
+ if (!messages.get(i).equals(messages.get(j))) {
+ sb.append(BinaryDecoderType.values()[i].name())
+ .append(" and ")
+ .append(BinaryDecoderType.values()[j].name())
+ .append(" parsed the payload differently.\n");
+ }
+ }
}
+ throw new RuntimeException(sb.toString());
+ }
+
+ return messages.get(0);
+ }
+
+ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+ com.google.protobuf.MessageLite testMessage;
+ boolean isProto3 =
+ request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
+ boolean isProto2 =
+ request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
+
+ switch (request.getPayloadCase()) {
+ case PROTOBUF_PAYLOAD:
+ {
+ if (isProto3) {
+ try {
+ ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance();
+ TestMessagesProto3.registerAllExtensions(extensions);
+ testMessage =
+ parseBinary(
+ request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setParseError(e.getMessage())
+ .build();
+ }
+ } else if (isProto2) {
+ try {
+ ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance();
+ TestMessagesProto2.registerAllExtensions(extensions);
+ testMessage =
+ parseBinary(
+ request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setParseError(e.getMessage())
+ .build();
+ }
+ } else {
+ throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+ }
+ break;
+ }
+ case JSON_PAYLOAD:
+ {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setSkipped("Lite runtime does not support JSON format.")
+ .build();
+ }
+ case TEXT_PAYLOAD:
+ {
+ return Conformance.ConformanceResponse.newBuilder()
+ .setSkipped("Lite runtime does not support Text format.")
+ .build();
+ }
+ case PAYLOAD_NOT_SET:
+ {
+ throw new RuntimeException("Request didn't have payload.");
+ }
+ default:
+ {
+ throw new RuntimeException("Unexpected payload case.");
+ }
}
switch (request.getRequestedOutputFormat()) {
@@ -103,15 +292,23 @@
throw new RuntimeException("Unspecified output format.");
case PROTOBUF:
- return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setProtobufPayload(testMessage.toByteString())
+ .build();
case JSON:
- return Conformance.ConformanceResponse.newBuilder().setSkipped(
- "Lite runtime does not support JSON format.").build();
+ return Conformance.ConformanceResponse.newBuilder()
+ .setSkipped("Lite runtime does not support JSON format.")
+ .build();
- default: {
- throw new RuntimeException("Unexpected request output.");
- }
+ case TEXT_FORMAT:
+ return Conformance.ConformanceResponse.newBuilder()
+ .setSkipped("Lite runtime does not support Text format.")
+ .build();
+ default:
+ {
+ throw new RuntimeException("Unexpected request output.");
+ }
}
}
@@ -119,7 +316,7 @@
int bytes = readLittleEndianIntFromStdin();
if (bytes == -1) {
- return false; // EOF
+ return false; // EOF
}
byte[] serializedInput = new byte[bytes];
@@ -144,8 +341,8 @@
this.testCount++;
}
- System.err.println("ConformanceJavaLite: received EOF from test runner after " +
- this.testCount + " tests");
+ System.err.println(
+ "ConformanceJavaLite: received EOF from test runner after " + this.testCount + " tests");
}
public static void main(String[] args) throws Exception {
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index 042f69e..8b21683 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -32,9 +32,9 @@
"Eg4KBm51bWJlchgBIAEoCRIoCgR0eXBlGAIgASgOMhoudHV0b3JpYWwuUGVy",
"c29uLlBob25lVHlwZSIrCglQaG9uZVR5cGUSCgoGTU9CSUxFEAASCAoESE9N",
"RRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZwZW9wbGUYASADKAsy",
- "EC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUudHV0b3JpYWxCEUFk",
- "ZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVmLkV4YW1wbGVzLkFk",
- "ZHJlc3NCb29rYgZwcm90bzM="));
+ "EC50dXRvcmlhbC5QZXJzb25CWQobY29tLmV4YW1wbGUudHV0b3JpYWwucHJv",
+ "dG9zQhFBZGRyZXNzQm9va1Byb3Rvc1ABqgIkR29vZ2xlLlByb3RvYnVmLkV4",
+ "YW1wbGVzLkFkZHJlc3NCb29rYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index 7592be4..be1af7d 100644
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -32,8 +32,8 @@
"""
import os
-import warnings
import sys
+import warnings
try:
# pylint: disable=g-import-not-at-top
@@ -60,10 +60,11 @@
raise ImportError('_use_fast_cpp_protos import succeeded but was None')
del _use_fast_cpp_protos
_api_version = 2
- # Can not import both use_fast_cpp_protos and use_pure_python.
from google.protobuf import use_pure_python
raise RuntimeError(
- 'Conflict depend on both use_fast_cpp_protos and use_pure_python')
+ 'Conflicting deps on both :use_fast_cpp_protos and :use_pure_python.\n'
+ ' go/build_deps_on_BOTH_use_fast_cpp_protos_AND_use_pure_python\n'
+ 'This should be impossible via a link error at build time...')
except ImportError:
try:
# pylint: disable=g-import-not-at-top
diff --git a/src/Makefile.am b/src/Makefile.am
index 49fe6ed..18b1a43 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -345,6 +345,8 @@
google/protobuf/compiler/cpp/cpp_options.h \
google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \
google/protobuf/compiler/cpp/cpp_padding_optimizer.h \
+ google/protobuf/compiler/cpp/cpp_parse_function_generator.cc \
+ google/protobuf/compiler/cpp/cpp_parse_function_generator.h \
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
google/protobuf/compiler/cpp/cpp_primitive_field.h \
google/protobuf/compiler/cpp/cpp_service.cc \
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 5ecf63f..f061f5a 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -315,7 +315,7 @@
void Any::InternalSwap(Any* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
}
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 0f4facd..e818046 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -558,7 +558,7 @@
void Api::InternalSwap(Api* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
methods_.InternalSwap(&other->methods_);
options_.InternalSwap(&other->options_);
mixins_.InternalSwap(&other->mixins_);
@@ -953,7 +953,7 @@
void Method::InternalSwap(Method* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
options_.InternalSwap(&other->options_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
request_type_url_.Swap(&other->request_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -1200,7 +1200,7 @@
void Mixin::InternalSwap(Mixin* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
root_.Swap(&other->root_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
}
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index 75b0428..15ee4c1 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -279,7 +279,7 @@
public:
void clear_source_context();
const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
- PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
private:
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 8b5c7f1..59c9317 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -618,7 +618,6 @@
new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
RTTI_TYPE_ID(T)))
T(std::forward<Args>(args)...);
- result->SetOwningArena(arena);
return result;
}
}
@@ -646,7 +645,6 @@
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
- object->SetOwningArena(this);
}
}
template <typename T>
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
index 8ceab91..33f5cf4 100644
--- a/src/google/protobuf/arena_test_util.h
+++ b/src/google/protobuf/arena_test_util.h
@@ -92,6 +92,33 @@
} capture_alloc;
};
+// Owns the internal T only if it's not owned by an arena.
+// T needs to be arena constructible and destructor skippable.
+template <typename T>
+class ArenaHolder {
+ public:
+ explicit ArenaHolder(Arena* arena)
+ : field_(Arena::CreateMessage<T>(arena)),
+ owned_by_arena_(arena != nullptr) {
+ GOOGLE_DCHECK(google::protobuf::Arena::is_arena_constructable<T>::value);
+ GOOGLE_DCHECK(google::protobuf::Arena::is_destructor_skippable<T>::value);
+ }
+
+ ~ArenaHolder() {
+ if (!owned_by_arena_) {
+ delete field_;
+ }
+ }
+
+ T* get() { return field_; }
+ T* operator->() { return field_; }
+ T& operator*() { return *field_; }
+
+ private:
+ T* field_;
+ bool owned_by_arena_;
+};
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index dcbb14f..fbca72c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -206,10 +206,6 @@
(*variables)[type] = IntTypeName(options, type);
}
-bool HasInternalAccessors(const FieldOptions::CType ctype) {
- return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
-}
-
} // namespace
void SetCommonVars(const Options& options,
@@ -1349,523 +1345,6 @@
}
}
-class ParseLoopGenerator {
- public:
- ParseLoopGenerator(int num_hasbits, const Options& options,
- MessageSCCAnalyzer* scc_analyzer, io::Printer* printer)
- : scc_analyzer_(scc_analyzer),
- options_(options),
- format_(printer),
- num_hasbits_(num_hasbits) {}
-
- void GenerateParserLoop(const Descriptor* descriptor) {
- format_.Set("classname", ClassName(descriptor));
- format_.Set("p_ns", "::" + ProtobufNamespace(options_));
- format_.Set("pi_ns",
- StrCat("::", ProtobufNamespace(options_), "::internal"));
- format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_));
- std::map<std::string, std::string> vars;
- SetCommonVars(options_, &vars);
- SetUnknkownFieldsVariable(descriptor, options_, &vars);
- format_.AddMap(vars);
-
- std::vector<const FieldDescriptor*> ordered_fields;
- for (auto field : FieldRange(descriptor)) {
- if (!IsFieldStripped(field, options_)) {
- ordered_fields.push_back(field);
- }
- }
- std::sort(ordered_fields.begin(), ordered_fields.end(),
- [](const FieldDescriptor* a, const FieldDescriptor* b) {
- return a->number() < b->number();
- });
-
- format_(
- "const char* $classname$::_InternalParse(const char* ptr, "
- "$pi_ns$::ParseContext* ctx) {\n"
- "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
- format_.Indent();
- int hasbits_size = 0;
- if (num_hasbits_ > 0) {
- hasbits_size = (num_hasbits_ + 31) / 32;
- }
- // For now only optimize small hasbits.
- if (hasbits_size != 1) hasbits_size = 0;
- if (hasbits_size) {
- format_("_Internal::HasBits has_bits{};\n");
- format_.Set("has_bits", "has_bits");
- } else {
- format_.Set("has_bits", "_has_bits_");
- }
-
- GenerateParseLoop(descriptor, ordered_fields);
- format_.Outdent();
- format_("success:\n");
- if (hasbits_size) format_(" _has_bits_.Or(has_bits);\n");
-
- format_(
- " return ptr;\n"
- "failure:\n"
- " ptr = nullptr;\n"
- " goto success;\n"
- "#undef CHK_\n"
- "}\n");
- }
-
- private:
- MessageSCCAnalyzer* scc_analyzer_;
- const Options& options_;
- Formatter format_;
- int num_hasbits_;
-
- using WireFormat = internal::WireFormat;
- using WireFormatLite = internal::WireFormatLite;
-
- void GenerateArenaString(const FieldDescriptor* field) {
- if (HasHasbit(field)) {
- format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
- }
- std::string default_string =
- field->default_value_string().empty()
- ? "::" + ProtobufNamespace(options_) +
- "::internal::GetEmptyStringAlreadyInited()"
- : QualifiedClassName(field->containing_type(), options_) +
- "::" + MakeDefaultName(field) + ".get()";
- format_(
- "if (arena != nullptr) {\n"
- " ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n"
- "} else {\n"
- " ptr = "
- "$pi_ns$::InlineGreedyStringParser($1$_.MutableNoArenaNoDefault(&$2$"
- "), ptr, ctx);"
- "\n}\n"
- "const std::string* str = &$1$_.Get(); (void)str;\n",
- FieldName(field), default_string);
- }
-
- void GenerateStrings(const FieldDescriptor* field, bool check_utf8) {
- FieldOptions::CType ctype = FieldOptions::STRING;
- if (!options_.opensource_runtime) {
- // Open source doesn't support other ctypes;
- ctype = field->options().ctype();
- }
- if (!field->is_repeated() && !options_.opensource_runtime &&
- GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
- // For now only use arena string for strings with empty defaults.
- field->default_value_string().empty() &&
- !field->real_containing_oneof() && ctype == FieldOptions::STRING) {
- GenerateArenaString(field);
- } else {
- std::string name;
- switch (ctype) {
- case FieldOptions::STRING:
- name = "GreedyStringParser";
- break;
- case FieldOptions::CORD:
- name = "CordParser";
- break;
- case FieldOptions::STRING_PIECE:
- name = "StringPieceParser";
- break;
- }
- format_(
- "auto str = $1$$2$_$3$();\n"
- "ptr = $pi_ns$::Inline$4$(str, ptr, ctx);\n",
- HasInternalAccessors(ctype) ? "_internal_" : "",
- field->is_repeated() && !field->is_packable() ? "add" : "mutable",
- FieldName(field), name);
- }
- if (!check_utf8) return; // return if this is a bytes field
- auto level = GetUtf8CheckMode(field, options_);
- switch (level) {
- case Utf8CheckMode::kNone:
- return;
- case Utf8CheckMode::kVerify:
- format_("#ifndef NDEBUG\n");
- break;
- case Utf8CheckMode::kStrict:
- format_("CHK_(");
- break;
- }
- std::string field_name;
- field_name = "nullptr";
- if (HasDescriptorMethods(field->file(), options_)) {
- field_name = StrCat("\"", field->full_name(), "\"");
- }
- format_("$pi_ns$::VerifyUTF8(str, $1$)", field_name);
- switch (level) {
- case Utf8CheckMode::kNone:
- return;
- case Utf8CheckMode::kVerify:
- format_(
- ";\n"
- "#endif // !NDEBUG\n");
- break;
- case Utf8CheckMode::kStrict:
- format_(");\n");
- break;
- }
- }
-
- void GenerateLengthDelim(const FieldDescriptor* field) {
- if (field->is_packable()) {
- std::string enum_validator;
- if (field->type() == FieldDescriptor::TYPE_ENUM &&
- !HasPreservingUnknownEnumSemantics(field)) {
- enum_validator =
- StrCat(", ", QualifiedClassName(field->enum_type(), options_),
- "_IsValid, &_internal_metadata_, ", field->number());
- format_(
- "ptr = "
- "$pi_ns$::Packed$1$Parser<$unknown_fields_type$>(_internal_mutable_"
- "$2$(), ptr, "
- "ctx$3$);\n",
- DeclaredTypeMethodName(field->type()), FieldName(field),
- enum_validator);
- } else {
- format_(
- "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, "
- "ctx$3$);\n",
- DeclaredTypeMethodName(field->type()), FieldName(field),
- enum_validator);
- }
- } else {
- auto field_type = field->type();
- switch (field_type) {
- case FieldDescriptor::TYPE_STRING:
- GenerateStrings(field, true /* utf8 */);
- break;
- case FieldDescriptor::TYPE_BYTES:
- GenerateStrings(field, false /* utf8 */);
- break;
- case FieldDescriptor::TYPE_MESSAGE: {
- if (field->is_map()) {
- const FieldDescriptor* val =
- field->message_type()->FindFieldByName("value");
- GOOGLE_CHECK(val);
- if (val->type() == FieldDescriptor::TYPE_ENUM &&
- !HasPreservingUnknownEnumSemantics(field)) {
- format_(
- "auto object = "
- "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_"
- "fields_type$>("
- "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n"
- "ptr = ctx->ParseMessage(&object, ptr);\n",
- FieldName(field), QualifiedClassName(val->enum_type()),
- field->number());
- } else {
- format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
- FieldName(field));
- }
- } else if (IsLazy(field, options_)) {
- if (field->real_containing_oneof()) {
- format_(
- "if (!_internal_has_$1$()) {\n"
- " clear_$2$();\n"
- " $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
- " $pi_ns$::LazyField>(GetArena());\n"
- " set_has_$1$();\n"
- "}\n"
- "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n",
- FieldName(field), field->containing_oneof()->name());
- } else if (HasHasbit(field)) {
- format_(
- "_Internal::set_has_$1$(&$has_bits$);\n"
- "ptr = ctx->ParseMessage(&$1$_, ptr);\n",
- FieldName(field));
- } else {
- format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
- FieldName(field));
- }
- } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
- if (!field->is_repeated()) {
- format_(
- "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), "
- "ptr);\n",
- FieldName(field));
- } else {
- format_(
- "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
- "::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
- "), ptr);\n",
- FieldName(field), Namespace(field->message_type(), options_),
- ClassName(field->message_type()));
- }
- } else if (IsWeak(field, options_)) {
- format_(
- "{\n"
- " auto* default_ = &reinterpret_cast<const Message&>($1$);\n"
- " ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($2$,"
- " default_), ptr);\n"
- "}\n",
- QualifiedDefaultInstanceName(field->message_type(), options_),
- field->number());
- } else {
- format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
- field->is_repeated() ? "add" : "mutable", FieldName(field));
- }
- break;
- }
- default:
- GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
- << " filed type is " << field->type();
- }
- }
- }
-
- // Convert a 1 or 2 byte varint into the equivalent value upon a direct load.
- static uint32_t SmallVarintValue(uint32_t x) {
- GOOGLE_DCHECK(x < 128 * 128);
- if (x >= 128) x += (x & 0xFF80) + 128;
- return x;
- }
-
- static bool ShouldRepeat(const FieldDescriptor* descriptor,
- internal::WireFormatLite::WireType wiretype) {
- constexpr int kMaxTwoByteFieldNumber = 16 * 128;
- return descriptor->number() < kMaxTwoByteFieldNumber &&
- descriptor->is_repeated() &&
- (!descriptor->is_packable() ||
- wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
- }
-
- void GenerateFieldBody(internal::WireFormatLite::WireType wiretype,
- const FieldDescriptor* field) {
- uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
- switch (wiretype) {
- case WireFormatLite::WIRETYPE_VARINT: {
- std::string type = PrimitiveTypeName(options_, field->cpp_type());
- std::string prefix = field->is_repeated() ? "add" : "set";
- if (field->type() == FieldDescriptor::TYPE_ENUM) {
- format_(
- "$uint64$ val = $pi_ns$::ReadVarint64(&ptr);\n"
- "CHK_(ptr);\n");
- if (!HasPreservingUnknownEnumSemantics(field)) {
- format_("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n",
- QualifiedClassName(field->enum_type(), options_));
- format_.Indent();
- }
- format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
- FieldName(field),
- QualifiedClassName(field->enum_type(), options_));
- if (!HasPreservingUnknownEnumSemantics(field)) {
- format_.Outdent();
- format_(
- "} else {\n"
- " $pi_ns$::WriteVarint($1$, val, mutable_unknown_fields());\n"
- "}\n",
- field->number());
- }
- } else {
- std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 ||
- field->type() == FieldDescriptor::TYPE_UINT32)
- ? "32"
- : "64";
- std::string zigzag;
- if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
- field->type() == FieldDescriptor::TYPE_SINT64)) {
- zigzag = "ZigZag";
- }
- if (field->is_repeated() || field->real_containing_oneof()) {
- std::string prefix = field->is_repeated() ? "add" : "set";
- format_(
- "_internal_$1$_$2$($pi_ns$::ReadVarint$3$$4$(&ptr));\n"
- "CHK_(ptr);\n",
- prefix, FieldName(field), zigzag, size);
- } else {
- if (HasHasbit(field)) {
- format_("_Internal::set_has_$1$(&$has_bits$);\n",
- FieldName(field));
- }
- format_(
- "$1$_ = $pi_ns$::ReadVarint$2$$3$(&ptr);\n"
- "CHK_(ptr);\n",
- FieldName(field), zigzag, size);
- }
- }
- break;
- }
- case WireFormatLite::WIRETYPE_FIXED32:
- case WireFormatLite::WIRETYPE_FIXED64: {
- std::string type = PrimitiveTypeName(options_, field->cpp_type());
- if (field->is_repeated() || field->real_containing_oneof()) {
- std::string prefix = field->is_repeated() ? "add" : "set";
- format_(
- "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
- "ptr += sizeof($3$);\n",
- prefix, FieldName(field), type);
- } else {
- if (HasHasbit(field)) {
- format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
- }
- format_(
- "$1$_ = $pi_ns$::UnalignedLoad<$2$>(ptr);\n"
- "ptr += sizeof($2$);\n",
- FieldName(field), type);
- }
- break;
- }
- case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
- GenerateLengthDelim(field);
- format_("CHK_(ptr);\n");
- break;
- }
- case WireFormatLite::WIRETYPE_START_GROUP: {
- format_(
- "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
- "CHK_(ptr);\n",
- field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
- break;
- }
- case WireFormatLite::WIRETYPE_END_GROUP: {
- GOOGLE_LOG(FATAL) << "Can't have end group field\n";
- break;
- }
- } // switch (wire_type)
- }
-
- // Returns the tag for this field and in case of repeated packable fields,
- // sets a fallback tag in fallback_tag_ptr.
- static uint32_t ExpectedTag(const FieldDescriptor* field,
- uint32_t* fallback_tag_ptr) {
- uint32_t expected_tag;
- if (field->is_packable()) {
- auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
- expected_tag =
- WireFormatLite::MakeTag(field->number(), expected_wiretype);
- GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
- auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
- uint32_t fallback_tag =
- WireFormatLite::MakeTag(field->number(), fallback_wiretype);
-
- if (field->is_packed()) std::swap(expected_tag, fallback_tag);
- *fallback_tag_ptr = fallback_tag;
- } else {
- auto expected_wiretype = WireFormat::WireTypeForField(field);
- expected_tag =
- WireFormatLite::MakeTag(field->number(), expected_wiretype);
- }
- return expected_tag;
- }
-
- void GenerateParseLoop(
- const Descriptor* descriptor,
- const std::vector<const FieldDescriptor*>& ordered_fields) {
- format_(
- "while (!ctx->Done(&ptr)) {\n"
- " $uint32$ tag;\n"
- " ptr = $pi_ns$::ReadTag(ptr, &tag);\n");
- if (!ordered_fields.empty()) format_(" switch (tag >> 3) {\n");
-
- format_.Indent();
- format_.Indent();
-
- for (const auto* field : ordered_fields) {
- PrintFieldComment(format_, field);
- format_("case $1$:\n", field->number());
- format_.Indent();
- uint32_t fallback_tag = 0;
- uint32_t expected_tag = ExpectedTag(field, &fallback_tag);
- format_(
- "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
- expected_tag & 0xFF);
- format_.Indent();
- auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
- uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
- int tag_size = io::CodedOutputStream::VarintSize32(tag);
- bool is_repeat = ShouldRepeat(field, wiretype);
- if (is_repeat) {
- format_(
- "ptr -= $1$;\n"
- "do {\n"
- " ptr += $1$;\n",
- tag_size);
- format_.Indent();
- }
- GenerateFieldBody(wiretype, field);
- if (is_repeat) {
- format_.Outdent();
- format_(
- " if (!ctx->DataAvailable(ptr)) break;\n"
- "} while ($pi_ns$::ExpectTag<$1$>(ptr));\n",
- tag);
- }
- format_.Outdent();
- if (fallback_tag) {
- format_("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
- fallback_tag & 0xFF);
- format_.Indent();
- GenerateFieldBody(WireFormatLite::GetTagWireType(fallback_tag), field);
- format_.Outdent();
- }
- format_.Outdent();
- format_(
- " } else goto handle_unusual;\n"
- " continue;\n");
- } // for loop over ordered fields
-
- // Default case
- if (!ordered_fields.empty()) format_("default: {\n");
- if (!ordered_fields.empty()) format_("handle_unusual:\n");
- format_(
- " if ((tag == 0) || ((tag & 7) == 4)) {\n"
- " CHK_(ptr);\n"
- " ctx->SetLastTag(tag);\n"
- " goto success;\n"
- " }\n");
- if (IsMapEntryMessage(descriptor)) {
- format_(" continue;\n");
- } else {
- if (descriptor->extension_range_count() > 0) {
- format_("if (");
- for (int i = 0; i < descriptor->extension_range_count(); i++) {
- const Descriptor::ExtensionRange* range =
- descriptor->extension_range(i);
- if (i > 0) format_(" ||\n ");
-
- uint32_t start_tag = WireFormatLite::MakeTag(
- range->start, static_cast<WireFormatLite::WireType>(0));
- uint32_t end_tag = WireFormatLite::MakeTag(
- range->end, static_cast<WireFormatLite::WireType>(0));
-
- if (range->end > FieldDescriptor::kMaxNumber) {
- format_("($1$u <= tag)", start_tag);
- } else {
- format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
- }
- }
- format_(") {\n");
- format_(
- " ptr = _extensions_.ParseField(tag, ptr,\n"
- " internal_default_instance(), &_internal_metadata_, ctx);\n"
- " CHK_(ptr != nullptr);\n"
- " continue;\n"
- "}\n");
- }
- format_(
- " ptr = UnknownFieldParse(tag,\n"
- " _internal_metadata_.mutable_unknown_fields<$unknown_"
- "fields_type$>(),\n"
- " ptr, ctx);\n"
- " CHK_(ptr != nullptr);\n"
- " continue;\n");
- }
- if (!ordered_fields.empty()) format_("}\n"); // default case
- format_.Outdent();
- format_.Outdent();
- if (!ordered_fields.empty()) format_(" } // switch\n");
- format_("} // while\n");
- }
-};
-
-void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
- const Options& options,
- MessageSCCAnalyzer* scc_analyzer,
- io::Printer* printer) {
- ParseLoopGenerator generator(num_hasbits, options, scc_analyzer, printer);
- generator.GenerateParserLoop(descriptor);
-}
-
static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file,
const Options& options,
bool* has_opt_codesize_extension) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 8e509c1..5fa019d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -418,8 +418,8 @@
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter);
-inline bool HasFieldPresence(const FileDescriptor* file) {
- return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+inline bool IsProto3(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
inline bool HasHasbit(const FieldDescriptor* field) {
@@ -865,10 +865,6 @@
inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
-void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
- const Options& options,
- MessageSCCAnalyzer* scc_analyzer, io::Printer* printer);
-
PROTOC_EXPORT std::string StripProto(const std::string& filename);
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index c9c30e0..44c9138 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -157,7 +157,7 @@
void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_.Swap(&other->$name$_);\n");
+ format("$name$_.InternalSwap(&other->$name$_);\n");
}
void MapFieldGenerator::GenerateCopyConstructorCode(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 0a41acf..f2d1aab 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
+#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
@@ -237,7 +238,7 @@
// Does the given field have a has_$name$() method?
bool HasHasMethod(const FieldDescriptor* field) {
- if (HasFieldPresence(field->file())) {
+ if (!IsProto3(field->file())) {
// In proto1/proto2, every field has a has_$name$() method.
return true;
}
@@ -276,7 +277,7 @@
bool HasPrivateHasMethod(const FieldDescriptor* field) {
// Only for oneofs in message types with no field presence. has_$name$(),
// based on the oneof case, is still useful internally for generated code.
- return (!HasFieldPresence(field->file()) && field->real_containing_oneof());
+ return IsProto3(field->file()) && field->real_containing_oneof();
}
// TODO(ckennelly): Cull these exclusions if/when these protos do not have
@@ -2896,15 +2897,13 @@
if (HasGeneratedMethods(descriptor_->file(), options_)) {
if (descriptor_->extension_range_count() > 0) {
- format("_extensions_.Swap(&other->_extensions_);\n");
+ format("_extensions_.InternalSwap(&other->_extensions_);\n");
}
std::map<std::string, std::string> vars;
SetUnknkownFieldsVariable(descriptor_, options_, &vars);
format.AddMap(vars);
- format(
- "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_"
- "metadata_);\n");
+ format("_internal_metadata_.InternalSwap(&other->_internal_metadata_);\n");
if (!has_bit_indices_.empty()) {
for (int i = 0; i < HasBitsSize(); ++i) {
@@ -3255,8 +3254,8 @@
"}\n");
return;
}
- GenerateParserLoop(descriptor_, max_has_bit_index_, options_, scc_analyzer_,
- printer);
+ GenerateParseFunction(descriptor_, max_has_bit_index_, options_,
+ scc_analyzer_, printer);
}
void MessageGenerator::GenerateSerializeOneofFields(
@@ -3410,7 +3409,7 @@
LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer)
: mg_(mg),
format_(printer),
- eager_(!HasFieldPresence(mg->descriptor_->file())),
+ eager_(IsProto3(mg->descriptor_->file())),
cached_has_bit_index_(kNoHasbit) {}
~LazySerializerEmitter() { Flush(); }
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 7bad24c..18c6f09 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -125,7 +125,8 @@
}
format(
"$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
- "$deprecated_attr$$type$* ${1$$release_name$$}$();\n"
+ "PROTOBUF_FUTURE_MUST_USE_RESULT $deprecated_attr$$type$* "
+ "${1$$release_name$$}$();\n"
"$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$"
"($type$* $name$);\n",
@@ -320,7 +321,7 @@
format(
"::$proto_ns$::MessageLite*\n"
"$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
- if (HasFieldPresence(descriptor_->file())) {
+ if (HasHasbit(descriptor_)) {
format(" msg->$set_hasbit$\n");
}
format(
@@ -353,7 +354,7 @@
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
- if (!HasFieldPresence(descriptor_->file())) {
+ if (!HasHasbit(descriptor_)) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
format(
@@ -371,7 +372,7 @@
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
- if (!HasFieldPresence(descriptor_->file())) {
+ if (!HasHasbit(descriptor_)) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
format(
diff --git a/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
new file mode 100644
index 0000000..41be0b5
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
@@ -0,0 +1,580 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
+
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+using google::protobuf::internal::WireFormat;
+using google::protobuf::internal::WireFormatLite;
+
+std::vector<const FieldDescriptor*> GetOrderedFields(
+ const Descriptor* descriptor, const Options& options) {
+ std::vector<const FieldDescriptor*> ordered_fields;
+ for (auto field : FieldRange(descriptor)) {
+ if (!IsFieldStripped(field, options)) {
+ ordered_fields.push_back(field);
+ }
+ }
+ std::sort(ordered_fields.begin(), ordered_fields.end(),
+ [](const FieldDescriptor* a, const FieldDescriptor* b) {
+ return a->number() < b->number();
+ });
+ return ordered_fields;
+}
+
+bool HasInternalAccessors(const FieldOptions::CType ctype) {
+ return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
+}
+
+class ParseFunctionGenerator {
+ public:
+ ParseFunctionGenerator(const Descriptor* descriptor, int num_hasbits,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer, io::Printer* printer)
+ : descriptor_(descriptor),
+ scc_analyzer_(scc_analyzer),
+ options_(options),
+ format_(printer),
+ num_hasbits_(num_hasbits) {
+ format_.Set("classname", ClassName(descriptor));
+ format_.Set("p_ns", "::" + ProtobufNamespace(options_));
+ format_.Set("pi_ns",
+ StrCat("::", ProtobufNamespace(options_), "::internal"));
+ format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_));
+ std::map<std::string, std::string> vars;
+ SetCommonVars(options_, &vars);
+ SetUnknkownFieldsVariable(descriptor, options_, &vars);
+ format_.AddMap(vars);
+ }
+
+ void GenerateLoopingParseFunction() {
+ format_(
+ "const char* $classname$::_InternalParse(const char* ptr, "
+ "$pi_ns$::ParseContext* ctx) {\n"
+ "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
+ format_.Indent();
+ int hasbits_size = 0;
+ if (num_hasbits_ > 0) {
+ hasbits_size = (num_hasbits_ + 31) / 32;
+ }
+ // For now only optimize small hasbits.
+ if (hasbits_size != 1) hasbits_size = 0;
+ if (hasbits_size) {
+ format_("_Internal::HasBits has_bits{};\n");
+ format_.Set("has_bits", "has_bits");
+ } else {
+ format_.Set("has_bits", "_has_bits_");
+ }
+ format_.Set("continue", "continue");
+ format_("while (!ctx->Done(&ptr)) {\n");
+ format_.Indent();
+
+ GenerateParseIterationBody(descriptor_,
+ GetOrderedFields(descriptor_, options_));
+
+ format_.Outdent();
+ format_("} // while\n");
+
+ format_.Outdent();
+ format_("success:\n");
+ if (hasbits_size) format_(" _has_bits_.Or(has_bits);\n");
+
+ format_(
+ " return ptr;\n"
+ "failure:\n"
+ " ptr = nullptr;\n"
+ " goto success;\n"
+ "#undef CHK_\n"
+ "}\n");
+ }
+
+ private:
+ const Descriptor* descriptor_;
+ MessageSCCAnalyzer* scc_analyzer_;
+ const Options& options_;
+ Formatter format_;
+ int num_hasbits_;
+
+ void GenerateArenaString(const FieldDescriptor* field) {
+ if (HasHasbit(field)) {
+ format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+ }
+ std::string default_string =
+ field->default_value_string().empty()
+ ? "::" + ProtobufNamespace(options_) +
+ "::internal::GetEmptyStringAlreadyInited()"
+ : QualifiedClassName(field->containing_type(), options_) +
+ "::" + MakeDefaultName(field) + ".get()";
+ format_(
+ "if (arena != nullptr) {\n"
+ " ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n"
+ "} else {\n"
+ " ptr = "
+ "$pi_ns$::InlineGreedyStringParser($1$_.MutableNoArenaNoDefault(&$2$"
+ "), ptr, ctx);"
+ "\n}\n"
+ "const std::string* str = &$1$_.Get(); (void)str;\n",
+ FieldName(field), default_string);
+ }
+
+ void GenerateStrings(const FieldDescriptor* field, bool check_utf8) {
+ FieldOptions::CType ctype = FieldOptions::STRING;
+ if (!options_.opensource_runtime) {
+ // Open source doesn't support other ctypes;
+ ctype = field->options().ctype();
+ }
+ if (!field->is_repeated() && !options_.opensource_runtime &&
+ GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
+ // For now only use arena string for strings with empty defaults.
+ field->default_value_string().empty() &&
+ !field->real_containing_oneof() && ctype == FieldOptions::STRING) {
+ GenerateArenaString(field);
+ } else {
+ std::string name;
+ switch (ctype) {
+ case FieldOptions::STRING:
+ name = "GreedyStringParser";
+ break;
+ case FieldOptions::CORD:
+ name = "CordParser";
+ break;
+ case FieldOptions::STRING_PIECE:
+ name = "StringPieceParser";
+ break;
+ }
+ format_(
+ "auto str = $1$$2$_$3$();\n"
+ "ptr = $pi_ns$::Inline$4$(str, ptr, ctx);\n",
+ HasInternalAccessors(ctype) ? "_internal_" : "",
+ field->is_repeated() && !field->is_packable() ? "add" : "mutable",
+ FieldName(field), name);
+ }
+ if (!check_utf8) return; // return if this is a bytes field
+ auto level = GetUtf8CheckMode(field, options_);
+ switch (level) {
+ case Utf8CheckMode::kNone:
+ return;
+ case Utf8CheckMode::kVerify:
+ format_("#ifndef NDEBUG\n");
+ break;
+ case Utf8CheckMode::kStrict:
+ format_("CHK_(");
+ break;
+ }
+ std::string field_name;
+ field_name = "nullptr";
+ if (HasDescriptorMethods(field->file(), options_)) {
+ field_name = StrCat("\"", field->full_name(), "\"");
+ }
+ format_("$pi_ns$::VerifyUTF8(str, $1$)", field_name);
+ switch (level) {
+ case Utf8CheckMode::kNone:
+ return;
+ case Utf8CheckMode::kVerify:
+ format_(
+ ";\n"
+ "#endif // !NDEBUG\n");
+ break;
+ case Utf8CheckMode::kStrict:
+ format_(");\n");
+ break;
+ }
+ }
+
+ void GenerateLengthDelim(const FieldDescriptor* field) {
+ if (field->is_packable()) {
+ std::string enum_validator;
+ if (field->type() == FieldDescriptor::TYPE_ENUM &&
+ !HasPreservingUnknownEnumSemantics(field)) {
+ enum_validator =
+ StrCat(", ", QualifiedClassName(field->enum_type(), options_),
+ "_IsValid, &_internal_metadata_, ", field->number());
+ format_(
+ "ptr = "
+ "$pi_ns$::Packed$1$Parser<$unknown_fields_type$>(_internal_mutable_"
+ "$2$(), ptr, "
+ "ctx$3$);\n",
+ DeclaredTypeMethodName(field->type()), FieldName(field),
+ enum_validator);
+ } else {
+ format_(
+ "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, "
+ "ctx$3$);\n",
+ DeclaredTypeMethodName(field->type()), FieldName(field),
+ enum_validator);
+ }
+ } else {
+ auto field_type = field->type();
+ switch (field_type) {
+ case FieldDescriptor::TYPE_STRING:
+ GenerateStrings(field, true /* utf8 */);
+ break;
+ case FieldDescriptor::TYPE_BYTES:
+ GenerateStrings(field, false /* utf8 */);
+ break;
+ case FieldDescriptor::TYPE_MESSAGE: {
+ if (field->is_map()) {
+ const FieldDescriptor* val =
+ field->message_type()->FindFieldByName("value");
+ GOOGLE_CHECK(val);
+ if (val->type() == FieldDescriptor::TYPE_ENUM &&
+ !HasPreservingUnknownEnumSemantics(field)) {
+ format_(
+ "auto object = "
+ "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_"
+ "fields_type$>("
+ "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n"
+ "ptr = ctx->ParseMessage(&object, ptr);\n",
+ FieldName(field), QualifiedClassName(val->enum_type()),
+ field->number());
+ } else {
+ format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
+ FieldName(field));
+ }
+ } else if (IsLazy(field, options_)) {
+ if (field->real_containing_oneof()) {
+ format_(
+ "if (!_internal_has_$1$()) {\n"
+ " clear_$2$();\n"
+ " $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+ " $pi_ns$::LazyField>(GetArena());\n"
+ " set_has_$1$();\n"
+ "}\n"
+ "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n",
+ FieldName(field), field->containing_oneof()->name());
+ } else if (HasHasbit(field)) {
+ format_(
+ "_Internal::set_has_$1$(&$has_bits$);\n"
+ "ptr = ctx->ParseMessage(&$1$_, ptr);\n",
+ FieldName(field));
+ } else {
+ format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
+ FieldName(field));
+ }
+ } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
+ if (!field->is_repeated()) {
+ format_(
+ "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), "
+ "ptr);\n",
+ FieldName(field));
+ } else {
+ format_(
+ "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
+ "::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
+ "), ptr);\n",
+ FieldName(field), Namespace(field->message_type(), options_),
+ ClassName(field->message_type()));
+ }
+ } else if (IsWeak(field, options_)) {
+ format_(
+ "{\n"
+ " auto* default_ = &reinterpret_cast<const Message&>($1$);\n"
+ " ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($2$,"
+ " default_), ptr);\n"
+ "}\n",
+ QualifiedDefaultInstanceName(field->message_type(), options_),
+ field->number());
+ } else {
+ format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
+ field->is_repeated() ? "add" : "mutable", FieldName(field));
+ }
+ break;
+ }
+ default:
+ GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
+ << " filed type is " << field->type();
+ }
+ }
+ }
+
+ // Convert a 1 or 2 byte varint into the equivalent value upon a direct load.
+ static uint32_t SmallVarintValue(uint32_t x) {
+ GOOGLE_DCHECK(x < 128 * 128);
+ if (x >= 128) x += (x & 0xFF80) + 128;
+ return x;
+ }
+
+ static bool ShouldRepeat(const FieldDescriptor* descriptor,
+ internal::WireFormatLite::WireType wiretype) {
+ constexpr int kMaxTwoByteFieldNumber = 16 * 128;
+ return descriptor->number() < kMaxTwoByteFieldNumber &&
+ descriptor->is_repeated() &&
+ (!descriptor->is_packable() ||
+ wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ void GenerateFieldBody(internal::WireFormatLite::WireType wiretype,
+ const FieldDescriptor* field) {
+ uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+ switch (wiretype) {
+ case WireFormatLite::WIRETYPE_VARINT: {
+ std::string type = PrimitiveTypeName(options_, field->cpp_type());
+ std::string prefix = field->is_repeated() ? "add" : "set";
+ if (field->type() == FieldDescriptor::TYPE_ENUM) {
+ format_(
+ "$uint64$ val = $pi_ns$::ReadVarint64(&ptr);\n"
+ "CHK_(ptr);\n");
+ if (!HasPreservingUnknownEnumSemantics(field)) {
+ format_("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n",
+ QualifiedClassName(field->enum_type(), options_));
+ format_.Indent();
+ }
+ format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
+ FieldName(field),
+ QualifiedClassName(field->enum_type(), options_));
+ if (!HasPreservingUnknownEnumSemantics(field)) {
+ format_.Outdent();
+ format_(
+ "} else {\n"
+ " $pi_ns$::WriteVarint($1$, val, mutable_unknown_fields());\n"
+ "}\n",
+ field->number());
+ }
+ } else {
+ std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 ||
+ field->type() == FieldDescriptor::TYPE_UINT32)
+ ? "32"
+ : "64";
+ std::string zigzag;
+ if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
+ field->type() == FieldDescriptor::TYPE_SINT64)) {
+ zigzag = "ZigZag";
+ }
+ if (field->is_repeated() || field->real_containing_oneof()) {
+ std::string prefix = field->is_repeated() ? "add" : "set";
+ format_(
+ "_internal_$1$_$2$($pi_ns$::ReadVarint$3$$4$(&ptr));\n"
+ "CHK_(ptr);\n",
+ prefix, FieldName(field), zigzag, size);
+ } else {
+ if (HasHasbit(field)) {
+ format_("_Internal::set_has_$1$(&$has_bits$);\n",
+ FieldName(field));
+ }
+ format_(
+ "$1$_ = $pi_ns$::ReadVarint$2$$3$(&ptr);\n"
+ "CHK_(ptr);\n",
+ FieldName(field), zigzag, size);
+ }
+ }
+ break;
+ }
+ case WireFormatLite::WIRETYPE_FIXED32:
+ case WireFormatLite::WIRETYPE_FIXED64: {
+ std::string type = PrimitiveTypeName(options_, field->cpp_type());
+ if (field->is_repeated() || field->real_containing_oneof()) {
+ std::string prefix = field->is_repeated() ? "add" : "set";
+ format_(
+ "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
+ "ptr += sizeof($3$);\n",
+ prefix, FieldName(field), type);
+ } else {
+ if (HasHasbit(field)) {
+ format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+ }
+ format_(
+ "$1$_ = $pi_ns$::UnalignedLoad<$2$>(ptr);\n"
+ "ptr += sizeof($2$);\n",
+ FieldName(field), type);
+ }
+ break;
+ }
+ case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+ GenerateLengthDelim(field);
+ format_("CHK_(ptr);\n");
+ break;
+ }
+ case WireFormatLite::WIRETYPE_START_GROUP: {
+ format_(
+ "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
+ "CHK_(ptr);\n",
+ field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
+ break;
+ }
+ case WireFormatLite::WIRETYPE_END_GROUP: {
+ GOOGLE_LOG(FATAL) << "Can't have end group field\n";
+ break;
+ }
+ } // switch (wire_type)
+ }
+
+ // Returns the tag for this field and in case of repeated packable fields,
+ // sets a fallback tag in fallback_tag_ptr.
+ static uint32_t ExpectedTag(const FieldDescriptor* field,
+ uint32_t* fallback_tag_ptr) {
+ uint32_t expected_tag;
+ if (field->is_packable()) {
+ auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
+ expected_tag =
+ WireFormatLite::MakeTag(field->number(), expected_wiretype);
+ GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+ uint32_t fallback_tag =
+ WireFormatLite::MakeTag(field->number(), fallback_wiretype);
+
+ if (field->is_packed()) std::swap(expected_tag, fallback_tag);
+ *fallback_tag_ptr = fallback_tag;
+ } else {
+ auto expected_wiretype = WireFormat::WireTypeForField(field);
+ expected_tag =
+ WireFormatLite::MakeTag(field->number(), expected_wiretype);
+ }
+ return expected_tag;
+ }
+
+ void GenerateParseIterationBody(
+ const Descriptor* descriptor,
+ const std::vector<const FieldDescriptor*>& ordered_fields) {
+ format_(
+ "$uint32$ tag;\n"
+ "ptr = $pi_ns$::ReadTag(ptr, &tag);\n");
+ if (!ordered_fields.empty()) format_("switch (tag >> 3) {\n");
+
+ format_.Indent();
+
+ for (const auto* field : ordered_fields) {
+ PrintFieldComment(format_, field);
+ format_("case $1$:\n", field->number());
+ format_.Indent();
+ uint32_t fallback_tag = 0;
+ uint32_t expected_tag = ExpectedTag(field, &fallback_tag);
+ format_(
+ "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
+ expected_tag & 0xFF);
+ format_.Indent();
+ auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
+ uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+ int tag_size = io::CodedOutputStream::VarintSize32(tag);
+ bool is_repeat = ShouldRepeat(field, wiretype);
+ if (is_repeat) {
+ format_(
+ "ptr -= $1$;\n"
+ "do {\n"
+ " ptr += $1$;\n",
+ tag_size);
+ format_.Indent();
+ }
+ GenerateFieldBody(wiretype, field);
+ if (is_repeat) {
+ format_.Outdent();
+ format_(
+ " if (!ctx->DataAvailable(ptr)) break;\n"
+ "} while ($pi_ns$::ExpectTag<$1$>(ptr));\n",
+ tag);
+ }
+ format_.Outdent();
+ if (fallback_tag) {
+ format_("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
+ fallback_tag & 0xFF);
+ format_.Indent();
+ GenerateFieldBody(WireFormatLite::GetTagWireType(fallback_tag), field);
+ format_.Outdent();
+ }
+ format_.Outdent();
+ format_(
+ " } else goto handle_unusual;\n"
+ " $continue$;\n");
+ } // for loop over ordered fields
+
+ // Default case
+ if (!ordered_fields.empty()) format_("default: {\n");
+ if (!ordered_fields.empty()) format_("handle_unusual:\n");
+ format_(
+ " if ((tag == 0) || ((tag & 7) == 4)) {\n"
+ " CHK_(ptr);\n"
+ " ctx->SetLastTag(tag);\n"
+ " goto success;\n"
+ " }\n");
+ if (IsMapEntryMessage(descriptor)) {
+ format_(" $continue$;\n");
+ } else {
+ if (descriptor->extension_range_count() > 0) {
+ format_("if (");
+ for (int i = 0; i < descriptor->extension_range_count(); i++) {
+ const Descriptor::ExtensionRange* range =
+ descriptor->extension_range(i);
+ if (i > 0) format_(" ||\n ");
+
+ uint32_t start_tag = WireFormatLite::MakeTag(
+ range->start, static_cast<WireFormatLite::WireType>(0));
+ uint32_t end_tag = WireFormatLite::MakeTag(
+ range->end, static_cast<WireFormatLite::WireType>(0));
+
+ if (range->end > FieldDescriptor::kMaxNumber) {
+ format_("($1$u <= tag)", start_tag);
+ } else {
+ format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
+ }
+ }
+ format_(") {\n");
+ format_(
+ " ptr = _extensions_.ParseField(tag, ptr,\n"
+ " internal_default_instance(), &_internal_metadata_, ctx);\n"
+ " CHK_(ptr != nullptr);\n"
+ " $continue$;\n"
+ "}\n");
+ }
+ format_(
+ " ptr = UnknownFieldParse(tag,\n"
+ " _internal_metadata_.mutable_unknown_fields<$unknown_"
+ "fields_type$>(),\n"
+ " ptr, ctx);\n"
+ " CHK_(ptr != nullptr);\n"
+ " $continue$;\n");
+ }
+ if (!ordered_fields.empty()) format_("}\n"); // default case
+ format_.Outdent();
+ if (!ordered_fields.empty()) format_("} // switch\n");
+ }
+};
+
+} // namespace
+
+void GenerateParseFunction(const Descriptor* descriptor, int num_hasbits,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer,
+ io::Printer* printer) {
+ ParseFunctionGenerator generator(descriptor, num_hasbits, options,
+ scc_analyzer, printer);
+ generator.GenerateLoopingParseFunction();
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
new file mode 100644
index 0000000..5166903
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+void GenerateParseFunction(const Descriptor* descriptor, int num_hasbits,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer,
+ io::Printer* printer);
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index b1bf288..bbcc8e5 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -2215,7 +2215,6 @@
return true;
}
-
bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
const FileDescriptorProto* containing_file,
const int optionsFieldNumber,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index e0ba90f..b5a5df8 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -523,7 +523,6 @@
return syntax_identifier_ == "proto3";
}
-
bool ValidateEnum(const EnumDescriptorProto* proto);
// =================================================================
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 374a444..1fd80a1 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -516,7 +516,7 @@
void Version::InternalSwap(Version* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
suffix_.Swap(&other->suffix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -863,7 +863,7 @@
void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
file_to_generate_.InternalSwap(&other->file_to_generate_);
proto_file_.InternalSwap(&other->proto_file_);
@@ -1226,7 +1226,7 @@
void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
insertion_point_.Swap(&other->insertion_point_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -1513,7 +1513,7 @@
void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
file_.InternalSwap(&other->file_);
error_.Swap(&other->error_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 9ac275a..67eeabb 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -490,7 +490,7 @@
public:
void clear_compiler_version();
const PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const;
- PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version();
void set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
private:
@@ -698,7 +698,7 @@
public:
void clear_generated_code_info();
const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const;
- PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info();
void set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
private:
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 03c4e2b..40ded3a 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -2591,7 +2591,7 @@
enum_type(i)->DebugString(depth, contents, debug_string_options);
}
for (int i = 0; i < field_count(); i++) {
- if (field(i)->containing_oneof() == nullptr) {
+ if (field(i)->real_containing_oneof() == nullptr) {
field(i)->DebugString(depth, contents, debug_string_options);
} else if (field(i)->containing_oneof()->field(0) == field(i)) {
// This is the first field in this oneof, so print the whole oneof.
@@ -2701,7 +2701,7 @@
std::string label = StrCat(kLabelToName[this->label()], " ");
// Label is omitted for maps, oneof, and plain proto3 fields.
- if (is_map() || containing_oneof() ||
+ if (is_map() || real_containing_oneof() ||
(is_optional() && !has_optional_keyword())) {
label.clear();
}
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index c22ae43..047a401 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1418,7 +1418,7 @@
void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
file_.InternalSwap(&other->file_);
}
@@ -2056,7 +2056,7 @@
void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
dependency_.InternalSwap(&other->dependency_);
message_type_.InternalSwap(&other->message_type_);
@@ -2362,7 +2362,7 @@
void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_)
@@ -2612,7 +2612,7 @@
void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, end_)
@@ -3149,7 +3149,7 @@
void DescriptorProto::InternalSwap(DescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
field_.InternalSwap(&other->field_);
nested_type_.InternalSwap(&other->nested_type_);
@@ -3375,8 +3375,8 @@
void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
}
@@ -3987,7 +3987,7 @@
void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
extendee_.Swap(&other->extendee_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -4270,7 +4270,7 @@
void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
swap(options_, other->options_);
@@ -4516,7 +4516,7 @@
void EnumDescriptorProto_EnumReservedRange::InternalSwap(EnumDescriptorProto_EnumReservedRange* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, end_)
@@ -4893,7 +4893,7 @@
void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
value_.InternalSwap(&other->value_);
reserved_range_.InternalSwap(&other->reserved_range_);
@@ -5201,7 +5201,7 @@
void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -5510,7 +5510,7 @@
void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
method_.InternalSwap(&other->method_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -5931,7 +5931,7 @@
void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
input_type_.Swap(&other->input_type_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -6900,8 +6900,8 @@
void FileOptions::InternalSwap(FileOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
java_package_.Swap(&other->java_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -7259,8 +7259,8 @@
void MessageOptions::InternalSwap(MessageOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -7671,8 +7671,8 @@
void FieldOptions::InternalSwap(FieldOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -7895,8 +7895,8 @@
void OneofOptions::InternalSwap(OneofOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
}
@@ -8185,8 +8185,8 @@
void EnumOptions::InternalSwap(EnumOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -8444,8 +8444,8 @@
void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
swap(deprecated_, other->deprecated_);
@@ -8698,8 +8698,8 @@
void ServiceOptions::InternalSwap(ServiceOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
swap(deprecated_, other->deprecated_);
@@ -8999,8 +8999,8 @@
void MethodOptions::InternalSwap(MethodOptions* other) {
using std::swap;
- _extensions_.Swap(&other->_extensions_);
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _extensions_.InternalSwap(&other->_extensions_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -9276,7 +9276,7 @@
void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_part_.Swap(&other->name_part_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
swap(is_extension_, other->is_extension_);
@@ -9706,7 +9706,7 @@
void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
name_.InternalSwap(&other->name_);
identifier_value_.Swap(&other->identifier_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -10097,7 +10097,7 @@
void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
path_.InternalSwap(&other->path_);
span_.InternalSwap(&other->span_);
@@ -10297,7 +10297,7 @@
void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
location_.InternalSwap(&other->location_);
}
@@ -10623,7 +10623,7 @@
void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
path_.InternalSwap(&other->path_);
source_file_.Swap(&other->source_file_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -10826,7 +10826,7 @@
void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
annotation_.InternalSwap(&other->annotation_);
}
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 8f109ab..c3b7ed2 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -804,7 +804,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::FileOptions& options() const;
- PROTOBUF_NAMESPACE_ID::FileOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::FileOptions* release_options();
PROTOBUF_NAMESPACE_ID::FileOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::FileOptions* options);
private:
@@ -822,7 +822,7 @@
public:
void clear_source_code_info();
const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info() const;
- PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info();
PROTOBUF_NAMESPACE_ID::SourceCodeInfo* mutable_source_code_info();
void set_allocated_source_code_info(PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info);
private:
@@ -983,7 +983,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options() const;
- PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options();
PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options);
private:
@@ -1497,7 +1497,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::MessageOptions& options() const;
- PROTOBUF_NAMESPACE_ID::MessageOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::MessageOptions* release_options();
PROTOBUF_NAMESPACE_ID::MessageOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::MessageOptions* options);
private:
@@ -1998,7 +1998,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::FieldOptions& options() const;
- PROTOBUF_NAMESPACE_ID::FieldOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::FieldOptions* release_options();
PROTOBUF_NAMESPACE_ID::FieldOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::FieldOptions* options);
private:
@@ -2240,7 +2240,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::OneofOptions& options() const;
- PROTOBUF_NAMESPACE_ID::OneofOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::OneofOptions* release_options();
PROTOBUF_NAMESPACE_ID::OneofOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::OneofOptions* options);
private:
@@ -2631,7 +2631,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::EnumOptions& options() const;
- PROTOBUF_NAMESPACE_ID::EnumOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::EnumOptions* release_options();
PROTOBUF_NAMESPACE_ID::EnumOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumOptions* options);
private:
@@ -2803,7 +2803,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::EnumValueOptions& options() const;
- PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options();
PROTOBUF_NAMESPACE_ID::EnumValueOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumValueOptions* options);
private:
@@ -3004,7 +3004,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::ServiceOptions& options() const;
- PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options();
PROTOBUF_NAMESPACE_ID::ServiceOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::ServiceOptions* options);
private:
@@ -3213,7 +3213,7 @@
public:
void clear_options();
const PROTOBUF_NAMESPACE_ID::MethodOptions& options() const;
- PROTOBUF_NAMESPACE_ID::MethodOptions* release_options();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::MethodOptions* release_options();
PROTOBUF_NAMESPACE_ID::MethodOptions* mutable_options();
void set_allocated_options(PROTOBUF_NAMESPACE_ID::MethodOptions* options);
private:
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 01cd8d7..5330763 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -285,7 +285,7 @@
void Duration::InternalSwap(Duration* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(Duration, nanos_)
+ sizeof(Duration::nanos_)
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index b2149ab..2adc793 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -219,7 +219,7 @@
void Empty::InternalSwap(Empty* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
}
::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const {
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index bc53480..aa57e67 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -1055,10 +1055,7 @@
void ExtensionSet::Swap(ExtensionSet* x) {
if (GetArena() == x->GetArena()) {
- using std::swap;
- swap(flat_capacity_, x->flat_capacity_);
- swap(flat_size_, x->flat_size_);
- swap(map_, x->map_);
+ InternalSwap(x);
} else {
// TODO(cfallin, rohananil): We maybe able to optimize a case where we are
// swapping from heap to arena-allocated extension set, by just Own()'ing
@@ -1072,6 +1069,13 @@
}
}
+void ExtensionSet::InternalSwap(ExtensionSet* other) {
+ using std::swap;
+ swap(flat_capacity_, other->flat_capacity_);
+ swap(flat_size_, other->flat_size_);
+ swap(map_, other->map_);
+}
+
void ExtensionSet::SwapExtension(ExtensionSet* other, int number) {
if (this == other) return;
Extension* this_ext = FindOrNull(number);
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index c4b845a..55492a6 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -369,6 +369,7 @@
void Clear();
void MergeFrom(const ExtensionSet& other);
void Swap(ExtensionSet* other);
+ void InternalSwap(ExtensionSet* other);
void SwapExtension(ExtensionSet* other, int number);
bool IsInitialized() const;
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 6a6fc25..7971fe5 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -198,7 +198,8 @@
// ReleaseExtension will return the underlying object even after
// ClearExtension is called.
message.SetAllocatedExtension(
- unittest::TestMessageSetExtension1::message_set_extension, extension);
+ unittest::TestMessageSetExtension1::message_set_extension,
+ released_extension);
message.ClearExtension(
unittest::TestMessageSetExtension1::message_set_extension);
released_extension = message.ReleaseExtension(
@@ -1335,5 +1336,3 @@
} // namespace internal
} // namespace protobuf
} // namespace google
-
-#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 5890bb2..f83f62d 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -263,7 +263,7 @@
void FieldMask::InternalSwap(FieldMask* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
paths_.InternalSwap(&other->paths_);
}
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index 7234f5f..8b14662 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -55,6 +55,9 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
namespace google {
namespace protobuf {
@@ -358,6 +361,7 @@
ASSERT_EQ(2, message.repeated_foreign_message_size());
const protobuf_unittest::ForeignMessage* expected =
message.mutable_repeated_foreign_message(1);
+ (void)expected; // unused in somce configurations
std::unique_ptr<Message> released(message.GetReflection()->ReleaseLast(
&message, descriptor->FindFieldByName("repeated_foreign_message")));
EXPECT_EQ(expected, released.get());
@@ -781,6 +785,7 @@
&to_message);
const Message& sub_message = reflection->GetMessage(
to_message, descriptor->FindFieldByName("foo_lazy_message"));
+ (void)sub_message; // unused in somce configurations
released = reflection->ReleaseMessage(
&to_message, descriptor->FindFieldByName("foo_lazy_message"));
EXPECT_TRUE(released != NULL);
@@ -798,6 +803,7 @@
const Message& sub_message2 = reflection->GetMessage(
to_message, descriptor->FindFieldByName("foo_message"));
+ (void)sub_message2; // unused in somce configurations
released = reflection->ReleaseMessage(
&to_message, descriptor->FindFieldByName("foo_message"));
EXPECT_TRUE(released != NULL);
@@ -917,6 +923,7 @@
const Reflection* reflection = message.GetReflection();
const Message& sub_message = reflection->GetMessage(
message, descriptor->FindFieldByName("foo_lazy_message"));
+ (void)sub_message; // unused in somce configurations
Message* released = reflection->ReleaseMessage(
&message, descriptor->FindFieldByName("foo_lazy_message"));
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 7efee12..df84e1e 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -1321,7 +1321,7 @@
void swap(Map& other) {
if (arena() == other.arena()) {
- elements_.Swap(&other.elements_);
+ InternalSwap(other);
} else {
// TODO(zuguang): optimize this. The temporary copy can be allocated
// in the same arena as the other message, and the "other = copy" can
@@ -1332,6 +1332,8 @@
}
}
+ void InternalSwap(Map& other) { elements_.Swap(&other.elements_); }
+
// Access to hasher. Currently this returns a copy, but it may
// be modified to return a const reference in the future.
hasher hash_function() const { return elements_.hash_function(); }
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index 542a1f8..23f36d0 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -56,6 +56,20 @@
return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
}
+void MapFieldBase::Swap(MapFieldBase* other) {
+ // TODO(teboring): This is incorrect when on different arenas.
+ InternalSwap(other);
+}
+
+void MapFieldBase::InternalSwap(MapFieldBase* other) {
+ std::swap(repeated_field_, other->repeated_field_);
+ // a relaxed swap of the atomic
+ auto other_state = other->state_.load(std::memory_order_relaxed);
+ auto this_state = state_.load(std::memory_order_relaxed);
+ other->state_.store(this_state, std::memory_order_relaxed);
+ state_.store(other_state, std::memory_order_relaxed);
+}
+
size_t MapFieldBase::SpaceUsedExcludingSelfLong() const {
ConstAccess();
mutex_.Lock();
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index e05d3ee..452c463 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -371,7 +371,7 @@
virtual void MapBegin(MapIterator* map_iter) const = 0;
virtual void MapEnd(MapIterator* map_iter) const = 0;
virtual void MergeFrom(const MapFieldBase& other) = 0;
- virtual void Swap(MapFieldBase* other) = 0;
+ virtual void Swap(MapFieldBase* other);
// Sync Map with repeated field and returns the size of map.
virtual int size() const = 0;
virtual void Clear() = 0;
@@ -407,6 +407,8 @@
// Provides derived class the access to repeated field.
void* MutableRepeatedPtrField() const;
+ void InternalSwap(MapFieldBase* other);
+
// Support thread sanitizer (tsan) by making const / mutable races
// more apparent. If one thread calls MutableAccess() while another
// thread calls either ConstAccess() or MutableAccess(), on the same
@@ -571,6 +573,7 @@
void Clear() override;
void MergeFrom(const MapFieldBase& other) override;
void Swap(MapFieldBase* other) override;
+ void InternalSwap(MapField* other);
// Used in the implementation of parsing. Caller should take the ownership iff
// arena_ is NULL.
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 8e92170..5564895 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -277,14 +277,18 @@
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
MapFieldBase* other) {
+ MapFieldBase::Swap(other);
MapField* other_field = down_cast<MapField*>(other);
- std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_);
impl_.Swap(&other_field->impl_);
- // a relaxed swap of the atomic
- auto other_state = other_field->state_.load(std::memory_order_relaxed);
- auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed);
- other_field->state_.store(this_state, std::memory_order_relaxed);
- this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed);
+}
+
+template <typename Derived, typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap(
+ MapField* other) {
+ MapFieldBase::InternalSwap(other);
+ impl_.InternalSwap(&other->impl_);
}
template <typename Derived, typename Key, typename T,
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
index 665cb0e..46658d4 100644
--- a/src/google/protobuf/map_field_lite.h
+++ b/src/google/protobuf/map_field_lite.h
@@ -81,6 +81,7 @@
}
}
void Swap(MapFieldLite* other) { map_.swap(other->map_); }
+ void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); }
// Used in the implementation of parsing. Caller should take the ownership iff
// arena_ is NULL.
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index dd70e98..e581f20 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -102,14 +102,17 @@
void IncreaseIterator(MapIterator* map_iter) const override {}
};
-class MapFieldBasePrimitiveTest : public ::testing::Test {
+class MapFieldBasePrimitiveTest : public testing::TestWithParam<bool> {
protected:
typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
WireFormatLite::TYPE_INT32>
MapFieldType;
- MapFieldBasePrimitiveTest() {
+ MapFieldBasePrimitiveTest()
+ : arena_(GetParam() ? new Arena() : nullptr),
+ map_field_(arena_.get()),
+ map_field_base_(map_field_.get()) {
// Get descriptors
map_descriptor_ = unittest::TestMap::descriptor()
->FindFieldByName("map_int32_int32")
@@ -118,7 +121,6 @@
value_descriptor_ = map_descriptor_->map_value();
// Build map field
- map_field_.reset(new MapFieldType);
map_field_base_ = map_field_.get();
map_ = map_field_->MutableMap();
initial_value_map_[0] = 100;
@@ -127,7 +129,8 @@
EXPECT_EQ(2, map_->size());
}
- std::unique_ptr<MapFieldType> map_field_;
+ std::unique_ptr<Arena> arena_;
+ ArenaHolder<MapFieldType> map_field_;
MapFieldBase* map_field_base_;
Map<int32, int32>* map_;
const Descriptor* map_descriptor_;
@@ -136,11 +139,15 @@
std::map<int32, int32> initial_value_map_; // copy of initial values inserted
};
-TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
+INSTANTIATE_TEST_SUITE_P(MapFieldBasePrimitiveTestInstance,
+ MapFieldBasePrimitiveTest,
+ testing::Values(true, false));
+
+TEST_P(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
}
-TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
+TEST_P(MapFieldBasePrimitiveTest, GetRepeatedField) {
const RepeatedPtrField<Message>& repeated =
reinterpret_cast<const RepeatedPtrField<Message>&>(
map_field_base_->GetRepeatedField());
@@ -153,7 +160,7 @@
}
}
-TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
+TEST_P(MapFieldBasePrimitiveTest, MutableRepeatedField) {
RepeatedPtrField<Message>* repeated =
reinterpret_cast<RepeatedPtrField<Message>*>(
map_field_base_->MutableRepeatedField());
@@ -166,7 +173,7 @@
}
}
-TEST_F(MapFieldBasePrimitiveTest, Arena) {
+TEST_P(MapFieldBasePrimitiveTest, Arena) {
// Allocate a large initial block to avoid mallocs during hooked test.
std::vector<char> arena_block(128 * 1024);
ArenaOptions options;
@@ -205,18 +212,19 @@
enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
} // anonymous namespace
-class MapFieldStateTest : public testing::TestWithParam<State> {
- public:
+class MapFieldStateTest
+ : public testing::TestWithParam<std::tuple<State, bool>> {
protected:
typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
WireFormatLite::TYPE_INT32>
MapFieldType;
- MapFieldStateTest() : state_(GetParam()) {
+ MapFieldStateTest()
+ : arena_(std::get<1>(GetParam()) ? new Arena() : nullptr),
+ map_field_(arena_.get()),
+ map_field_base_(map_field_.get()),
+ state_(std::get<0>(GetParam())) {
// Build map field
- map_field_.reset(new MapFieldType());
- map_field_base_ = map_field_.get();
-
Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
switch (state_) {
case CLEAN:
@@ -297,13 +305,16 @@
}
}
- std::unique_ptr<MapFieldType> map_field_;
+ std::unique_ptr<Arena> arena_;
+ ArenaHolder<MapFieldType> map_field_;
MapFieldBase* map_field_base_;
State state_;
};
INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
- ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
+ testing::Combine(testing::Values(CLEAN, MAP_DIRTY,
+ REPEATED_DIRTY),
+ testing::Values(true, false)));
TEST_P(MapFieldStateTest, GetMap) {
map_field_->GetMap();
@@ -324,10 +335,10 @@
}
TEST_P(MapFieldStateTest, MergeFromClean) {
- MapFieldType other;
- AddOneStillClean(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ AddOneStillClean(other.get());
- map_field_->MergeFrom(other);
+ map_field_->MergeFrom(*other);
if (state_ != MAP_DIRTY) {
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -335,14 +346,14 @@
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
}
- Expect(&other, CLEAN, 1, 1, false);
+ Expect(other.get(), CLEAN, 1, 1, false);
}
TEST_P(MapFieldStateTest, MergeFromMapDirty) {
- MapFieldType other;
- MakeMapDirty(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ MakeMapDirty(other.get());
- map_field_->MergeFrom(other);
+ map_field_->MergeFrom(*other);
if (state_ != MAP_DIRTY) {
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -350,14 +361,14 @@
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
}
- Expect(&other, MAP_DIRTY, 1, 0, true);
+ Expect(other.get(), MAP_DIRTY, 1, 0, true);
}
TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
- MapFieldType other;
- MakeRepeatedDirty(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ MakeRepeatedDirty(other.get());
- map_field_->MergeFrom(other);
+ map_field_->MergeFrom(*other);
if (state_ != MAP_DIRTY) {
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -365,26 +376,26 @@
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
}
- Expect(&other, CLEAN, 1, 1, false);
+ Expect(other.get(), CLEAN, 1, 1, false);
}
TEST_P(MapFieldStateTest, SwapClean) {
- MapFieldType other;
- AddOneStillClean(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ AddOneStillClean(other.get());
- map_field_->Swap(&other);
+ map_field_->Swap(other.get());
Expect(map_field_.get(), CLEAN, 1, 1, false);
switch (state_) {
case CLEAN:
- Expect(&other, CLEAN, 1, 1, false);
+ Expect(other.get(), CLEAN, 1, 1, false);
break;
case MAP_DIRTY:
- Expect(&other, MAP_DIRTY, 1, 0, true);
+ Expect(other.get(), MAP_DIRTY, 1, 0, true);
break;
case REPEATED_DIRTY:
- Expect(&other, REPEATED_DIRTY, 0, 1, false);
+ Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
break;
default:
break;
@@ -392,22 +403,22 @@
}
TEST_P(MapFieldStateTest, SwapMapDirty) {
- MapFieldType other;
- MakeMapDirty(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ MakeMapDirty(other.get());
- map_field_->Swap(&other);
+ map_field_->Swap(other.get());
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
switch (state_) {
case CLEAN:
- Expect(&other, CLEAN, 1, 1, false);
+ Expect(other.get(), CLEAN, 1, 1, false);
break;
case MAP_DIRTY:
- Expect(&other, MAP_DIRTY, 1, 0, true);
+ Expect(other.get(), MAP_DIRTY, 1, 0, true);
break;
case REPEATED_DIRTY:
- Expect(&other, REPEATED_DIRTY, 0, 1, false);
+ Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
break;
default:
break;
@@ -415,22 +426,22 @@
}
TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
- MapFieldType other;
- MakeRepeatedDirty(&other);
+ ArenaHolder<MapFieldType> other(arena_.get());
+ MakeRepeatedDirty(other.get());
- map_field_->Swap(&other);
+ map_field_->Swap(other.get());
Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
switch (state_) {
case CLEAN:
- Expect(&other, CLEAN, 1, 1, false);
+ Expect(other.get(), CLEAN, 1, 1, false);
break;
case MAP_DIRTY:
- Expect(&other, MAP_DIRTY, 1, 0, true);
+ Expect(other.get(), MAP_DIRTY, 1, 0, true);
break;
case REPEATED_DIRTY:
- Expect(&other, REPEATED_DIRTY, 0, 1, false);
+ Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
break;
default:
break;
@@ -501,5 +512,3 @@
} // namespace internal
} // namespace protobuf
} // namespace google
-
-#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 768858f..335756e 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -1471,19 +1471,19 @@
std::unique_ptr<Message> entry_int32_int32(
MessageFactory::generated_factory()
->GetPrototype(fd_map_int32_int32->message_type())
- ->New());
+ ->New(message.GetArena()));
std::unique_ptr<Message> entry_int32_double(
MessageFactory::generated_factory()
->GetPrototype(fd_map_int32_double->message_type())
- ->New());
+ ->New(message.GetArena()));
std::unique_ptr<Message> entry_string_string(
MessageFactory::generated_factory()
->GetPrototype(fd_map_string_string->message_type())
- ->New());
+ ->New(message.GetArena()));
std::unique_ptr<Message> entry_int32_foreign_message(
MessageFactory::generated_factory()
->GetPrototype(fd_map_int32_foreign_message->message_type())
- ->New());
+ ->New(message.GetArena()));
EXPECT_EQ(10, mf_int32_int32.size());
EXPECT_EQ(10, mmf_int32_int32.size());
@@ -1890,6 +1890,15 @@
EXPECT_EQ(int32_value9a, int32_value0b);
EXPECT_EQ(int32_value0a, int32_value9b);
}
+
+ // TODO(b/181148674): After supporting arena agnostic delete or let map entry
+ // handle heap allocation, this could be removed.
+ if (message.GetArena() != nullptr) {
+ entry_int32_int32.release();
+ entry_int32_double.release();
+ entry_string_string.release();
+ entry_int32_foreign_message.release();
+ }
}
TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
@@ -3771,5 +3780,3 @@
} // namespace internal
} // namespace protobuf
} // namespace google
-
-#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 52e6a1d..c9db4e8 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -476,7 +476,8 @@
void RemoveLast(Message* message, const FieldDescriptor* field) const;
// Removes the last element of a repeated message field, and returns the
// pointer to the caller. Caller takes ownership of the returned pointer.
- Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
+ PROTOBUF_FUTURE_MUST_USE_RESULT Message* ReleaseLast(
+ Message* message, const FieldDescriptor* field) const;
// Swap the complete contents of two messages.
void Swap(Message* message1, Message* message2) const;
@@ -604,8 +605,9 @@
// If the field existed (HasField() is true), then the returned pointer will
// be the same as the pointer returned by MutableMessage().
// This function has the same effect as ClearField().
- Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
- MessageFactory* factory = nullptr) const;
+ PROTOBUF_FUTURE_MUST_USE_RESULT Message* ReleaseMessage(
+ Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = nullptr) const;
// Repeated field getters ------------------------------------------
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 8a9b79d..68cfa03 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -83,7 +83,6 @@
// See parse_context.h for explanation
class ParseContext;
-class Proto3ArenaTestHelper;
class RepeatedPtrFieldBase;
class WireFormatLite;
class WeakFieldMap;
@@ -210,11 +209,11 @@
// if arena is a NULL. Default implementation for backwards compatibility.
virtual MessageLite* New(Arena* arena) const;
- // Get the arena for allocating submessages, if any, associated with this
- // message. Virtual method required for generic operations but most
- // arena-related operations should use the GetArena() generated-code method.
- // Default implementation to reduce code size by avoiding the need for
- // per-type implementations when types do not implement arena support.
+ // Get the arena, if any, associated with this message. Virtual method
+ // required for generic operations but most arena-related operations should
+ // use the GetArena() generated-code method. Default implementation
+ // to reduce code size by avoiding the need for per-type implementations
+ // when types do not implement arena support.
Arena* GetArena() const { return _internal_metadata_.arena(); }
// Get a pointer that may be equal to this message's arena, or may not be.
@@ -503,18 +502,8 @@
// TODO(gerbens) make this a pure abstract function
virtual const void* InternalGetTable() const { return NULL; }
- // Get the arena that owns this message.
- Arena* GetOwningArena() const { return _internal_metadata_.GetOwningArena(); }
-
- // Set the owning arena to the given one.
- void SetOwningArena(Arena* arena) {
- _internal_metadata_.SetOwningArena(arena);
- }
-
- friend class Arena;
friend class internal::WireFormatLite;
friend class Message;
- friend class internal::Proto3ArenaTestHelper;
friend class internal::WeakFieldMap;
void LogInitializationErrorMessage() const;
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index 0d97d40..78a1297 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -374,6 +374,17 @@
EXPECT_EQ("c", errors[2]);
}
+TEST(MESSAGE_TEST_NAME, ReleaseMustUseResult) {
+ UNITTEST::TestAllTypes message;
+ auto* f = new UNITTEST::ForeignMessage();
+ f->set_c(1000);
+ message.set_allocated_optional_foreign_message(f);
+ auto* mf = message.mutable_optional_foreign_message();
+ EXPECT_EQ(mf, f);
+ EXPECT_NE(message.release_optional_foreign_message(), nullptr);
+ delete f;
+}
+
TEST(MESSAGE_TEST_NAME, ParseFailsOnInvalidMessageEnd) {
UNITTEST::TestAllTypes message;
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index 1f8d8fc..ad5710c 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -73,17 +73,15 @@
}
PROTOBUF_NDEBUG_INLINE Arena* arena() const {
- if (PROTOBUF_PREDICT_TRUE(!has_tag())) {
- return PtrValue<Arena>();
- } else if (is_heap_allocating()) {
- return nullptr;
- } else {
+ if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
return PtrValue<ContainerBase>()->arena;
+ } else {
+ return PtrValue<Arena>();
}
}
PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
- return UnknownTag() == kUnknownTagMask;
+ return PtrTag() == kTagContainer;
}
PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const { return ptr_; }
@@ -120,6 +118,10 @@
}
}
+ PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) {
+ std::swap(ptr_, other->ptr_);
+ }
+
template <typename T>
PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
if (other.have_unknown_fields()) {
@@ -134,56 +136,23 @@
}
}
- PROTOBUF_ALWAYS_INLINE Arena* GetOwningArena() const {
- if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
- return PtrValue<ContainerBase>()->arena;
- } else {
- return PtrValue<Arena>();
- }
- }
-
- PROTOBUF_ALWAYS_INLINE void SetOwningArena(Arena* arena) {
- Arena* owning_arena = GetOwningArena();
- GOOGLE_DCHECK(arena != nullptr); // Heap can't own.
- GOOGLE_DCHECK(owning_arena == nullptr); // Only heap can be owned.
-
- if (have_unknown_fields()) {
- ContainerBase* container = PtrValue<ContainerBase>();
- container->arena = arena;
- ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr_) |
- kHeapAllocatingTagMask);
- } else {
- ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(arena) |
- kHeapAllocatingTagMask);
- }
- }
-
private:
void* ptr_;
// Tagged pointer implementation.
- static constexpr intptr_t kUnknownTagMask = 1;
- static constexpr intptr_t kHeapAllocatingTagMask = 2;
- static constexpr intptr_t kPtrTagMask =
- kUnknownTagMask | kHeapAllocatingTagMask;
+ enum {
+ // ptr_ is an Arena*.
+ kTagArena = 0,
+ // ptr_ is a Container*.
+ kTagContainer = 1,
+ };
+ static constexpr intptr_t kPtrTagMask = 1;
static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
// Accessors for pointer tag and pointer value.
PROTOBUF_NDEBUG_INLINE int PtrTag() const {
return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
}
- PROTOBUF_ALWAYS_INLINE int UnknownTag() const {
- return reinterpret_cast<intptr_t>(ptr_) & kUnknownTagMask;
- }
- PROTOBUF_ALWAYS_INLINE int HeapAllocatingTag() const {
- return reinterpret_cast<intptr_t>(ptr_) & kHeapAllocatingTagMask;
- }
- PROTOBUF_ALWAYS_INLINE bool has_tag() const {
- return (reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask) != 0;
- }
- PROTOBUF_ALWAYS_INLINE bool is_heap_allocating() const {
- return HeapAllocatingTag() == kHeapAllocatingTagMask;
- }
template <typename U>
U* PtrValue() const {
@@ -191,8 +160,7 @@
kPtrValueMask);
}
- // If ptr_'s tag is kUnknownTagMask, it points to an instance of this
- // struct.
+ // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
struct ContainerBase {
Arena* arena;
};
@@ -212,16 +180,13 @@
template <typename T>
PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
Arena* my_arena = arena();
- Arena* owning_arena = GetOwningArena();
Container<T>* container = Arena::Create<Container<T>>(my_arena);
// Two-step assignment works around a bug in clang's static analyzer:
// https://bugs.llvm.org/show_bug.cgi?id=34198.
- intptr_t allocating_tag =
- reinterpret_cast<intptr_t>(ptr_) & kHeapAllocatingTagMask;
ptr_ = container;
ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr_) |
- kUnknownTagMask | allocating_tag);
- container->arena = owning_arena;
+ kTagContainer);
+ container->arena = my_arena;
return &(container->unknown_fields);
}
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 4c29134..8a64749 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -48,10 +48,10 @@
// detect/prohibit anytime it is #included twice without a corresponding
// #undef.
-// These macros are private and should always be
-// ::util::RetrieveErrorSpace(*this) headers. If any of these errors fire, you
-// should either properly #include port_undef.h at the end of your header that
-// #includes port.h, or don't #include port.h twice in a .cc file.
+// These macros are private and should always be #undef'd from headers.
+// If any of these errors fire, you should either properly #include
+// port_undef.h at the end of your header that #includes port.h, or
+// don't #include port.h twice in a .cc file.
#ifdef PROTOBUF_NAMESPACE
#error PROTOBUF_NAMESPACE was previously defined
#endif
@@ -160,6 +160,15 @@
#ifdef PROTOBUF_ATTRIBUTE_WEAK
#error PROTOBUF_ATTRIBUTE_WEAK was previously defined
#endif
+#ifdef PROTOBUF_ASAN
+#error PROTOBUF_ASAN was previously defined
+#endif
+#ifdef PROTOBUF_MSAN
+#error PROTOBUF_MSAN was previously defined
+#endif
+#ifdef PROTOBUF_TSAN
+#error PROTOBUF_TSAN was previously defined
+#endif
#define PROTOBUF_NAMESPACE "google::protobuf"
@@ -191,6 +200,7 @@
#define PROTOBUF_SECTION_VARIABLE(x)
#define PROTOBUF_MUST_USE_RESULT
+#define PROTOBUF_FUTURE_MUST_USE_RESULT
// ----------------------------------------------------------------------------
// Annotations: Some parts of the code have been annotated in ways that might
@@ -335,8 +345,6 @@
#endif
-// Shared google3/opensource definitions. //////////////////////////////////////
-
#define PROTOBUF_VERSION 3015008
#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3015000
#define PROTOBUF_MIN_PROTOC_VERSION 3015000
@@ -372,7 +380,7 @@
#if defined(__clang__)
// For Clang we use __builtin_offsetof() and suppress the warning,
// to avoid Control Flow Integrity and UBSan vptr sanitizers from
-// crashing while trying to validate the invalid reinterpet_casts.
+// crashing while trying to validate the invalid reinterpret_casts.
#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
@@ -444,6 +452,8 @@
#undef ERROR
#pragma push_macro("ERROR_BUSY")
#undef ERROR_BUSY
+#pragma push_macro("ERROR_INSTALL_FAILED")
+#undef ERROR_INSTALL_FAILED
#pragma push_macro("ERROR_NOT_FOUND")
#undef ERROR_NOT_FOUND
#pragma push_macro("GetMessage")
@@ -619,6 +629,22 @@
#define PROTOBUF_ATTRIBUTE_WEAK
#endif
+// Macros to detect sanitizers.
+#if defined(__clang__)
+# if __has_feature(address_sanitizer)
+# define PROTOBUF_ASAN 1
+# endif
+# if __has_feature(thread_sanitizer)
+# define PROTOBUF_TSAN 1
+# endif
+# if __has_feature(memory_sanitizer)
+# define PROTOBUF_MSAN 1
+# endif
+#elif defined(__GNUC__)
+# define PROTOBUF_ASAN __SANITIZE_ADDRESS__
+# define PROTOBUF_TSAN __SANITIZE_THREAD__
+#endif
+
// Silence some MSVC warnings in all our code.
#if _MSC_VER
#pragma warning(push)
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index 80bfd30..e40ac0d 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -78,6 +78,9 @@
#undef PROTOBUF_ATTRIBUTE_NO_DESTROY
#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
#undef PROTOBUF_PRAGMA_INIT_SEG
+#undef PROTOBUF_ASAN
+#undef PROTOBUF_MSAN
+#undef PROTOBUF_TSAN
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
#undef PROTOBUF_FUTURE_BREAKING_CHANGES
@@ -90,6 +93,7 @@
#pragma pop_macro("DOUBLE_CLICK")
#pragma pop_macro("ERROR")
#pragma pop_macro("ERROR_BUSY")
+#pragma pop_macro("ERROR_INSTALL_FAILED")
#pragma pop_macro("ERROR_NOT_FOUND")
#pragma pop_macro("GetMessage")
#pragma pop_macro("IGNORE")
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index 83be3d8..5588f91 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -42,6 +42,9 @@
#include <gtest/gtest.h>
#include <google/protobuf/stubs/strutil.h>
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
using proto3_arena_unittest::ForeignMessage;
using proto3_arena_unittest::TestAllTypes;
@@ -166,8 +169,6 @@
auto* arena_repeated_submessage1 =
arena_message1->add_repeated_foreign_message();
EXPECT_EQ(&arena, arena_message1->GetArena());
- EXPECT_EQ(&arena,
- internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1));
EXPECT_EQ(&arena, arena_submessage1->GetArena());
EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
@@ -180,17 +181,11 @@
const auto& repeated_submessage2 =
arena_message2->repeated_foreign_message(0);
EXPECT_EQ(nullptr, submessage2.GetArena());
- EXPECT_EQ(&arena,
- internal::Proto3ArenaTestHelper::GetOwningArena(submessage2));
EXPECT_EQ(nullptr, repeated_submessage2.GetArena());
- EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena(
- repeated_submessage2));
// Tests message created by Arena::Create.
auto* arena_message3 = Arena::Create<TestAllTypes>(&arena);
EXPECT_EQ(nullptr, arena_message3->GetArena());
- EXPECT_EQ(&arena,
- internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message3));
}
TEST(Proto3ArenaTest, GetArenaWithUnknown) {
@@ -206,8 +201,6 @@
arena_repeated_submessage1->GetReflection()->MutableUnknownFields(
arena_repeated_submessage1);
EXPECT_EQ(&arena, arena_message1->GetArena());
- EXPECT_EQ(&arena,
- internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1));
EXPECT_EQ(&arena, arena_submessage1->GetArena());
EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
@@ -223,11 +216,7 @@
repeated_submessage2->GetReflection()->MutableUnknownFields(
repeated_submessage2);
EXPECT_EQ(nullptr, submessage2->GetArena());
- EXPECT_EQ(&arena,
- internal::Proto3ArenaTestHelper::GetOwningArena(*submessage2));
EXPECT_EQ(nullptr, repeated_submessage2->GetArena());
- EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena(
- *repeated_submessage2));
}
TEST(Proto3ArenaTest, Swap) {
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 58190e3..ebccf18 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -688,7 +688,7 @@
void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
template <typename TypeHandler>
- typename TypeHandler::Type* ReleaseLast() {
+ PROTOBUF_FUTURE_MUST_USE_RESULT typename TypeHandler::Type* ReleaseLast() {
typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
return ReleaseLastInternal<TypeHandler>(t);
}
@@ -702,7 +702,7 @@
template <typename TypeHandler>
void AddCleared(typename TypeHandler::Type* value);
template <typename TypeHandler>
- typename TypeHandler::Type* ReleaseCleared();
+ PROTOBUF_FUTURE_MUST_USE_RESULT typename TypeHandler::Type* ReleaseCleared();
template <typename TypeHandler>
void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type);
@@ -1084,7 +1084,7 @@
// If this RepeatedPtrField is on an arena, an object copy is required to pass
// ownership back to the user (for compatible semantics). Use
// UnsafeArenaReleaseLast() if this behavior is undesired.
- Element* ReleaseLast();
+ PROTOBUF_FUTURE_MUST_USE_RESULT Element* ReleaseLast();
// Add an already-allocated object, skipping arena-ownership checks. The user
// must guarantee that the given object is in the same arena as this
@@ -1154,7 +1154,7 @@
//
// This method cannot be called when the repeated field is on an arena; doing
// so will trigger a GOOGLE_DCHECK-failure.
- Element* ReleaseCleared();
+ PROTOBUF_FUTURE_MUST_USE_RESULT Element* ReleaseCleared();
// Removes the element referenced by position.
//
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index f3e8c2d..b270885 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -333,7 +333,7 @@
EXPECT_GE(huge_field.Capacity(), min_clamping_size);
ASSERT_LT(huge_field.Capacity(), std::numeric_limits<int>::max() - 1);
-#ifndef ADDRESS_SANITIZER
+#ifndef PROTOBUF_ASAN
// The array containing all the fields is, in theory, up to MAXINT-1 in size.
// However, some compilers can't handle a struct whose size is larger
// than 2GB, and the protocol buffer format doesn't handle more than 2GB of
@@ -344,7 +344,7 @@
// size must still be clamped to a valid range.
huge_field.Reserve(huge_field.Capacity() + 1);
EXPECT_EQ(huge_field.Capacity(), std::numeric_limits<int>::max());
-#endif
+#endif // PROTOBUF_ASAN
#endif // PROTOBUF_TEST_ALLOW_LARGE_ALLOC
}
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 3994ceb..4dae936 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -264,7 +264,7 @@
void SourceContext::InternalSwap(SourceContext* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
}
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index fbe98e7..1b2fbc7 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -403,8 +403,8 @@
void Struct::InternalSwap(Struct* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
- fields_.Swap(&other->fields_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ fields_.InternalSwap(&other->fields_);
}
::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const {
@@ -842,7 +842,7 @@
void Value::InternalSwap(Value* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(kind_, other->kind_);
swap(_oneof_case_[0], other->_oneof_case_[0]);
}
@@ -1038,7 +1038,7 @@
void ListValue::InternalSwap(ListValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
values_.InternalSwap(&other->values_);
}
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 56df12e..a6f5e78 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -462,7 +462,7 @@
public:
void clear_struct_value();
const PROTOBUF_NAMESPACE_ID::Struct& struct_value() const;
- PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
PROTOBUF_NAMESPACE_ID::Struct* mutable_struct_value();
void set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value);
private:
@@ -480,7 +480,7 @@
public:
void clear_list_value();
const PROTOBUF_NAMESPACE_ID::ListValue& list_value() const;
- PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
PROTOBUF_NAMESPACE_ID::ListValue* mutable_list_value();
void set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value);
private:
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 2abd927..449a5a6 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -65,6 +65,7 @@
// Must be included last.
#include <google/protobuf/port_def.inc>
+#define DEBUG_STRING_SILENT_MARKER "\t "
namespace google {
namespace protobuf {
@@ -1247,6 +1248,18 @@
buffer_size_(0),
at_start_of_line_(true),
failed_(false),
+ insert_silent_marker_(false),
+ indent_level_(initial_indent_level),
+ initial_indent_level_(initial_indent_level) {}
+
+ explicit TextGenerator(io::ZeroCopyOutputStream* output,
+ bool insert_silent_marker, int initial_indent_level)
+ : output_(output),
+ buffer_(nullptr),
+ buffer_size_(0),
+ at_start_of_line_(true),
+ failed_(false),
+ insert_silent_marker_(insert_silent_marker),
indent_level_(initial_indent_level),
initial_indent_level_(initial_indent_level) {}
@@ -1309,6 +1322,22 @@
// error.)
bool failed() const { return failed_; }
+ void PrintMaybeWithMarker(StringPiece text) {
+ Print(text.data(), text.size());
+ if (ConsumeInsertSilentMarker()) {
+ PrintLiteral(DEBUG_STRING_SILENT_MARKER);
+ }
+ }
+
+ void PrintMaybeWithMarker(StringPiece text_head,
+ StringPiece text_tail) {
+ Print(text_head.data(), text_head.size());
+ if (ConsumeInsertSilentMarker()) {
+ PrintLiteral(DEBUG_STRING_SILENT_MARKER);
+ }
+ Print(text_tail.data(), text_tail.size());
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
@@ -1369,17 +1398,68 @@
buffer_size_ -= size;
}
+ // Return the current value of insert_silent_marker_. If it is true, set it
+ // to false as we assume that a silent marker is inserted after a call to this
+ // function.
+ bool ConsumeInsertSilentMarker() {
+ if (insert_silent_marker_) {
+ insert_silent_marker_ = false;
+ return true;
+ }
+ return false;
+ }
+
io::ZeroCopyOutputStream* const output_;
char* buffer_;
int buffer_size_;
bool at_start_of_line_;
bool failed_;
+ // This flag is false when inserting silent marker is disabled or a silent
+ // marker has been inserted.
+ bool insert_silent_marker_;
int indent_level_;
int initial_indent_level_;
};
// ===========================================================================
+// An internal field value printer that may insert a silent marker in
+// DebugStrings.
+class TextFormat::Printer::DebugStringFieldValuePrinter
+ : public TextFormat::FastFieldValuePrinter {
+ public:
+ void PrintMessageStart(const Message& message, int field_index,
+ int field_count, bool single_line_mode,
+ BaseTextGenerator* generator) const override {
+ // This is safe as only TextGenerator is used with
+ // DebugStringFieldValuePrinter.
+ TextGenerator* text_generator = static_cast<TextGenerator*>(generator);
+ if (single_line_mode) {
+ text_generator->PrintMaybeWithMarker(" ", "{ ");
+ } else {
+ text_generator->PrintMaybeWithMarker(" ", "{\n");
+ }
+ }
+};
+
+// ===========================================================================
+// An internal field value printer that escape UTF8 strings.
+class TextFormat::Printer::FastFieldValuePrinterUtf8Escaping
+ : public TextFormat::Printer::DebugStringFieldValuePrinter {
+ public:
+ void PrintString(const std::string& val,
+ TextFormat::BaseTextGenerator* generator) const override {
+ generator->PrintLiteral("\"");
+ generator->PrintString(strings::Utf8SafeCEscape(val));
+ generator->PrintLiteral("\"");
+ }
+ void PrintBytes(const std::string& val,
+ TextFormat::BaseTextGenerator* generator) const override {
+ return FastFieldValuePrinter::PrintString(val, generator);
+ }
+};
+
+// ===========================================================================
// Implementation of the default Finder for extensions.
TextFormat::Finder::~Finder() {}
@@ -1808,22 +1888,6 @@
std::unique_ptr<const TextFormat::FieldValuePrinter> delegate_;
};
-// Our own specialization: for UTF8 escaped strings.
-class FastFieldValuePrinterUtf8Escaping
- : public TextFormat::FastFieldValuePrinter {
- public:
- void PrintString(const std::string& val,
- TextFormat::BaseTextGenerator* generator) const override {
- generator->PrintLiteral("\"");
- generator->PrintString(strings::Utf8SafeCEscape(val));
- generator->PrintLiteral("\"");
- }
- void PrintBytes(const std::string& val,
- TextFormat::BaseTextGenerator* generator) const override {
- return FastFieldValuePrinter::PrintString(val, generator);
- }
-};
-
} // namespace
const char* const TextFormat::Printer::kDoNotParse =
@@ -1834,6 +1898,7 @@
single_line_mode_(false),
use_field_number_(false),
use_short_repeated_primitives_(false),
+ insert_silent_marker_(false),
hide_unknown_fields_(false),
print_message_fields_in_index_order_(false),
expand_any_(false),
@@ -1844,7 +1909,7 @@
void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) {
SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping()
- : new FastFieldValuePrinter());
+ : new DebugStringFieldValuePrinter());
}
void TextFormat::Printer::SetDefaultFieldValuePrinter(
@@ -1924,7 +1989,7 @@
bool TextFormat::Printer::Print(const Message& message,
io::ZeroCopyOutputStream* output) const {
- TextGenerator generator(output, initial_indent_level_);
+ TextGenerator generator(output, insert_silent_marker_, initial_indent_level_);
Print(message, &generator);
@@ -2302,7 +2367,7 @@
printer->PrintMessageEnd(sub_message, field_index, count,
single_line_mode_, generator);
} else {
- generator->PrintLiteral(": ");
+ generator->PrintMaybeWithMarker(": ");
// Write the field value.
PrintFieldValue(message, reflection, field, field_index, generator);
if (single_line_mode_) {
@@ -2327,7 +2392,7 @@
int size = reflection->FieldSize(message, field);
PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection,
field, generator);
- generator->PrintLiteral(": [");
+ generator->PrintMaybeWithMarker(": ", "[");
for (int i = 0; i < size; i++) {
if (i > 0) generator->PrintLiteral(", ");
PrintFieldValue(message, reflection, field, i, generator);
@@ -2481,7 +2546,7 @@
switch (field.type()) {
case UnknownField::TYPE_VARINT:
generator->PrintString(field_number);
- generator->PrintLiteral(": ");
+ generator->PrintMaybeWithMarker(": ");
generator->PrintString(StrCat(field.varint()));
if (single_line_mode_) {
generator->PrintLiteral(" ");
@@ -2491,7 +2556,7 @@
break;
case UnknownField::TYPE_FIXED32: {
generator->PrintString(field_number);
- generator->PrintLiteral(": 0x");
+ generator->PrintMaybeWithMarker(": ", "0x");
generator->PrintString(
StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
if (single_line_mode_) {
@@ -2503,7 +2568,7 @@
}
case UnknownField::TYPE_FIXED64: {
generator->PrintString(field_number);
- generator->PrintLiteral(": 0x");
+ generator->PrintMaybeWithMarker(": ", "0x");
generator->PrintString(
StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
if (single_line_mode_) {
@@ -2528,9 +2593,9 @@
// This field is parseable as a Message.
// So it is probably an embedded message.
if (single_line_mode_) {
- generator->PrintLiteral(" { ");
+ generator->PrintMaybeWithMarker(" ", "{ ");
} else {
- generator->PrintLiteral(" {\n");
+ generator->PrintMaybeWithMarker(" ", "{\n");
generator->Indent();
}
PrintUnknownFields(embedded_unknown_fields, generator,
@@ -2544,7 +2609,7 @@
} else {
// This field is not parseable as a Message (or we ran out of
// recursion budget). So it is probably just a plain string.
- generator->PrintLiteral(": \"");
+ generator->PrintMaybeWithMarker(": ", "\"");
generator->PrintString(CEscape(value));
if (single_line_mode_) {
generator->PrintLiteral("\" ");
@@ -2557,9 +2622,9 @@
case UnknownField::TYPE_GROUP:
generator->PrintString(field_number);
if (single_line_mode_) {
- generator->PrintLiteral(" { ");
+ generator->PrintMaybeWithMarker(" ", "{ ");
} else {
- generator->PrintLiteral(" {\n");
+ generator->PrintMaybeWithMarker(" ", "{\n");
generator->Indent();
}
// For groups, we recurse without checking the budget. This is OK,
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 3a3ee15..ce4d1f4 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -62,9 +62,9 @@
class ErrorCollector; // tokenizer.h
}
-// This class implements protocol buffer text format. Printing and parsing
-// protocol messages in text format is useful for debugging and human editing
-// of messages.
+// This class implements protocol buffer text format, colloquially known as text
+// proto. Printing and parsing protocol messages in text format is useful for
+// debugging and human editing of messages.
//
// This class is really a namespace that contains only static methods.
class PROTOBUF_EXPORT TextFormat {
@@ -369,6 +369,14 @@
// output to the OutputStream (see text_format.cc for implementation).
class TextGenerator;
+ // Forward declaration of an internal class used to print field values for
+ // DebugString APIs (see text_format.cc for implementation).
+ class DebugStringFieldValuePrinter;
+
+ // Forward declaration of an internal class used to print UTF-8 escaped
+ // strings (see text_format.cc for implementation).
+ class FastFieldValuePrinterUtf8Escaping;
+
static const char* const kDoNotParse;
// Internal Print method, used for writing to the OutputStream via
@@ -419,6 +427,7 @@
bool single_line_mode_;
bool use_field_number_;
bool use_short_repeated_primitives_;
+ bool insert_silent_marker_;
bool hide_unknown_fields_;
bool print_message_fields_in_index_order_;
bool expand_any_;
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index a3040a6..1828f83 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -285,7 +285,7 @@
void Timestamp::InternalSwap(Timestamp* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(Timestamp, nanos_)
+ sizeof(Timestamp::nanos_)
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 024b277..214d205 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -696,7 +696,7 @@
void Type::InternalSwap(Type* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
fields_.InternalSwap(&other->fields_);
oneofs_.InternalSwap(&other->oneofs_);
options_.InternalSwap(&other->options_);
@@ -1173,7 +1173,7 @@
void Field::InternalSwap(Field* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
options_.InternalSwap(&other->options_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -1522,7 +1522,7 @@
void Enum::InternalSwap(Enum* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
enumvalue_.InternalSwap(&other->enumvalue_);
options_.InternalSwap(&other->options_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
@@ -1788,7 +1788,7 @@
void EnumValue::InternalSwap(EnumValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
options_.InternalSwap(&other->options_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
swap(number_, other->number_);
@@ -2038,7 +2038,7 @@
void Option::InternalSwap(Option* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
swap(value_, other->value_);
}
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index acc86ed..e6a93f1 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -373,7 +373,7 @@
public:
void clear_source_context();
const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
- PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
private:
@@ -938,7 +938,7 @@
public:
void clear_source_context();
const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
- PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
private:
@@ -1273,7 +1273,7 @@
public:
void clear_value();
const PROTOBUF_NAMESPACE_ID::Any& value() const;
- PROTOBUF_NAMESPACE_ID::Any* release_value();
+ PROTOBUF_FUTURE_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::Any* release_value();
PROTOBUF_NAMESPACE_ID::Any* mutable_value();
void set_allocated_value(PROTOBUF_NAMESPACE_ID::Any* value);
private:
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index fa26488..1752939 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -116,6 +116,23 @@
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
+ // Optional
+ optional int32 proto3_optional_int32 = 116;
+ optional int64 proto3_optional_int64 = 117;
+ optional uint32 proto3_optional_uint32 = 118;
+ optional uint64 proto3_optional_uint64 = 119;
+ optional sint32 proto3_optional_sint32 = 120;
+ optional sint64 proto3_optional_sint64 = 121;
+ optional fixed32 proto3_optional_fixed32 = 122;
+ optional fixed64 proto3_optional_fixed64 = 123;
+ optional sfixed32 proto3_optional_sfixed32 = 124;
+ optional sfixed64 proto3_optional_sfixed64 = 125;
+ optional float proto3_optional_float = 126;
+ optional double proto3_optional_double = 127;
+ optional bool proto3_optional_bool = 128;
+ optional string proto3_optional_string = 129;
+ optional bytes proto3_optional_bytes = 130;
+
// Groups are not allowed in proto3.
// repeated group RepeatedGroup = 46 {
// optional int32 a = 47;
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 4815178..88e01df 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -266,7 +266,6 @@
MessageDifferencer::MessageDifferencer()
: reporter_(NULL),
- field_comparator_(NULL),
message_field_comparison_(EQUAL),
scope_(FULL),
repeated_field_comparison_(AS_LIST),
@@ -289,9 +288,19 @@
void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
- field_comparator_ = comparator;
+ field_comparator_kind_ = kFCBase;
+ field_comparator_.base = comparator;
}
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+void MessageDifferencer::set_field_comparator(
+ DefaultFieldComparator* comparator) {
+ GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
+ field_comparator_kind_ = kFCDefault;
+ field_comparator_.default_impl = comparator;
+}
+#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
+
void MessageDifferencer::set_message_field_comparison(
MessageFieldComparison comparison) {
message_field_comparison_ = comparison;
@@ -1008,44 +1017,29 @@
const Reflection* reflection2 = message2.GetReflection();
// When both map fields are on map, do not sync to repeated field.
- // TODO(jieluo): Add support for reporter
- if (reporter_ == nullptr &&
+ if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() &&
+ reflection2->GetMapData(message2, repeated_field)->IsMapValid() &&
+ // TODO(jieluo): Add support for reporter
+ reporter_ == nullptr &&
// Users didn't set custom map field key comparator
map_field_key_comparator_.find(repeated_field) ==
map_field_key_comparator_.end() &&
// Users didn't set repeated field comparison
- repeated_field_comparison_ == AS_LIST) {
- DefaultFieldComparator* map_field_comparator =
- field_comparator_ ? nullptr : &default_field_comparator_;
-#if PROTOBUF_RTTI
- // Inherit class from DefaultFieldComparator can not get the benefit
- // because DefaultFieldComparator::Compare() method might be overwrote.
- if (field_comparator_ &&
- typeid(*field_comparator_) == typeid(default_field_comparator_)) {
- map_field_comparator =
- static_cast<DefaultFieldComparator*>(field_comparator_);
- }
-#endif
- if (map_field_comparator) {
- const FieldDescriptor* key_des =
- repeated_field->message_type()->map_key();
- const FieldDescriptor* val_des =
- repeated_field->message_type()->map_value();
- const internal::MapFieldBase* map_field1 =
- reflection1->GetMapData(message1, repeated_field);
- const internal::MapFieldBase* map_field2 =
- reflection2->GetMapData(message2, repeated_field);
- std::vector<SpecificField> current_parent_fields(*parent_fields);
- SpecificField specific_field;
- specific_field.field = repeated_field;
- current_parent_fields.push_back(specific_field);
- if (map_field1->IsMapValid() && map_field2->IsMapValid() &&
- !IsIgnored(message1, message2, key_des, current_parent_fields) &&
- !IsIgnored(message1, message2, val_des, current_parent_fields)) {
- return CompareMapFieldByMapReflection(
- message1, message2, repeated_field, ¤t_parent_fields,
- map_field_comparator);
- }
+ repeated_field_comparison_ == AS_LIST &&
+ // Users didn't set their own FieldComparator implementation
+ field_comparator_kind_ == kFCDefault) {
+ const FieldDescriptor* key_des = repeated_field->message_type()->map_key();
+ const FieldDescriptor* val_des =
+ repeated_field->message_type()->map_value();
+ std::vector<SpecificField> current_parent_fields(*parent_fields);
+ SpecificField specific_field;
+ specific_field.field = repeated_field;
+ current_parent_fields.push_back(specific_field);
+ if (!IsIgnored(message1, message2, key_des, current_parent_fields) &&
+ !IsIgnored(message1, message2, val_des, current_parent_fields)) {
+ return CompareMapFieldByMapReflection(message1, message2, repeated_field,
+ ¤t_parent_fields,
+ field_comparator_.default_impl);
}
}
@@ -1869,9 +1863,9 @@
const Message& message1, const Message& message2,
const FieldDescriptor* field, int index1, int index2,
const FieldContext* field_context) {
- FieldComparator* comparator = field_comparator_ != NULL
- ? field_comparator_
- : &default_field_comparator_;
+ FieldComparator* comparator = field_comparator_kind_ == kFCBase
+ ? field_comparator_.base
+ : field_comparator_.default_impl;
return comparator->Compare(message1, message2, field, index1, index2,
field_context);
}
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index 943a0db..4cdb817 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -533,6 +533,9 @@
// Note that this method must be called before Compare for the comparator to
// be used.
void set_field_comparator(FieldComparator* comparator);
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+ void set_field_comparator(DefaultFieldComparator* comparator);
+#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
// DEPRECATED. Pass a DefaultFieldComparator instance instead.
// Sets the fraction and margin for the float comparison of a given field.
@@ -904,7 +907,6 @@
Reporter* reporter_;
DefaultFieldComparator default_field_comparator_;
- FieldComparator* field_comparator_;
MessageFieldComparison message_field_comparison_;
Scope scope_;
RepeatedFieldComparison repeated_field_comparison_;
@@ -925,6 +927,12 @@
FieldSet ignored_fields_;
+ union {
+ DefaultFieldComparator* default_impl;
+ FieldComparator* base;
+ } field_comparator_ = {&default_field_comparator_};
+ enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
+
bool report_matches_;
bool report_moves_;
bool report_ignores_;
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index c791d05..0f16f66 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -417,7 +417,7 @@
void DoubleValue::InternalSwap(DoubleValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -605,7 +605,7 @@
void FloatValue::InternalSwap(FloatValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -795,7 +795,7 @@
void Int64Value::InternalSwap(Int64Value* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -985,7 +985,7 @@
void UInt64Value::InternalSwap(UInt64Value* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -1175,7 +1175,7 @@
void Int32Value::InternalSwap(Int32Value* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -1365,7 +1365,7 @@
void UInt32Value::InternalSwap(UInt32Value* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -1553,7 +1553,7 @@
void BoolValue::InternalSwap(BoolValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
swap(value_, other->value_);
}
@@ -1754,7 +1754,7 @@
void StringValue::InternalSwap(StringValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
}
@@ -1950,7 +1950,7 @@
void BytesValue::InternalSwap(BytesValue* other) {
using std::swap;
- _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
}