Change ParseAbseilFlagsOnly function to include handling of usage flags and exit on syntax errors.

PiperOrigin-RevId: 518198160
Change-Id: Ib4fe53e0b0b371472b6b9473aeb84779953b6a38
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index 145e591..e435204 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -21,6 +21,7 @@
 
 #include "absl/base/config.h"
 #include "absl/flags/declare.h"
+#include "absl/flags/internal/usage.h"
 #include "absl/strings/string_view.h"
 
 ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
@@ -40,8 +41,8 @@
 };
 
 std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
-                                        UsageFlagsAction usage_flag_act,
-                                        OnUndefinedFlag on_undef_flag);
+                                        UsageFlagsAction usage_flag_action,
+                                        OnUndefinedFlag undef_flag_action);
 
 // --------------------------------------------------------------------
 // Inspect original command line
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index e948148..6a56fce 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -18,6 +18,7 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <cstdlib>
 #include <functional>
 #include <iterator>
 #include <map>
@@ -354,8 +355,8 @@
 // --------------------------------------------------------------------
 // Checks all the 'usage' command line flags to see if any have been set.
 // If so, handles them appropriately.
-int HandleUsageFlags(std::ostream& out,
-                     absl::string_view program_usage_message) {
+HelpMode HandleUsageFlags(std::ostream& out,
+                          absl::string_view program_usage_message) {
   switch (GetFlagsHelpMode()) {
     case HelpMode::kNone:
       break;
@@ -363,25 +364,24 @@
       flags_internal::FlagsHelpImpl(
           out, flags_internal::GetUsageConfig().contains_help_flags,
           GetFlagsHelpFormat(), program_usage_message);
-      return 1;
+      break;
 
     case HelpMode::kShort:
       flags_internal::FlagsHelpImpl(
           out, flags_internal::GetUsageConfig().contains_helpshort_flags,
           GetFlagsHelpFormat(), program_usage_message);
-      return 1;
+      break;
 
     case HelpMode::kFull:
       flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
                                 program_usage_message);
-      return 1;
+      break;
 
     case HelpMode::kPackage:
       flags_internal::FlagsHelpImpl(
           out, flags_internal::GetUsageConfig().contains_helppackage_flags,
           GetFlagsHelpFormat(), program_usage_message);
-
-      return 1;
+      break;
 
     case HelpMode::kMatch: {
       std::string substr = GetFlagsHelpMatchSubstr();
@@ -400,20 +400,19 @@
         flags_internal::FlagsHelpImpl(
             out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
       }
-
-      return 1;
+      break;
     }
     case HelpMode::kVersion:
       if (flags_internal::GetUsageConfig().version_string)
         out << flags_internal::GetUsageConfig().version_string();
       // Unlike help, we may be asking for version in a script, so return 0
-      return 0;
+      break;
 
     case HelpMode::kOnlyCheckArgs:
-      return 0;
+      break;
   }
 
-  return -1;
+  return GetFlagsHelpMode();
 }
 
 // --------------------------------------------------------------------
@@ -521,6 +520,22 @@
   return false;
 }
 
+// --------------------------------------------------------------------
+
+void MaybeExit(HelpMode mode) {
+  switch (mode) {
+    case flags_internal::HelpMode::kNone:
+      return;
+    case flags_internal::HelpMode::kOnlyCheckArgs:
+    case flags_internal::HelpMode::kVersion:
+      std::exit(0);
+    default:  // For all the other modes we exit with 1
+      std::exit(1);
+  }
+}
+
+// --------------------------------------------------------------------
+
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index c0bcac5..a96cbf3 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -17,11 +17,11 @@
 #define ABSL_FLAGS_INTERNAL_USAGE_H_
 
 #include <iosfwd>
+#include <ostream>
 #include <string>
 
 #include "absl/base/config.h"
 #include "absl/flags/commandlineflag.h"
-#include "absl/flags/declare.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
@@ -36,6 +36,18 @@
   kHumanReadable,
 };
 
+// The kind of usage help requested.
+enum class HelpMode {
+  kNone,
+  kImportant,
+  kShort,
+  kFull,
+  kPackage,
+  kMatch,
+  kVersion,
+  kOnlyCheckArgs
+};
+
 // Streams the help message describing `flag` to `out`.
 // The default value for `flag` is included in the output.
 void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
@@ -57,29 +69,19 @@
 
 // If any of the 'usage' related command line flags (listed on the bottom of
 // this file) has been set this routine produces corresponding help message in
-// the specified output stream and returns:
-//  0 - if "version" or "only_check_flags" flags were set and handled.
-//  1 - if some other 'usage' related flag was set and handled.
-// -1 - if no usage flags were set on a commmand line.
-// Non negative return values are expected to be used as an exit code for a
-// binary.
-int HandleUsageFlags(std::ostream& out,
-                     absl::string_view program_usage_message);
+// the specified output stream and returns HelpMode that was handled. Otherwise
+// it returns HelpMode::kNone.
+HelpMode HandleUsageFlags(std::ostream& out,
+                          absl::string_view program_usage_message);
+
+// --------------------------------------------------------------------
+// Encapsulates the logic of exiting the binary depending on handled help mode.
+
+void MaybeExit(HelpMode mode);
 
 // --------------------------------------------------------------------
 // Globals representing usage reporting flags
 
-enum class HelpMode {
-  kNone,
-  kImportant,
-  kShort,
-  kFull,
-  kPackage,
-  kMatch,
-  kVersion,
-  kOnlyCheckArgs
-};
-
 // Returns substring to filter help output (--help=substr argument)
 std::string GetFlagsHelpMatchSubstr();
 // Returns the requested help mode.
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index 209a7be..c3ab4a4 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -24,7 +24,6 @@
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/parse.h"
-#include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
 #include "absl/flags/reflection.h"
 #include "absl/flags/usage.h"
@@ -256,7 +255,8 @@
 
 TEST_F(UsageReportingTest, TestNoUsageFlags) {
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kNone);
 }
 
 // --------------------------------------------------------------------
@@ -265,7 +265,8 @@
   flags::SetFlagsHelpMode(flags::HelpMode::kShort);
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kShort);
   EXPECT_EQ(test_buf.str(),
             R"(usage_test: Custom usage message
 
@@ -298,7 +299,8 @@
   flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kImportant);
   EXPECT_EQ(test_buf.str(),
             R"(usage_test: Custom usage message
 
@@ -332,7 +334,8 @@
   flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kMatch);
   EXPECT_EQ(test_buf.str(),
             R"(usage_test: Custom usage message
 
@@ -356,7 +359,8 @@
   flags::SetFlagsHelpMatchSubstr("test_flag");
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kMatch);
   EXPECT_EQ(test_buf.str(),
             R"(usage_test: Custom usage message
 
@@ -389,7 +393,8 @@
   flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kPackage);
   EXPECT_EQ(test_buf.str(),
             R"(usage_test: Custom usage message
 
@@ -422,7 +427,8 @@
   flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kVersion);
 #ifndef NDEBUG
   EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n");
 #else
@@ -436,7 +442,8 @@
   flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
 
   std::stringstream test_buf;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+            flags::HelpMode::kOnlyCheckArgs);
   EXPECT_EQ(test_buf.str(), "");
 }
 
@@ -447,7 +454,8 @@
   flags::SetFlagsHelpMatchSubstr("/bla-bla.");
 
   std::stringstream test_buf_01;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage),
+            flags::HelpMode::kMatch);
   EXPECT_EQ(test_buf_01.str(),
             R"(usage_test: Custom usage message
 
@@ -461,7 +469,8 @@
   flags::SetFlagsHelpMatchSubstr("/usage_test.");
 
   std::stringstream test_buf_02;
-  EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage),
+            flags::HelpMode::kMatch);
   EXPECT_EQ(test_buf_02.str(),
             R"(usage_test: Custom usage message
 
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 236d31b..1f63906 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -666,7 +666,7 @@
   const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
   auto undefok = absl::GetFlag(FLAGS_undefok);
   BestHints best_hints(static_cast<uint8_t>(maxCutoff));
-  absl::flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
+  flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
     if (best_hints.hints.size() >= kMaxHints) return;
     uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
         flag, f.Name(), best_hints.best_distance);
@@ -697,51 +697,42 @@
   std::vector<char*> positional_args;
   std::vector<UnrecognizedFlag> unrecognized_flags;
 
-  bool parse_successful = absl::ParseAbseilFlagsOnly(
-      argc, argv, positional_args, unrecognized_flags);
+  auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
+      argc, argv, positional_args, unrecognized_flags, usage_flag_action);
 
   if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) {
-    if (parse_successful &&
-        undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
-      if (!unrecognized_flags.empty()) { parse_successful = false; }
-    }
-
     flags_internal::ReportUnrecognizedFlags(
         unrecognized_flags,
-        !parse_successful &&
-            (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
-  }
+        (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
 
-#if ABSL_FLAGS_STRIP_NAMES
-  if (!parse_successful) {
-    ReportUsageError("NOTE: command line flags are disabled in this build",
-                     true);
-  }
-#endif
-
-  if (!parse_successful) {
-    HandleUsageFlags(std::cout, ProgramUsageMessage());
-    std::exit(1);
-  }
-
-  if (usage_flag_action == UsageFlagsAction::kHandleUsage) {
-    int exit_code = HandleUsageFlags(std::cout, ProgramUsageMessage());
-
-    if (exit_code != -1) {
-      std::exit(exit_code);
+    if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
+      if (!unrecognized_flags.empty()) { std::exit(1); }
     }
   }
 
+  flags_internal::MaybeExit(help_mode);
+
   return positional_args;
 }
 
 // --------------------------------------------------------------------
 
-}  // namespace flags_internal
-
-bool ParseAbseilFlagsOnly(int argc, char* argv[],
-                          std::vector<char*>& positional_args,
-                          std::vector<UnrecognizedFlag>& unrecognized_flags) {
+// This function handles all Abseil Flags and built-in usage flags and, if any
+// help mode was handled, it returns that help mode. The caller of this function
+// can decide to exit based on the returned help mode.
+// The caller may decide to handle unrecognized positional arguments and
+// unrecognized flags first before exiting.
+//
+// Returns:
+// * HelpMode::kFull if parsing errors were detected in recognized arguments
+// * The HelpMode that was handled in case when `usage_flag_action` is
+//   UsageFlagsAction::kHandleUsage and a usage flag was specified on the
+//   commandline
+// * Otherwise it returns HelpMode::kNone
+HelpMode ParseAbseilFlagsOnlyImpl(
+    int argc, char* argv[], std::vector<char*>& positional_args,
+    std::vector<UnrecognizedFlag>& unrecognized_flags,
+    UsageFlagsAction usage_flag_action) {
   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
 
   using flags_internal::ArgsList;
@@ -771,9 +762,9 @@
     specified_flags->clear();
   }
 
-  // Iterate through the list of the input arguments. First level are arguments
-  // originated from argc/argv. Following levels are arguments originated from
-  // recursive parsing of flagfile(s).
+  // Iterate through the list of the input arguments. First level are
+  // arguments originated from argc/argv. Following levels are arguments
+  // originated from recursive parsing of flagfile(s).
   bool success = true;
   while (!input_args.empty()) {
     // First we process the built-in generator flags.
@@ -793,8 +784,8 @@
     }
 
     // Handle the next argument in the current list. If the stack of argument
-    // lists contains only one element - we are processing an argument from the
-    // original argv.
+    // lists contains only one element - we are processing an argument from
+    // the original argv.
     absl::string_view arg(curr_list.Front());
     bool arg_from_argv = input_args.size() == 1;
 
@@ -895,7 +886,33 @@
 
   std::swap(unrecognized_flags, filtered);
 
-  return success;
+  if (!success) {
+#if ABSL_FLAGS_STRIP_NAMES
+    flags_internal::ReportUsageError(
+        "NOTE: command line flags are disabled in this build", true);
+#else
+    flags_internal::HandleUsageFlags(std::cout, ProgramUsageMessage());
+#endif
+    return HelpMode::kFull;  // We just need to make sure the exit with
+                             // code 1.
+  }
+
+  return usage_flag_action == UsageFlagsAction::kHandleUsage
+             ? flags_internal::HandleUsageFlags(std::cout,
+                                                ProgramUsageMessage())
+             : HelpMode::kNone;
+}
+
+}  // namespace flags_internal
+
+void ParseAbseilFlagsOnly(int argc, char* argv[],
+                          std::vector<char*>& positional_args,
+                          std::vector<UnrecognizedFlag>& unrecognized_flags) {
+  auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
+      argc, argv, positional_args, unrecognized_flags,
+      flags_internal::UsageFlagsAction::kHandleUsage);
+
+  flags_internal::MaybeExit(help_mode);
 }
 
 // --------------------------------------------------------------------
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
index 9732727..f2a5cb1 100644
--- a/absl/flags/parse.h
+++ b/absl/flags/parse.h
@@ -28,7 +28,6 @@
 
 #include "absl/base/config.h"
 #include "absl/flags/internal/parse.h"
-#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -52,6 +51,15 @@
   return lhs.source == rhs.source && lhs.flag_name == rhs.flag_name;
 }
 
+namespace flags_internal {
+
+HelpMode ParseAbseilFlagsOnlyImpl(
+    int argc, char* argv[], std::vector<char*>& positional_args,
+    std::vector<UnrecognizedFlag>& unrecognized_flags,
+    UsageFlagsAction usage_flag_action);
+
+}  // namespace flags_internal
+
 // ParseAbseilFlagsOnly()
 //
 // Parses a list of command-line arguments, passed in the `argc` and `argv[]`
@@ -69,7 +77,11 @@
 //     treated as positional arguments regardless of their syntax.
 //
 // All of the deduced Abseil Flag arguments are then parsed into their
-// corresponding flag values.
+// corresponding flag values. If any syntax errors are found in these arguments,
+// the binary exits with code 1.
+//
+// This function also handles Abseil Flags built-in usage flags (e.g. --help)
+// if any were present on the command line.
 //
 // All the remaining positional arguments including original program name
 // (argv[0]) are are returned in the `positional_args` output parameter.
@@ -81,10 +93,7 @@
 // that appear within `undefok` will therefore be ignored and not included in
 // the `unrecognized_flag` output parameter.
 //
-// This function returns true if no syntax errors were found on the command line
-// or in the referenced flag files. Unrecognized flags do not cause this routine
-// to return false.
-bool ParseAbseilFlagsOnly(int argc, char* argv[],
+void ParseAbseilFlagsOnly(int argc, char* argv[],
                           std::vector<char*>& positional_args,
                           std::vector<UnrecognizedFlag>& unrecognized_flags);
 
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index c46bb46..13606d1 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -250,19 +250,31 @@
 // --------------------------------------------------------------------
 
 template <int N>
-std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
-  return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
+flags::HelpMode InvokeParseAbslOnlyImpl(const char* (&in_argv)[N]) {
+  std::vector<char*> positional_args;
+  std::vector<absl::UnrecognizedFlag> unrecognized_flags;
+
+  return flags::ParseAbseilFlagsOnlyImpl(N, const_cast<char**>(in_argv),
+                                         positional_args, unrecognized_flags,
+                                         flags::UsageFlagsAction::kHandleUsage);
 }
 
 // --------------------------------------------------------------------
 
 template <int N>
-bool InvokeParseAbslOnly(const char* (&in_argv)[N]) {
+void InvokeParseAbslOnly(const char* (&in_argv)[N]) {
   std::vector<char*> positional_args;
   std::vector<absl::UnrecognizedFlag> unrecognized_flags;
 
-  return absl::ParseAbseilFlagsOnly(N, const_cast<char**>(in_argv),
-                                    positional_args, unrecognized_flags);
+  absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_argv), positional_args,
+                             unrecognized_flags);
+}
+
+// --------------------------------------------------------------------
+
+template <int N>
+std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
+  return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
 }
 
 // --------------------------------------------------------------------
@@ -871,6 +883,7 @@
       "--help",
   };
 
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kImportant);
   EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
 
   const char* in_args2[] = {
@@ -879,34 +892,55 @@
       "--int_flag=3",
   };
 
-  InvokeParseAbslOnly(in_args2);
-
-  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kImportant);
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
 
   const char* in_args3[] = {"testbin", "--help", "some_positional_arg"};
 
-  InvokeParseAbslOnly(in_args3);
-
-  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args3), flags::HelpMode::kImportant);
 }
 
 // --------------------------------------------------------------------
 
-TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
+TEST_F(ParseTest, TestSubstringHelpFlagHandling) {
   const char* in_args1[] = {
       "testbin",
       "--help=abcd",
   };
 
-  InvokeParseAbslOnly(in_args1);
-
-  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kMatch);
   EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
 }
 
 // --------------------------------------------------------------------
 
+TEST_F(ParseDeathTest, TestVersionHandling) {
+  const char* in_args1[] = {
+      "testbin",
+      "--version",
+  };
+
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kVersion);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestCheckArgsHandling) {
+  const char* in_args1[] = {"testbin", "--only_check_args", "--int_flag=211"};
+
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kOnlyCheckArgs);
+  EXPECT_EXIT(InvokeParseAbslOnly(in_args1), testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(0), "");
+
+  const char* in_args2[] = {"testbin", "--only_check_args", "--unknown_flag=a"};
+
+  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kOnlyCheckArgs);
+  EXPECT_EXIT(InvokeParseAbslOnly(in_args2), testing::ExitedWithCode(0), "");
+  EXPECT_EXIT(InvokeParse(in_args2), testing::ExitedWithCode(1), "");
+}
+
+// --------------------------------------------------------------------
+
 TEST_F(ParseTest, WasPresentOnCommandLine) {
   const char* in_args1[] = {
       "testbin",        "arg1", "--bool_flag",
@@ -947,8 +981,8 @@
   std::vector<char*> positional_args;
   std::vector<absl::UnrecognizedFlag> unrecognized_flags;
 
-  EXPECT_TRUE(absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args),
-                                         positional_args, unrecognized_flags));
+  absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args), positional_args,
+                             unrecognized_flags);
   EXPECT_THAT(positional_args,
               ElementsAreArray(
                   {absl::string_view("testbin"), absl::string_view("arg1"),
@@ -964,17 +998,15 @@
 
 // --------------------------------------------------------------------
 
-TEST_F(ParseTest, ParseAbseilFlagsOnlyFailure) {
+TEST_F(ParseDeathTest, ParseAbseilFlagsOnlyFailure) {
   const char* in_args[] = {
       "testbin",
       "--int_flag=21.1",
   };
 
-  std::vector<char*> positional_args;
-  std::vector<absl::UnrecognizedFlag> unrecognized_flags;
-
-  EXPECT_FALSE(absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_args),
-                                          positional_args, unrecognized_flags));
+  EXPECT_DEATH_IF_SUPPORTED(
+      InvokeParseAbslOnly(in_args),
+      "Illegal value '21.1' specified for flag 'int_flag'");
 }
 
 // --------------------------------------------------------------------
@@ -989,8 +1021,8 @@
   std::vector<char*> positional_args;
   std::vector<absl::UnrecognizedFlag> unrecognized_flags;
 
-  EXPECT_TRUE(absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args),
-                                         positional_args, unrecognized_flags));
+  absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args), positional_args,
+                             unrecognized_flags);
   EXPECT_THAT(positional_args, ElementsAreArray({absl::string_view("testbin"),
                                                  absl::string_view("value")}));
   EXPECT_THAT(unrecognized_flags,
@@ -1018,8 +1050,8 @@
   std::vector<char*> positional_args;
   std::vector<absl::UnrecognizedFlag> unrecognized_flags;
 
-  EXPECT_TRUE(absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args),
-                                         positional_args, unrecognized_flags));
+  absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args), positional_args,
+                             unrecognized_flags);
   EXPECT_THAT(positional_args,
               ElementsAreArray({absl::string_view("testbin"),
                                 absl::string_view("value"),