Merge pull request #8354 from Yannic/refactor_status

[C++] Refactor util::Status
diff --git a/BUILD b/BUILD
index 1124321..07ee629 100644
--- a/BUILD
+++ b/BUILD
@@ -14,38 +14,6 @@
 # build configuration
 ################################################################################
 
-# TODO(yannic): Remove in 3.14.0.
-string_flag(
-    name = "incompatible_use_com_google_googletest",
-    build_setting_default = "true",
-    values = ["true", "false"]
-)
-
-config_setting(
-    name = "use_com_google_googletest",
-    flag_values = {
-        "//:incompatible_use_com_google_googletest": "true"
-    },
-)
-
-GTEST = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest",
-    ],
-    "//conditions:default": [
-        "//external:gtest",
-    ],
-})
-
-GTEST_MAIN = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest_main",
-    ],
-    "//conditions:default": [
-        "//external:gtest_main",
-    ],
-})
-
 ################################################################################
 # ZLIB configuration
 ################################################################################
@@ -571,6 +539,7 @@
 
 cc_binary(
     name = "test_plugin",
+    testonly = True,
     srcs = [
         # AUTOGEN(test_plugin_srcs)
         "src/google/protobuf/compiler/mock_code_generator.cc",
@@ -580,7 +549,8 @@
     deps = [
         ":protobuf",
         ":protoc_lib",
-    ] + GTEST,
+        "@com_google_googletest//:gtest",
+    ],
 )
 
 cc_test(
@@ -592,7 +562,9 @@
     ],
     deps = [
         ":protobuf_lite",
-    ] + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
 )
 
 cc_test(
@@ -695,7 +667,9 @@
         ":cc_test_protos",
         ":protobuf",
         ":protoc_lib",
-    ] + PROTOBUF_DEPS + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ] + PROTOBUF_DEPS,
 )
 
 ################################################################################
diff --git a/WORKSPACE b/WORKSPACE
index 5a767a9..d9ed7c8 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -29,18 +29,6 @@
     actual = "//util/python:python_headers",
 )
 
-# TODO(yannic): Remove in 3.14.0.
-bind(
-    name = "gtest",
-    actual = "@com_google_googletest//:gtest",
-)
-
-# TODO(yannic): Remove in 3.14.0.
-bind(
-    name = "gtest_main",
-    actual = "@com_google_googletest//:gtest_main",
-)
-
 jvm_maven_import_external(
     name = "guava_maven",
     artifact = "com.google.guava:guava:18.0",
diff --git a/docs/options.md b/docs/options.md
index 907fe5a..79a085e 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -268,3 +268,11 @@
 1. Protoc-gen-sanitize
    * Website: https://github.com/Intrinsec/protoc-gen-sanitize
    * Extension: 1102-1106
+
+1. Coach Client Connect (planned release in March 2021)
+   * Website: https://www.coachclientconnect.com
+   * Extension: 1107
+
+1. Kratos API Errors
+   * Website: https://go-kratos.dev
+   * Extension: 1108
diff --git a/docs/third_party.md b/docs/third_party.md
index 7799e30..6b0e271 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -101,7 +101,6 @@
 * Solidity: https://github.com/celer-network/pb3-gen-sol
 * Swift: https://github.com/alexeyxo/protobuf-swift
 * Swift: https://github.com/apple/swift-protobuf/
-* Typescript: https://github.com/y3llowcake/protoc-gen-ts
 * Vala: https://launchpad.net/protobuf-vala
 * Visual Basic: http://code.google.com/p/protobuf-net/
 
diff --git a/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh
index efc3ee6..44a95aa 100755
--- a/kokoro/release/protoc/linux/build.sh
+++ b/kokoro/release/protoc/linux/build.sh
@@ -23,7 +23,7 @@
 protoc-artifacts/build-protoc.sh linux ppcle_64 protoc
 
 sudo apt install -y g++-s390x-linux-gnu
-protoc-artifacts/build-protoc.sh linux s390x protoc
+protoc-artifacts/build-protoc.sh linux s390_64 protoc
 
 # Use docker image to build linux artifacts.
 DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 2c45fef..1706ddc 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -123,7 +123,7 @@
           protoc.exe
         + ppcle_64
           protoc.exe
-        + s390x
+        + s390_64
           protoc.exe
       + osx
         + x86_64
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 7f65d37..4602842 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -93,7 +93,7 @@
         assertEq $format "elf64-x86-64" $LINENO
       elif [[ "$ARCH" == aarch_64 ]]; then
         assertEq $format "elf64-little" $LINENO
-      elif [[ "$ARCH" == s390x ]]; then
+      elif [[ "$ARCH" == s390_64 ]]; then
 	if [[ $host_machine == s390x ]];then
 	  assertEq $format "elf64-s390" $LINENO
 	else
@@ -149,7 +149,7 @@
       white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
     elif [[ "$ARCH" == x86_64 ]]; then
       white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       if [[ $host_machine != s390x ]];then
         dump_cmd='objdump -p '"$1"' | grep NEEDED'
       fi
@@ -226,7 +226,7 @@
     elif [[ "$ARCH" == ppcle_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=powerpc64le-linux-gnu"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=s390x-linux-gnu"
     else
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
index 2a25d3c..7d1923e 100755
--- a/protoc-artifacts/build-zip.sh
+++ b/protoc-artifacts/build-zip.sh
@@ -21,7 +21,7 @@
   dist/<TARGET>-<VERSION_NUMBER>-linux-x86_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-aarch_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-ppcle_64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-linux-s390x.zip
+  dist/<TARGET>-<VERSION_NUMBER>-linux-s390_64.zip
 EOF
   exit 1
 fi
@@ -38,7 +38,7 @@
   linux-x86_64.zip linux-x86_64.exe \
   linux-aarch_64.zip linux-aarch_64.exe \
   linux-ppcle_64.zip linux-ppcle_64.exe \
-  linux-s390x.zip linux-s390x.exe \
+  linux-s390_64.zip linux-s390_64.exe \
 )
 
 # List of all well-known types to be included.
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index ba9eaf8..e46c902 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -81,8 +81,8 @@
                   <type>exe</type>
 	  	</artifact>
                 <artifact>
-                  <file>${basedir}/target/linux/s390x/protoc.exe</file>
-                  <classifier>linux-s390x</classifier>
+                  <file>${basedir}/target/linux/s390_64/protoc.exe</file>
+                  <classifier>linux-s390_64</classifier>
                   <type>exe</type>
                 </artifact>
               </artifacts>
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index c27f30a..c9eecee 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -37,7 +37,7 @@
 #include "message.h"
 #include "repeated_field.h"
 
-VALUE cError;
+VALUE cParseError;
 VALUE cTypeError;
 
 const upb_fielddef* map_field_key(const upb_fielddef* field) {
@@ -368,8 +368,10 @@
   Map_register(protobuf);
   Message_register(protobuf);
 
-  cError = rb_const_get(protobuf, rb_intern("Error"));
+  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+  rb_gc_register_mark_object(cParseError);
   cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
+  rb_gc_register_mark_object(cTypeError);
 
   rb_define_singleton_method(protobuf, "discard_unknown",
                              Google_Protobuf_discard_unknown, 1);
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 28b0bfa..b0b2963 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -288,7 +288,7 @@
       public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL)
-      : format_(format), tree_(tree), found_errors_(false) {}
+      : format_(format), tree_(tree), found_errors_(false), found_warnings_(false) {}
   ~ErrorPrinter() {}
 
   // implements MultiFileErrorCollector ------------------------------
@@ -300,6 +300,7 @@
 
   void AddWarning(const std::string& filename, int line, int column,
                   const std::string& message) {
+    found_warnings_ = true;
     AddErrorOrWarning(filename, line, column, message, "warning", std::clog);
   }
 
@@ -327,6 +328,8 @@
 
   bool FoundErrors() const { return found_errors_; }
 
+  bool FoundWarnings() const { return found_warnings_; }
+
  private:
   void AddErrorOrWarning(const std::string& filename, int line, int column,
                          const std::string& message, const std::string& type,
@@ -365,6 +368,7 @@
   const ErrorFormat format_;
   DiskSourceTree* tree_;
   bool found_errors_;
+  bool found_warnings_;
 };
 
 // -------------------------------------------------------------------
@@ -1117,7 +1121,8 @@
     }
   }
 
-  if (error_collector->FoundErrors()) {
+  if (error_collector->FoundErrors() ||
+      (fatal_warnings_ && error_collector->FoundWarnings())) {
     return 1;
   }
 
@@ -1630,7 +1635,8 @@
       *name == "--version" || *name == "--decode_raw" ||
       *name == "--print_free_field_numbers" ||
       *name == "--experimental_allow_proto3_optional" ||
-      *name == "--deterministic_output") {
+      *name == "--deterministic_output" ||
+      *name == "--fatal_warnings") {
     // HACK:  These are the only flags that don't take a value.
     //   They probably should not be hard-coded like this but for now it's
     //   not worth doing better.
@@ -1883,6 +1889,12 @@
       return PARSE_ARGUMENT_FAIL;
     }
 
+  } else if (name == "--fatal_warnings") {
+    if (fatal_warnings_) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    fatal_warnings_ = true;
   } else if (name == "--plugin") {
     if (plugin_prefix_.empty()) {
       std::cerr << "This compiler does not support plugins." << std::endl;
@@ -2042,6 +2054,10 @@
   --error_format=FORMAT       Set the format in which to print errors.
                               FORMAT may be 'gcc' (the default) or 'msvs'
                               (Microsoft Visual Studio format).
+  --fatal_warnings            Make warnings be fatal (similar to -Werr in
+                              gcc). This flag will make protoc return
+                              with a non-zero exit code if any warnings
+                              are generated.
   --print_free_field_numbers  Print the free field numbers of the messages
                               defined in the given proto files. Groups share
                               the same field number space with the parent
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 4ff2471..5fdc04b 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -392,6 +392,9 @@
 
   ErrorFormat error_format_ = ERROR_FORMAT_GCC;
 
+  // True if we should treat warnings as errors that fail the compilation.
+  bool fatal_warnings_ = false;
+
   std::vector<std::pair<std::string, std::string> >
       proto_path_;                        // Search path for proto files.
   std::vector<std::string> input_files_;  // Names of the input proto files.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 74dc9bf..2ca8608 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -157,6 +157,11 @@
   void ExpectCapturedStdoutSubstringWithZeroReturnCode(
       const std::string& expected_substring);
 
+  // Checks that Run() returned zero and the stderr contains the given
+  // substring.
+  void ExpectCapturedStderrSubstringWithZeroReturnCode(
+      const std::string& expected_substring);
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
   // does not fail otherwise.
@@ -426,8 +431,8 @@
 
 void CommandLineInterfaceTest::ExpectWarningSubstring(
     const std::string& expected_substring) {
-  EXPECT_EQ(0, return_code_);
   EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+  EXPECT_EQ(0, return_code_);
 }
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -515,6 +520,13 @@
                       captured_stdout_);
 }
 
+void CommandLineInterfaceTest::ExpectCapturedStderrSubstringWithZeroReturnCode(
+    const std::string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring,
+                      error_text_);
+}
+
 void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename,
                                                  const std::string& content) {
   std::string path = temp_directory_ + "/" + filename;
@@ -2303,7 +2315,7 @@
 }
 
 TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
-  // Test --error_format=msvs
+  // Test invalid --error_format
 
   CreateTempFile("foo.proto",
                  "syntax = \"proto2\";\n"
@@ -2315,6 +2327,26 @@
   ExpectErrorText("Unknown error format: invalid\n");
 }
 
+TEST_F(CommandLineInterfaceTest, Warnings) {
+  // Test --fatal_warnings.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+    "--proto_path=$tmpdir foo.proto");
+  ExpectCapturedStderrSubstringWithZeroReturnCode(
+    "foo.proto:2:1: warning: Import bar.proto is unused.");
+
+  Run("protocol_compiler --test_out=$tmpdir --fatal_warnings "
+    "--proto_path=$tmpdir foo.proto");
+  ExpectErrorSubstring(
+    "foo.proto:2:1: warning: Import bar.proto is unused.");
+}
+
 // -------------------------------------------------------------------
 // Flag parsing tests