Explorar o código

Merge pull request #7378 from haberman/sync-stage

Integrate from Piper for C++, Java, and Python
Joshua Haberman %!s(int64=5) %!d(string=hai) anos
pai
achega
88529f5017
Modificáronse 28 ficheiros con 258 adicións e 165 borrados
  1. BIN=BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  2. 14 3
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  3. 52 12
      php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
  4. 5 2
      python/google/protobuf/pyext/message.cc
  5. 1 1
      src/google/protobuf/compiler/cpp/cpp_field.cc
  6. 1 0
      src/google/protobuf/compiler/cpp/cpp_file.cc
  7. 5 5
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  8. 5 35
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  9. 33 35
      src/google/protobuf/compiler/cpp/cpp_message.cc
  10. 2 2
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  11. 3 1
      src/google/protobuf/compiler/java/java_file.cc
  12. 2 3
      src/google/protobuf/compiler/mock_code_generator.h
  13. 1 2
      src/google/protobuf/compiler/parser.cc
  14. 3 4
      src/google/protobuf/compiler/python/python_generator.h
  15. 36 0
      src/google/protobuf/descriptor.cc
  16. 17 1
      src/google/protobuf/descriptor.h
  17. 14 3
      src/google/protobuf/descriptor.proto
  18. 1 1
      src/google/protobuf/dynamic_message.cc
  19. 1 1
      src/google/protobuf/generated_message_reflection.h
  20. 8 7
      src/google/protobuf/generated_message_table_driven_lite.h
  21. 9 0
      src/google/protobuf/stubs/statusor.h
  22. 2 2
      src/google/protobuf/util/internal/datapiece.cc
  23. 5 5
      src/google/protobuf/util/internal/default_value_objectwriter.cc
  24. 8 8
      src/google/protobuf/util/internal/object_writer.cc
  25. 17 17
      src/google/protobuf/util/internal/proto_writer.cc
  26. 1 1
      src/google/protobuf/util/internal/protostream_objectsource.cc
  27. 8 10
      src/google/protobuf/util/internal/protostream_objectwriter.cc
  28. 4 4
      src/google/protobuf/util/internal/type_info.cc

BIN=BIN
csharp/src/Google.Protobuf.Test/testprotos.pb


+ 14 - 3
csharp/src/Google.Protobuf/Reflection/Descriptor.cs

@@ -2074,10 +2074,21 @@ namespace Google.Protobuf.Reflection {
     /// If true, this is a proto3 "optional". When a proto3 field is optional, it
     /// tracks presence regardless of field type.
     ///
-    /// For message fields this doesn't create any semantic change, since
-    /// non-repeated message fields always track presence. However it still
+    /// When proto3_optional is true, this field must be belong to a oneof to
+    /// signal to old proto3 clients that presence is tracked for this field. This
+    /// oneof is known as a "synthetic" oneof, and this field must be its sole
+    /// member (each proto3 optional field gets its own synthetic oneof). Synthetic
+    /// oneofs exist in the descriptor only, and do not generate any API. Synthetic
+    /// oneofs must be ordered after all "real" oneofs.
+    ///
+    /// For message fields, proto3_optional doesn't create any semantic change,
+    /// since non-repeated message fields always track presence. However it still
     /// indicates the semantic detail of whether the user wrote "optional" or not.
-    /// This can be useful for round-tripping the .proto file.
+    /// This can be useful for round-tripping the .proto file. For consistency we
+    /// give message fields a synthetic oneof also, even though it is not required
+    /// to track presence. This is especially important because the parser can't
+    /// tell if a field is a message or an enum, so it must always create a
+    /// synthetic oneof.
     ///
     /// Proto2 optional fields do not set this flag, because they already indicate
     /// optional with `LABEL_OPTIONAL`.

+ 52 - 12
php/src/Google/Protobuf/Internal/FieldDescriptorProto.php

@@ -96,10 +96,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
-     * For message fields this doesn't create any semantic change, since
-     * non-repeated message fields always track presence. However it still
+     * When proto3_optional is true, this field must be belong to a oneof to
+     * signal to old proto3 clients that presence is tracked for this field. This
+     * oneof is known as a "synthetic" oneof, and this field must be its sole
+     * member (each proto3 optional field gets its own synthetic oneof). Synthetic
+     * oneofs exist in the descriptor only, and do not generate any API. Synthetic
+     * oneofs must be ordered after all "real" oneofs.
+     * For message fields, proto3_optional doesn't create any semantic change,
+     * since non-repeated message fields always track presence. However it still
      * indicates the semantic detail of whether the user wrote "optional" or not.
-     * This can be useful for round-tripping the .proto file.
+     * This can be useful for round-tripping the .proto file. For consistency we
+     * give message fields a synthetic oneof also, even though it is not required
+     * to track presence. This is especially important because the parser can't
+     * tell if a field is a message or an enum, so it must always create a
+     * synthetic oneof.
      * Proto2 optional fields do not set this flag, because they already indicate
      * optional with `LABEL_OPTIONAL`.
      *
@@ -147,10 +157,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *     @type bool $proto3_optional
      *           If true, this is a proto3 "optional". When a proto3 field is optional, it
      *           tracks presence regardless of field type.
-     *           For message fields this doesn't create any semantic change, since
-     *           non-repeated message fields always track presence. However it still
+     *           When proto3_optional is true, this field must be belong to a oneof to
+     *           signal to old proto3 clients that presence is tracked for this field. This
+     *           oneof is known as a "synthetic" oneof, and this field must be its sole
+     *           member (each proto3 optional field gets its own synthetic oneof). Synthetic
+     *           oneofs exist in the descriptor only, and do not generate any API. Synthetic
+     *           oneofs must be ordered after all "real" oneofs.
+     *           For message fields, proto3_optional doesn't create any semantic change,
+     *           since non-repeated message fields always track presence. However it still
      *           indicates the semantic detail of whether the user wrote "optional" or not.
-     *           This can be useful for round-tripping the .proto file.
+     *           This can be useful for round-tripping the .proto file. For consistency we
+     *           give message fields a synthetic oneof also, even though it is not required
+     *           to track presence. This is especially important because the parser can't
+     *           tell if a field is a message or an enum, so it must always create a
+     *           synthetic oneof.
      *           Proto2 optional fields do not set this flag, because they already indicate
      *           optional with `LABEL_OPTIONAL`.
      * }
@@ -495,10 +515,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
-     * For message fields this doesn't create any semantic change, since
-     * non-repeated message fields always track presence. However it still
+     * When proto3_optional is true, this field must be belong to a oneof to
+     * signal to old proto3 clients that presence is tracked for this field. This
+     * oneof is known as a "synthetic" oneof, and this field must be its sole
+     * member (each proto3 optional field gets its own synthetic oneof). Synthetic
+     * oneofs exist in the descriptor only, and do not generate any API. Synthetic
+     * oneofs must be ordered after all "real" oneofs.
+     * For message fields, proto3_optional doesn't create any semantic change,
+     * since non-repeated message fields always track presence. However it still
      * indicates the semantic detail of whether the user wrote "optional" or not.
-     * This can be useful for round-tripping the .proto file.
+     * This can be useful for round-tripping the .proto file. For consistency we
+     * give message fields a synthetic oneof also, even though it is not required
+     * to track presence. This is especially important because the parser can't
+     * tell if a field is a message or an enum, so it must always create a
+     * synthetic oneof.
      * Proto2 optional fields do not set this flag, because they already indicate
      * optional with `LABEL_OPTIONAL`.
      *
@@ -513,10 +543,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
-     * For message fields this doesn't create any semantic change, since
-     * non-repeated message fields always track presence. However it still
+     * When proto3_optional is true, this field must be belong to a oneof to
+     * signal to old proto3 clients that presence is tracked for this field. This
+     * oneof is known as a "synthetic" oneof, and this field must be its sole
+     * member (each proto3 optional field gets its own synthetic oneof). Synthetic
+     * oneofs exist in the descriptor only, and do not generate any API. Synthetic
+     * oneofs must be ordered after all "real" oneofs.
+     * For message fields, proto3_optional doesn't create any semantic change,
+     * since non-repeated message fields always track presence. However it still
      * indicates the semantic detail of whether the user wrote "optional" or not.
-     * This can be useful for round-tripping the .proto file.
+     * This can be useful for round-tripping the .proto file. For consistency we
+     * give message fields a synthetic oneof also, even though it is not required
+     * to track presence. This is especially important because the parser can't
+     * tell if a field is a message or an enum, so it must always create a
+     * synthetic oneof.
      * Proto2 optional fields do not set this flag, because they already indicate
      * optional with `LABEL_OPTIONAL`.
      *

+ 5 - 2
python/google/protobuf/pyext/message.cc

@@ -33,11 +33,14 @@
 
 #include <google/protobuf/pyext/message.h>
 
+#include <structmember.h>  // A Python header file.
+
 #include <map>
 #include <memory>
 #include <string>
 #include <vector>
-#include <structmember.h>  // A Python header file.
+
+#include <google/protobuf/stubs/strutil.h>
 
 #ifndef PyVarObject_HEAD_INIT
 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -456,7 +459,7 @@ static PyObject* GetClassAttribute(CMessageClass *self, PyObject* name) {
   Py_ssize_t attr_size;
   static const char kSuffix[] = "_FIELD_NUMBER";
   if (PyString_AsStringAndSize(name, &attr, &attr_size) >= 0 &&
-      strings::EndsWith(StringPiece(attr, attr_size), kSuffix)) {
+      HasSuffixString(StringPiece(attr, attr_size), kSuffix)) {
     std::string field_name(attr, attr_size - sizeof(kSuffix) + 1);
     LowerString(&field_name);
 

+ 1 - 1
src/google/protobuf/compiler/cpp/cpp_field.cc

@@ -156,7 +156,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(
       default:
         return new RepeatedPrimitiveFieldGenerator(field, options);
     }
-  } else if (InRealOneof(field)) {
+  } else if (field->real_containing_oneof()) {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
         return new MessageOneofFieldGenerator(field, options, scc_analyzer);

+ 1 - 0
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -34,6 +34,7 @@
 
 #include <google/protobuf/compiler/cpp/cpp_file.h>
 
+#include <iostream>
 #include <map>
 #include <memory>
 #include <set>

+ 5 - 5
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -1151,7 +1151,7 @@ bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
   return UsingImplicitWeakFields(field->file(), options) &&
          field->type() == FieldDescriptor::TYPE_MESSAGE &&
          !field->is_required() && !field->is_map() && !field->is_extension() &&
-         !InRealOneof(field) &&
+         !field->real_containing_oneof() &&
          !IsWellKnownMessage(field->message_type()->file()) &&
          field->message_type()->file()->name() !=
              "net/proto2/proto/descriptor.proto" &&
@@ -1474,7 +1474,7 @@ class ParseLoopGenerator {
         GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
         // For now only use arena string for strings with empty defaults.
         field->default_value_string().empty() &&
-        !IsStringInlined(field, options_) && !InRealOneof(field) &&
+        !IsStringInlined(field, options_) && !field->real_containing_oneof() &&
         ctype == FieldOptions::STRING) {
       GenerateArenaString(field);
     } else {
@@ -1580,7 +1580,7 @@ class ParseLoopGenerator {
                       FieldName(field));
             }
           } else if (IsLazy(field, options_)) {
-            if (InRealOneof(field)) {
+            if (field->real_containing_oneof()) {
               format_(
                   "if (!_internal_has_$1$()) {\n"
                   "  clear_$2$();\n"
@@ -1684,7 +1684,7 @@ class ParseLoopGenerator {
                field->type() == FieldDescriptor::TYPE_SINT64)) {
             zigzag = "ZigZag";
           }
-          if (field->is_repeated() || InRealOneof(field)) {
+          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"
@@ -1706,7 +1706,7 @@ class ParseLoopGenerator {
       case WireFormatLite::WIRETYPE_FIXED32:
       case WireFormatLite::WIRETYPE_FIXED64: {
         std::string type = PrimitiveTypeName(options_, field->cpp_type());
-        if (field->is_repeated() || InRealOneof(field)) {
+        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"

+ 5 - 35
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -444,23 +444,6 @@ inline bool HasHasbit(const FieldDescriptor* field) {
          !field->options().weak();
 }
 
-inline bool InRealOneof(const FieldDescriptor* field) {
-  return field->containing_oneof() &&
-         !field->containing_oneof()->is_synthetic();
-}
-
-// In practice all synthetic oneofs should be at the end of the list, but we
-// decline to depend on this for correctness of the function.
-inline int RealOneofCount(const Descriptor* descriptor) {
-  int count = 0;
-  for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
-    if (!descriptor->oneof_decl(i)->is_synthetic()) {
-      count++;
-    }
-  }
-  return count;
-}
-
 // Returns true if 'enum' semantics are such that unknown values are preserved
 // in the enum field itself, rather than going to the UnknownFieldSet.
 inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
@@ -886,14 +869,6 @@ struct OneOfRangeImpl {
     using value_type = const OneofDescriptor*;
     using difference_type = int;
 
-    explicit Iterator(const Descriptor* _descriptor)
-        : idx(-1), descriptor(_descriptor) {
-      Next();
-    }
-
-    Iterator(int _idx, const Descriptor* _descriptor)
-        : idx(_idx), descriptor(_descriptor) {}
-
     value_type operator*() { return descriptor->oneof_decl(idx); }
 
     friend bool operator==(const Iterator& a, const Iterator& b) {
@@ -905,23 +880,18 @@ struct OneOfRangeImpl {
     }
 
     Iterator& operator++() {
-      Next();
+      idx++;
       return *this;
     }
 
-    void Next() {
-      do {
-        idx++;
-      } while (idx < descriptor->oneof_decl_count() &&
-               descriptor->oneof_decl(idx)->is_synthetic());
-    }
-
     int idx;
     const Descriptor* descriptor;
   };
 
-  Iterator begin() const { return Iterator(descriptor); }
-  Iterator end() const { return {descriptor->oneof_decl_count(), descriptor}; }
+  Iterator begin() const { return {0, descriptor}; }
+  Iterator end() const {
+    return {descriptor->real_oneof_decl_count(), descriptor};
+  }
 
   const Descriptor* descriptor;
 };

+ 33 - 35
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -226,7 +226,7 @@ bool EmitFieldNonDefaultCondition(io::Printer* printer,
     }
     format.Indent();
     return true;
-  } else if (InRealOneof(field)) {
+  } else if (field->real_containing_oneof()) {
     format("if (_internal_has_$name$()) {\n");
     format.Indent();
     return true;
@@ -282,7 +282,7 @@ void CollectMapInfo(const Options& options, const Descriptor* descriptor,
 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()) && InRealOneof(field));
+  return (!HasFieldPresence(field->file()) && field->real_containing_oneof());
 }
 
 // TODO(ckennelly):  Cull these exclusions if/when these protos do not have
@@ -597,7 +597,7 @@ MessageGenerator::MessageGenerator(
 
     if (IsWeak(field, options_)) {
       num_weak_fields_++;
-    } else if (!InRealOneof(field)) {
+    } else if (!field->real_containing_oneof()) {
       optimized_order_.push_back(field);
     }
   }
@@ -677,7 +677,7 @@ void MessageGenerator::AddGenerators(
 void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
   Formatter format(printer, variables_);
   // optimized_fields_ does not contain fields where
-  //    InRealOneof(field) == true
+  //    field->real_containing_oneof()
   // so we need to iterate over those as well.
   //
   // We place the non-oneof fields in optimized_order_, as that controls the
@@ -689,7 +689,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
   ordered_fields.insert(ordered_fields.begin(), optimized_order_.begin(),
                         optimized_order_.end());
   for (auto field : FieldRange(descriptor_)) {
-    if (!InRealOneof(field) && !field->options().weak() &&
+    if (!field->real_containing_oneof() && !field->options().weak() &&
         IsFieldUsed(field, options_)) {
       continue;
     }
@@ -922,7 +922,7 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
 
   format.Indent();
 
-  if (InRealOneof(field)) {
+  if (field->real_containing_oneof()) {
     // Clear this field only if it is the active field in this oneof,
     // otherwise ignore
     format("if (_internal_has_$name$()) {\n");
@@ -983,7 +983,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
                 ? ".weak"
                 : "");
       }
-    } else if (InRealOneof(field)) {
+    } else if (field->real_containing_oneof()) {
       format.Set("field_name", UnderscoresToCamelCase(field->name(), true));
       format.Set("oneof_name", field->containing_oneof()->name());
       format.Set("oneof_index",
@@ -1485,7 +1485,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   for (auto field : FieldRange(descriptor_)) {
     // set_has_***() generated in all oneofs.
     if (!field->is_repeated() && !field->options().weak() &&
-        InRealOneof(field)) {
+        field->real_containing_oneof()) {
       format("void set_has_$1$();\n", FieldName(field));
     }
   }
@@ -1594,12 +1594,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   }
 
   // Generate _oneof_case_.
-  int count = RealOneofCount(descriptor_);
-  if (count > 0) {
+  if (descriptor_->real_oneof_decl_count() > 0) {
     format(
         "$uint32$ _oneof_case_[$1$];\n"
         "\n",
-        count);
+        descriptor_->real_oneof_decl_count());
   }
 
   if (num_weak_fields_) {
@@ -1695,7 +1694,7 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
     format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
   }
 
-  if (RealOneofCount(descriptor_) > 0) {
+  if (descriptor_->real_oneof_decl_count() > 0) {
     format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_),\n");
   } else {
     format("-1,  // no _oneof_case_\n");
@@ -1755,7 +1754,7 @@ uint32 CalcFieldNum(const FieldGenerator& generator,
     }
   }
 
-  if (InRealOneof(field)) {
+  if (field->real_containing_oneof()) {
     return internal::FieldMetadata::CalculateType(
         type, internal::FieldMetadata::kOneOf);
   } else if (field->is_packed()) {
@@ -1764,7 +1763,7 @@ uint32 CalcFieldNum(const FieldGenerator& generator,
   } else if (field->is_repeated()) {
     return internal::FieldMetadata::CalculateType(
         type, internal::FieldMetadata::kRepeated);
-  } else if (HasHasbit(field) || InRealOneof(field) || is_a_map) {
+  } else if (HasHasbit(field) || field->real_containing_oneof() || is_a_map) {
     return internal::FieldMetadata::CalculateType(
         type, internal::FieldMetadata::kPresence);
   } else {
@@ -1859,7 +1858,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
     }
 
     std::string classfieldname = FieldName(field);
-    if (InRealOneof(field)) {
+    if (field->real_containing_oneof()) {
       classfieldname = field->containing_oneof()->name();
     }
     format.Set("field_name", classfieldname);
@@ -1895,7 +1894,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
       type = internal::FieldMetadata::kSpecial;
       ptr = "reinterpret_cast<const void*>(::" + variables_["proto_ns"] +
             "::internal::LazyFieldSerializer";
-      if (InRealOneof(field)) {
+      if (field->real_containing_oneof()) {
         ptr += "OneOf";
       } else if (!HasHasbit(field)) {
         ptr += "NoPresence";
@@ -1912,7 +1911,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
           "reinterpret_cast<const "
           "void*>(::$proto_ns$::internal::WeakFieldSerializer)},\n",
           tag);
-    } else if (InRealOneof(field)) {
+    } else if (field->real_containing_oneof()) {
       format.Set("oneofoffset",
                  sizeof(uint32) * field->containing_oneof()->index());
       format(
@@ -1972,10 +1971,10 @@ void MessageGenerator::GenerateDefaultInstanceInitializer(
 
     if (!field->is_repeated() && !IsLazy(field, options_) &&
         field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        (!InRealOneof(field) ||
+        (!field->real_containing_oneof() ||
          HasDescriptorMethods(descriptor_->file(), options_))) {
       std::string name;
-      if (InRealOneof(field) || field->options().weak()) {
+      if (field->real_containing_oneof() || field->options().weak()) {
         name = "_" + classname_ + "_default_instance_.";
       } else {
         name =
@@ -2007,7 +2006,7 @@ void MessageGenerator::GenerateDefaultInstanceInitializer(
             "    $1$::internal_default_instance());\n",
             FieldMessageTypeName(field, options_));
       }
-    } else if (InRealOneof(field) &&
+    } else if (field->real_containing_oneof() &&
                HasDescriptorMethods(descriptor_->file(), options_)) {
       field_generators_.get(field).GenerateConstructorCode(printer);
     }
@@ -2118,7 +2117,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
       Formatter::SaveState saver(&format);
       std::map<std::string, std::string> vars;
       SetCommonFieldVariables(field, &vars, options_);
-      if (InRealOneof(field)) {
+      if (field->real_containing_oneof()) {
         SetCommonOneofFieldVariables(field, &vars);
       }
       format.AddMap(vars);
@@ -2129,7 +2128,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
   GenerateStructors(printer);
   format("\n");
 
-  if (RealOneofCount(descriptor_) > 0) {
+  if (descriptor_->real_oneof_decl_count() > 0) {
     GenerateOneofClear(printer);
     format("\n");
   }
@@ -2258,8 +2257,8 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) {
 
     processing_type |= static_cast<unsigned>(
         field->is_repeated() ? internal::kRepeatedMask : 0);
-    processing_type |=
-        static_cast<unsigned>(InRealOneof(field) ? internal::kOneofMask : 0);
+    processing_type |= static_cast<unsigned>(
+        field->real_containing_oneof() ? internal::kOneofMask : 0);
 
     if (field->is_map()) {
       processing_type = internal::TYPE_MAP;
@@ -2269,7 +2268,7 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) {
         WireFormat::TagSize(field->number(), field->type());
 
     std::map<std::string, std::string> vars;
-    if (InRealOneof(field)) {
+    if (field->real_containing_oneof()) {
       vars["name"] = field->containing_oneof()->name();
       vars["presence"] = StrCat(field->containing_oneof()->index());
     } else {
@@ -2400,7 +2399,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
   } else {
     format("~0u,  // no _extensions_\n");
   }
-  if (RealOneofCount(descriptor_) > 0) {
+  if (descriptor_->real_oneof_decl_count() > 0) {
     format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_[0]),\n");
   } else {
     format("~0u,  // no _oneof_case_\n");
@@ -2418,13 +2417,13 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
   }
   const int kNumGenericOffsets = 5;  // the number of fixed offsets above
   const size_t offsets = kNumGenericOffsets + descriptor_->field_count() +
-                         RealOneofCount(descriptor_) - num_stripped;
+                         descriptor_->real_oneof_decl_count() - num_stripped;
   size_t entries = offsets;
   for (auto field : FieldRange(descriptor_)) {
     if (!IsFieldUsed(field, options_)) {
       continue;
     }
-    if (InRealOneof(field) || field->options().weak()) {
+    if (field->real_containing_oneof() || field->options().weak()) {
       format("offsetof($classtype$DefaultTypeInternal, $1$_)",
              FieldName(field));
     } else {
@@ -2444,7 +2443,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
     format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name());
     count++;
   }
-  GOOGLE_CHECK_EQ(count, RealOneofCount(descriptor_));
+  GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count());
 
   if (IsMapEntryMessage(descriptor_)) {
     entries += 2;
@@ -2656,7 +2655,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
   for (auto field : optimized_order_) {
     GOOGLE_DCHECK(IsFieldUsed(field, options_));
     bool has_arena_constructor = field->is_repeated();
-    if (!InRealOneof(field) &&
+    if (!field->real_containing_oneof() &&
         (IsLazy(field, options_) || IsStringPiece(field, options_))) {
       has_arena_constructor = true;
     }
@@ -3122,8 +3121,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
       format("swap($1$_, other->$1$_);\n", oneof->name());
     }
 
-    int count = RealOneofCount(descriptor_);
-    for (int i = 0; i < count; i++) {
+    for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
       format("swap(_oneof_case_[$1$], other->_oneof_case_[$1$]);\n", i);
     }
 
@@ -3572,7 +3570,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
       if (eager_ || MustFlush(field)) {
         Flush();
       }
-      if (!InRealOneof(field)) {
+      if (!field->real_containing_oneof()) {
         // TODO(ckennelly): Defer non-oneof fields similarly to oneof fields.
 
         if (!field->options().weak() && !field->is_repeated() && !eager_) {
@@ -4014,7 +4012,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
       } else if (field->options().weak()) {
         continue;
       } else {
-        GOOGLE_CHECK(!InRealOneof(field));
+        GOOGLE_CHECK(!field->real_containing_oneof());
         format(
             "if (_internal_has_$1$()) {\n"
             "  if (!$1$_->IsInitialized()) return false;\n"
@@ -4054,7 +4052,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
           field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
           !ShouldIgnoreRequiredFieldCheck(field, options_) &&
           scc_analyzer_->HasRequiredFields(field->message_type())) {
-        GOOGLE_CHECK(!(field->options().weak() || !InRealOneof(field)));
+        GOOGLE_CHECK(!(field->options().weak() || !field->real_containing_oneof()));
         if (field->options().weak()) {
           // Just skip.
         } else {

+ 2 - 2
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -501,7 +501,7 @@ void StringFieldGenerator::GenerateMessageClearingCode(
 
 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (SupportsArenas(descriptor_) || InRealOneof(descriptor_)) {
+  if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) {
     // TODO(gpike): improve this
     format("_internal_set_$name$(from._internal_$name$());\n");
   } else {
@@ -545,7 +545,7 @@ void StringFieldGenerator::GenerateCopyConstructorCode(
 
   format.Indent();
 
-  if (SupportsArenas(descriptor_) || InRealOneof(descriptor_)) {
+  if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) {
     // TODO(gpike): improve this
     format(
         "$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n"

+ 3 - 1
src/google/protobuf/compiler/java/java_file.cc

@@ -94,7 +94,9 @@ bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) {
   reflection->ListFields(message, &fields);
 
   for (int i = 0; i < fields.size(); i++) {
-    if (fields[i]->is_extension()) extensions->insert(fields[i]);
+    if (fields[i]->is_extension()) {
+      extensions->insert(fields[i]);
+    }
 
     if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
       if (fields[i]->is_repeated()) {

+ 2 - 3
src/google/protobuf/compiler/mock_code_generator.h

@@ -106,9 +106,8 @@ class MockCodeGenerator : public CodeGenerator {
 
   // implements CodeGenerator ----------------------------------------
 
-  virtual bool Generate(const FileDescriptor* file,
-                        const std::string& parameter, GeneratorContext* context,
-                        std::string* error) const override;
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* context, std::string* error) const override;
 
   uint64 GetSupportedFeatures() const override;
   void SuppressFeatures(uint64 features);

+ 1 - 2
src/google/protobuf/compiler/parser.cc

@@ -783,8 +783,7 @@ bool Parser::ParseMessageDefinition(
     }
 
     for (auto& field : *message->mutable_field()) {
-      if (field.proto3_optional() &&
-          field.type() != FieldDescriptorProto::TYPE_MESSAGE) {
+      if (field.proto3_optional()) {
         std::string oneof_name = field.name();
 
         // Prepend 'XXXXX_' until we are no longer conflicting.

+ 3 - 4
src/google/protobuf/compiler/python/python_generator.h

@@ -69,10 +69,9 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
   virtual ~Generator();
 
   // CodeGenerator methods.
-  virtual bool Generate(const FileDescriptor* file,
-                        const std::string& parameter,
-                        GeneratorContext* generator_context,
-                        std::string* error) const override;
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* generator_context,
+                std::string* error) const override;
 
   uint64 GetSupportedFeatures() const override;
 

+ 36 - 0
src/google/protobuf/descriptor.cc

@@ -5500,6 +5500,42 @@ void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
           message->field(i);
     }
   }
+
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if (field->proto3_optional_) {
+      if (!field->containing_oneof() ||
+          !field->containing_oneof()->is_synthetic()) {
+        AddError(message->full_name(), proto.field(i),
+                 DescriptorPool::ErrorCollector::OTHER,
+                 "Fields with proto3_optional set must be "
+                 "a member of a one-field oneof");
+      }
+    }
+  }
+
+  // Synthetic oneofs must be last.
+  int first_synthetic = -1;
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    if (oneof->is_synthetic()) {
+      if (first_synthetic == -1) {
+        first_synthetic = i;
+      }
+    } else {
+      if (first_synthetic != -1) {
+        AddError(message->full_name(), proto.oneof_decl(i),
+                 DescriptorPool::ErrorCollector::OTHER,
+                 "Synthetic oneofs must be after all other oneofs");
+      }
+    }
+  }
+
+  if (first_synthetic == -1) {
+    message->real_oneof_decl_count_ = message->oneof_decl_count_;
+  } else {
+    message->real_oneof_decl_count_ = first_synthetic;
+  }
 }
 
 void DescriptorBuilder::CrossLinkExtensionRange(

+ 17 - 1
src/google/protobuf/descriptor.h

@@ -337,6 +337,10 @@ class PROTOBUF_EXPORT Descriptor {
 
   // The number of oneofs in this message type.
   int oneof_decl_count() const;
+  // The number of oneofs in this message type, excluding synthetic oneofs.
+  // Real oneofs always come first, so iterating up to real_oneof_decl_cout()
+  // will yield all real oneofs.
+  int real_oneof_decl_count() const;
   // Get a oneof by index, where 0 <= index < oneof_decl_count().
   // These are returned in the order they were defined in the .proto file.
   const OneofDescriptor* oneof_decl(int index) const;
@@ -526,6 +530,7 @@ class PROTOBUF_EXPORT Descriptor {
 
   int field_count_;
   int oneof_decl_count_;
+  int real_oneof_decl_count_;
   int nested_type_count_;
   int enum_type_count_;
   int extension_range_count_;
@@ -745,6 +750,10 @@ class PROTOBUF_EXPORT FieldDescriptor {
   // nullptr.
   const OneofDescriptor* containing_oneof() const;
 
+  // If the field is a member of a non-synthetic oneof, returns the descriptor
+  // for the oneof, otherwise returns nullptr.
+  const OneofDescriptor* real_containing_oneof() const;
+
   // If the field is a member of a oneof, returns the index in that oneof.
   int index_in_oneof() const;
 
@@ -1972,6 +1981,7 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*)
 
 PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int)
 PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, real_oneof_decl_count, int)
 PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int)
 PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int)
 
@@ -2166,9 +2176,15 @@ inline bool FieldDescriptor::has_optional_keyword() const {
           !containing_oneof());
 }
 
+inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const {
+  return containing_oneof_ && !containing_oneof_->is_synthetic()
+             ? containing_oneof_
+             : nullptr;
+}
+
 inline bool FieldDescriptor::is_singular_with_presence() const {
   if (is_repeated()) return false;
-  if (containing_oneof() && !containing_oneof()->is_synthetic()) return false;
+  if (real_containing_oneof()) return false;
   return cpp_type() == CPPTYPE_MESSAGE || proto3_optional_ ||
          file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }

+ 14 - 3
src/google/protobuf/descriptor.proto

@@ -217,10 +217,21 @@ message FieldDescriptorProto {
   // If true, this is a proto3 "optional". When a proto3 field is optional, it
   // tracks presence regardless of field type.
   //
-  // For message fields this doesn't create any semantic change, since
-  // non-repeated message fields always track presence. However it still
+  // When proto3_optional is true, this field must be belong to a oneof to
+  // signal to old proto3 clients that presence is tracked for this field. This
+  // oneof is known as a "synthetic" oneof, and this field must be its sole
+  // member (each proto3 optional field gets its own synthetic oneof). Synthetic
+  // oneofs exist in the descriptor only, and do not generate any API. Synthetic
+  // oneofs must be ordered after all "real" oneofs.
+  //
+  // For message fields, proto3_optional doesn't create any semantic change,
+  // since non-repeated message fields always track presence. However it still
   // indicates the semantic detail of whether the user wrote "optional" or not.
-  // This can be useful for round-tripping the .proto file.
+  // This can be useful for round-tripping the .proto file. For consistency we
+  // give message fields a synthetic oneof also, even though it is not required
+  // to track presence. This is especially important because the parser can't
+  // tell if a field is a message or an enum, so it must always create a
+  // synthetic oneof.
   //
   // Proto2 optional fields do not set this flag, because they already indicate
   // optional with `LABEL_OPTIONAL`.

+ 1 - 1
src/google/protobuf/dynamic_message.cc

@@ -737,7 +737,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
         uint32* has_bits_indices = new uint32[type->field_count()];
         for (int i = 0; i < type->field_count(); i++) {
           // Initialize to -1, fields that need a hasbit will overwrite.
-          has_bits_indices[i] = -1;
+          has_bits_indices[i] = static_cast<uint32>(-1);
         }
         type_info->has_bits_indices.reset(has_bits_indices);
       }

+ 1 - 1
src/google/protobuf/generated_message_reflection.h

@@ -169,7 +169,7 @@ struct ReflectionSchema {
 
   // Bit index within the bit array of hasbits.  Bit order is low-to-high.
   uint32 HasBitIndex(const FieldDescriptor* field) const {
-    if (has_bits_offset_ == -1) return -1;
+    if (has_bits_offset_ == -1) return static_cast<uint32>(-1);
     GOOGLE_DCHECK(HasHasbits());
     return has_bit_indices_[field->index()];
   }

+ 8 - 7
src/google/protobuf/generated_message_table_driven_lite.h

@@ -280,9 +280,13 @@ static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg,
           }
           utf8_string_data = field->Get();
         } break;
+        default:
+          PROTOBUF_ASSUME(false);
       }
       break;
     }
+    default:
+      PROTOBUF_ASSUME(false);
   }
 
   if (kValidateUtf8) {
@@ -322,6 +326,8 @@ inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input,
         SetOneofField(msg, presence, presence_index, offset, field_number,
                       value);
         break;
+      default:
+        PROTOBUF_ASSUME(false);
     }
   } else {
     UnknownFieldHandler::Varint(msg, table, tag, value);
@@ -406,9 +412,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg,
     const unsigned char processing_type = data->processing_type;
 
     if (data->normal_wiretype == static_cast<unsigned char>(wire_type)) {
-      // TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate
-      // the bounds check on processing_type.
-
       switch (processing_type) {
 #define HANDLE_TYPE(TYPE, CPPTYPE)                                             \
   case (WireFormatLite::TYPE_##TYPE): {                                        \
@@ -739,7 +742,7 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg,
           return true;
         }
         default:
-          break;
+          PROTOBUF_ASSUME(false);
       }
     } else if (data->packed_wiretype == static_cast<unsigned char>(wire_type)) {
       // Non-packable fields have their packed_wiretype masked with
@@ -751,8 +754,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg,
       GOOGLE_DCHECK_NE(TYPE_BYTES_INLINED | kRepeatedMask, processing_type);
       GOOGLE_DCHECK_NE(TYPE_STRING_INLINED | kRepeatedMask, processing_type);
 
-      // TODO(ckennelly): Use a computed goto on GCC/LLVM.
-      //
       // Mask out kRepeatedMask bit, allowing the jump table to be smaller.
       switch (static_cast<WireFormatLite::FieldType>(processing_type ^
                                                      kRepeatedMask)) {
@@ -825,7 +826,7 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg,
           GOOGLE_DCHECK(false);
           return false;
         default:
-          break;
+          PROTOBUF_ASSUME(false);
       }
     } else {
       if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {

+ 9 - 0
src/google/protobuf/stubs/statusor.h

@@ -153,6 +153,7 @@ class StatusOr {
   // If you need to initialize a T object from the stored value,
   // ConsumeValueOrDie() may be more efficient.
   const T& ValueOrDie() const;
+  const T& value () const;
 
  private:
   Status status_;
@@ -254,6 +255,14 @@ inline const T& StatusOr<T>::ValueOrDie() const {
   }
   return value_;
 }
+
+template<typename T>
+inline const T& StatusOr<T>::value() const {
+  if (!status_.ok()) {
+    internal::StatusOrHelper::Crash(status_);
+  }
+  return value_;
+}
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google

+ 2 - 2
src/google/protobuf/util/internal/datapiece.cc

@@ -173,7 +173,7 @@ StatusOr<double> DataPiece::ToDouble() const {
     if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
     if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
     StatusOr<double> value = StringToNumber<double>(safe_strtod);
-    if (value.ok() && !std::isfinite(value.ValueOrDie())) {
+    if (value.ok() && !std::isfinite(value.value())) {
       // safe_strtod converts out-of-range values to +inf/-inf, but we want
       // to report them as errors.
       return InvalidArgument(StrCat("\"", str_, "\""));
@@ -289,7 +289,7 @@ StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
     StatusOr<int32> int_value = ToInt32();
     if (int_value.ok()) {
       if (const google::protobuf::EnumValue* enum_value =
-              FindEnumValueByNumberOrNull(enum_type, int_value.ValueOrDie())) {
+              FindEnumValueByNumberOrNull(enum_type, int_value.value())) {
         return enum_value->number();
       }
     }

+ 5 - 5
src/google/protobuf/util/internal/default_value_objectwriter.cc

@@ -52,7 +52,7 @@ T ConvertTo(StringPiece value,
             StatusOr<T> (DataPiece::*converter_fn)() const, T default_value) {
   if (value.empty()) return default_value;
   StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
-  return result.ok() ? result.ValueOrDie() : default_value;
+  return result.ok() ? result.value() : default_value;
 }
 }  // namespace
 
@@ -290,7 +290,7 @@ const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
     if (!sub_type.ok()) {
       GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'.";
     } else {
-      return sub_type.ValueOrDie();
+      return sub_type.value();
     }
     break;
   }
@@ -354,7 +354,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
         // "field" is of an unknown type.
         GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'.";
       } else {
-        const google::protobuf::Type* found_type = found_result.ValueOrDie();
+        const google::protobuf::Type* found_type = found_result.value();
         is_map = IsMap(field, *found_type);
 
         if (!is_map) {
@@ -587,7 +587,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
       name == "@type") {
     util::StatusOr<std::string> data_string = data.ToString();
     if (data_string.ok()) {
-      const std::string& string_value = data_string.ValueOrDie();
+      const std::string& string_value = data_string.value();
       // If the type of current_ is "Any" and its "@type" field is being set
       // here, sets the type of current_ to be the type specified by the
       // "@type".
@@ -596,7 +596,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
       if (!found_type.ok()) {
         GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
       } else {
-        current_->set_type(found_type.ValueOrDie());
+        current_->set_type(found_type.value());
       }
       current_->set_is_any(true);
       // If the "@type" field is placed after other fields, we should populate

+ 8 - 8
src/google/protobuf/util/internal/object_writer.cc

@@ -42,35 +42,35 @@ void ObjectWriter::RenderDataPieceTo(const DataPiece& data,
                                      StringPiece name, ObjectWriter* ow) {
   switch (data.type()) {
     case DataPiece::TYPE_INT32: {
-      ow->RenderInt32(name, data.ToInt32().ValueOrDie());
+      ow->RenderInt32(name, data.ToInt32().value());
       break;
     }
     case DataPiece::TYPE_INT64: {
-      ow->RenderInt64(name, data.ToInt64().ValueOrDie());
+      ow->RenderInt64(name, data.ToInt64().value());
       break;
     }
     case DataPiece::TYPE_UINT32: {
-      ow->RenderUint32(name, data.ToUint32().ValueOrDie());
+      ow->RenderUint32(name, data.ToUint32().value());
       break;
     }
     case DataPiece::TYPE_UINT64: {
-      ow->RenderUint64(name, data.ToUint64().ValueOrDie());
+      ow->RenderUint64(name, data.ToUint64().value());
       break;
     }
     case DataPiece::TYPE_DOUBLE: {
-      ow->RenderDouble(name, data.ToDouble().ValueOrDie());
+      ow->RenderDouble(name, data.ToDouble().value());
       break;
     }
     case DataPiece::TYPE_FLOAT: {
-      ow->RenderFloat(name, data.ToFloat().ValueOrDie());
+      ow->RenderFloat(name, data.ToFloat().value());
       break;
     }
     case DataPiece::TYPE_BOOL: {
-      ow->RenderBool(name, data.ToBool().ValueOrDie());
+      ow->RenderBool(name, data.ToBool().value());
       break;
     }
     case DataPiece::TYPE_STRING: {
-      ow->RenderString(name, data.ToString().ValueOrDie());
+      ow->RenderString(name, data.ToString().value());
       break;
     }
     case DataPiece::TYPE_BYTES: {

+ 17 - 17
src/google/protobuf/util/internal/proto_writer.cc

@@ -124,7 +124,7 @@ inline Status WriteInt32(int field_number, const DataPiece& data,
                          CodedOutputStream* stream) {
   StatusOr<int32> i32 = data.ToInt32();
   if (i32.ok()) {
-    WireFormatLite::WriteInt32(field_number, i32.ValueOrDie(), stream);
+    WireFormatLite::WriteInt32(field_number, i32.value(), stream);
   }
   return i32.status();
 }
@@ -134,7 +134,7 @@ inline Status WriteSFixed32(int field_number, const DataPiece& data,
                             CodedOutputStream* stream) {
   StatusOr<int32> i32 = data.ToInt32();
   if (i32.ok()) {
-    WireFormatLite::WriteSFixed32(field_number, i32.ValueOrDie(), stream);
+    WireFormatLite::WriteSFixed32(field_number, i32.value(), stream);
   }
   return i32.status();
 }
@@ -144,7 +144,7 @@ inline Status WriteSInt32(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<int32> i32 = data.ToInt32();
   if (i32.ok()) {
-    WireFormatLite::WriteSInt32(field_number, i32.ValueOrDie(), stream);
+    WireFormatLite::WriteSInt32(field_number, i32.value(), stream);
   }
   return i32.status();
 }
@@ -154,7 +154,7 @@ inline Status WriteFixed32(int field_number, const DataPiece& data,
                            CodedOutputStream* stream) {
   StatusOr<uint32> u32 = data.ToUint32();
   if (u32.ok()) {
-    WireFormatLite::WriteFixed32(field_number, u32.ValueOrDie(), stream);
+    WireFormatLite::WriteFixed32(field_number, u32.value(), stream);
   }
   return u32.status();
 }
@@ -164,7 +164,7 @@ inline Status WriteUInt32(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<uint32> u32 = data.ToUint32();
   if (u32.ok()) {
-    WireFormatLite::WriteUInt32(field_number, u32.ValueOrDie(), stream);
+    WireFormatLite::WriteUInt32(field_number, u32.value(), stream);
   }
   return u32.status();
 }
@@ -174,7 +174,7 @@ inline Status WriteInt64(int field_number, const DataPiece& data,
                          CodedOutputStream* stream) {
   StatusOr<int64> i64 = data.ToInt64();
   if (i64.ok()) {
-    WireFormatLite::WriteInt64(field_number, i64.ValueOrDie(), stream);
+    WireFormatLite::WriteInt64(field_number, i64.value(), stream);
   }
   return i64.status();
 }
@@ -184,7 +184,7 @@ inline Status WriteSFixed64(int field_number, const DataPiece& data,
                             CodedOutputStream* stream) {
   StatusOr<int64> i64 = data.ToInt64();
   if (i64.ok()) {
-    WireFormatLite::WriteSFixed64(field_number, i64.ValueOrDie(), stream);
+    WireFormatLite::WriteSFixed64(field_number, i64.value(), stream);
   }
   return i64.status();
 }
@@ -194,7 +194,7 @@ inline Status WriteSInt64(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<int64> i64 = data.ToInt64();
   if (i64.ok()) {
-    WireFormatLite::WriteSInt64(field_number, i64.ValueOrDie(), stream);
+    WireFormatLite::WriteSInt64(field_number, i64.value(), stream);
   }
   return i64.status();
 }
@@ -204,7 +204,7 @@ inline Status WriteFixed64(int field_number, const DataPiece& data,
                            CodedOutputStream* stream) {
   StatusOr<uint64> u64 = data.ToUint64();
   if (u64.ok()) {
-    WireFormatLite::WriteFixed64(field_number, u64.ValueOrDie(), stream);
+    WireFormatLite::WriteFixed64(field_number, u64.value(), stream);
   }
   return u64.status();
 }
@@ -214,7 +214,7 @@ inline Status WriteUInt64(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<uint64> u64 = data.ToUint64();
   if (u64.ok()) {
-    WireFormatLite::WriteUInt64(field_number, u64.ValueOrDie(), stream);
+    WireFormatLite::WriteUInt64(field_number, u64.value(), stream);
   }
   return u64.status();
 }
@@ -224,7 +224,7 @@ inline Status WriteDouble(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<double> d = data.ToDouble();
   if (d.ok()) {
-    WireFormatLite::WriteDouble(field_number, d.ValueOrDie(), stream);
+    WireFormatLite::WriteDouble(field_number, d.value(), stream);
   }
   return d.status();
 }
@@ -234,7 +234,7 @@ inline Status WriteFloat(int field_number, const DataPiece& data,
                          CodedOutputStream* stream) {
   StatusOr<float> f = data.ToFloat();
   if (f.ok()) {
-    WireFormatLite::WriteFloat(field_number, f.ValueOrDie(), stream);
+    WireFormatLite::WriteFloat(field_number, f.value(), stream);
   }
   return f.status();
 }
@@ -244,7 +244,7 @@ inline Status WriteBool(int field_number, const DataPiece& data,
                         CodedOutputStream* stream) {
   StatusOr<bool> b = data.ToBool();
   if (b.ok()) {
-    WireFormatLite::WriteBool(field_number, b.ValueOrDie(), stream);
+    WireFormatLite::WriteBool(field_number, b.value(), stream);
   }
   return b.status();
 }
@@ -264,7 +264,7 @@ inline Status WriteString(int field_number, const DataPiece& data,
                           CodedOutputStream* stream) {
   StatusOr<std::string> s = data.ToString();
   if (s.ok()) {
-    WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream);
+    WireFormatLite::WriteString(field_number, s.value(), stream);
   }
   return s.status();
 }
@@ -602,7 +602,7 @@ Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data,
                                 case_insensitive_enum_parsing,
                                 ignore_unknown_values, &is_unknown_enum_value);
   if (e.ok() && !is_unknown_enum_value) {
-    WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream);
+    WireFormatLite::WriteEnum(field_number, e.value(), stream);
   }
   return e.status();
 }
@@ -704,8 +704,8 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField(
       break;
     }
     default:  // TYPE_GROUP or TYPE_MESSAGE
-      status = Status(util::error::INVALID_ARGUMENT,
-                      data.ToString().ValueOrDie());
+      status =
+          Status(util::error::INVALID_ARGUMENT, data.ToString().value());
   }
 
   if (!status.ok()) {

+ 1 - 1
src/google/protobuf/util/internal/protostream_objectsource.cc

@@ -647,7 +647,7 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os,
                         resolved_type.status().message());
   }
   // nested_type cannot be null at this time.
-  const google::protobuf::Type* nested_type = resolved_type.ValueOrDie();
+  const google::protobuf::Type* nested_type = resolved_type.value();
 
   io::ArrayInputStream zero_copy_stream(value.data(), value.size());
   io::CodedInputStream in_stream(&zero_copy_stream);

+ 8 - 10
src/google/protobuf/util/internal/protostream_objectwriter.cc

@@ -334,7 +334,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
       invalid_ = true;
       return;
     }
-    type_url_ = s.ValueOrDie();
+    type_url_ = s.value();
   }
   // Resolve the type url, and report an error if we failed to resolve it.
   StatusOr<const google::protobuf::Type*> resolved_type =
@@ -345,7 +345,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
     return;
   }
   // At this point, type is never null.
-  const google::protobuf::Type* type = resolved_type.ValueOrDie();
+  const google::protobuf::Type* type = resolved_type.value();
 
   well_known_type_render_ = FindTypeRenderer(type_url_);
   if (well_known_type_render_ != nullptr ||
@@ -897,7 +897,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
-              DataPiece(SimpleDtoa(int_value.ValueOrDie()), true));
+              DataPiece(SimpleDtoa(int_value.value()), true));
           return Status();
         }
       }
@@ -910,7 +910,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
-              DataPiece(SimpleDtoa(int_value.ValueOrDie()), true));
+              DataPiece(SimpleDtoa(int_value.value()), true));
           return Status();
         }
       }
@@ -924,8 +924,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         StatusOr<int64> int_value = data.ToInt64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(StrCat(int_value.ValueOrDie()), true));
+              "string_value", DataPiece(StrCat(int_value.value()), true));
           return Status();
         }
       }
@@ -939,8 +938,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         StatusOr<uint64> int_value = data.ToUint64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(StrCat(int_value.ValueOrDie()), true));
+              "string_value", DataPiece(StrCat(int_value.value()), true));
           return Status();
         }
       }
@@ -953,7 +951,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         if (float_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
-              DataPiece(SimpleDtoa(float_value.ValueOrDie()), true));
+              DataPiece(SimpleDtoa(float_value.value()), true));
           return Status();
         }
       }
@@ -966,7 +964,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
         if (double_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
-              DataPiece(SimpleDtoa(double_value.ValueOrDie()), true));
+              DataPiece(SimpleDtoa(double_value.value()), true));
           return Status();
         }
       }

+ 4 - 4
src/google/protobuf/util/internal/type_info.cc

@@ -81,7 +81,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
   const google::protobuf::Type* GetTypeByTypeUrl(
       StringPiece type_url) const override {
     StatusOrType result = ResolveTypeUrl(type_url);
-    return result.ok() ? result.ValueOrDie() : NULL;
+    return result.ok() ? result.value() : NULL;
   }
 
   const google::protobuf::Enum* GetEnumByTypeUrl(
@@ -89,7 +89,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
     std::map<StringPiece, StatusOrEnum>::iterator it =
         cached_enums_.find(type_url);
     if (it != cached_enums_.end()) {
-      return it->second.ok() ? it->second.ValueOrDie() : NULL;
+      return it->second.ok() ? it->second.value() : NULL;
     }
     // Stores the string value so it can be referenced using StringPiece in the
     // cached_enums_ map.
@@ -102,7 +102,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
     StatusOrEnum result =
         status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status);
     cached_enums_[string_type_url] = result;
-    return result.ok() ? result.ValueOrDie() : NULL;
+    return result.ok() ? result.value() : NULL;
   }
 
   const google::protobuf::Field* FindField(
@@ -134,7 +134,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
              cached_types->begin();
          it != cached_types->end(); ++it) {
       if (it->second.ok()) {
-        delete it->second.ValueOrDie();
+        delete it->second.value();
       }
     }
   }