about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--absl/base/log_severity.h52
-rw-r--r--absl/flags/flag.h12
-rw-r--r--absl/flags/flag_test.cc23
-rw-r--r--absl/flags/internal/flag.h14
-rw-r--r--absl/functional/bind_front.h58
5 files changed, 126 insertions, 33 deletions
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index e247c4a9796c..65a3b1667270 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -24,19 +24,45 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-// Four severity levels are defined.  Logging APIs should terminate the program
+// absl::LogSeverity
+//
+// Four severity levels are defined. Logging APIs should terminate the program
 // when a message is logged at severity `kFatal`; the other levels have no
 // special semantics.
 //
-// Abseil flags may be defined with type `LogSeverity`.  Dependency layering
-// constraints require that the `AbslParseFlag` overload be declared and defined
-// in the flags module rather than here.  The `AbslUnparseFlag` overload is
-// defined there too for consistency.
+// Values other than the four defined levels (e.g. produced by `static_cast`)
+// are valid, but their semantics when passed to a function, macro, or flag
+// depend on the function, macro, or flag. The usual behavior is to normalize
+// such values to a defined severity level, however in some cases values other
+// than the defined levels are useful for comparison.
+//
+// Exmaple:
+//
+//   // Effectively disables all logging:
+//   SetMinLogLevel(static_cast<absl::LogSeverity>(100));
+//
+// Abseil flags may be defined with type `LogSeverity`. Dependency layering
+// constraints require that the `AbslParseFlag()` overload be declared and
+// defined in the flags library itself rather than here. The `AbslUnparseFlag()`
+// overload is defined there as well for consistency.
+//
+// absl::LogSeverity Flag String Representation
+//
+// An `absl::LogSeverity` has a string representation used for parsing
+// command-line flags based on the enumerator name (e.g. `kFatal`) or
+// its unprefixed name (without the `k`) in any case-insensitive form. (E.g.
+// "FATAL", "fatal" or "Fatal" are all valid.) Unparsing such flags produces an
+// unprefixed string representation in all caps (e.g. "FATAL") or an integer.
 //
-// The parser accepts arbitrary integers (as if the type were `int`).  It also
-// accepts each named enumerator, without regard for case, with or without the
-// leading 'k'.  For example: "kInfo", "INFO", and "info" all parse to the value
-// `absl::LogSeverity::kInfo`.
+// Additionally, the parser accepts arbitrary integers (as if the type were
+// `int`).
+//
+// Examples:
+//
+//   --my_log_level=kInfo
+//   --my_log_level=INFO
+//   --my_log_level=info
+//   --my_log_level=0
 //
 // Unparsing a flag produces the same result as `absl::LogSeverityName()` for
 // the standard levels and a base-ten integer otherwise.
@@ -47,6 +73,8 @@ enum class LogSeverity : int {
   kFatal = 3,
 };
 
+// LogSeverities()
+//
 // Returns an iterable of all standard `absl::LogSeverity` values, ordered from
 // least to most severe.
 constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
@@ -54,6 +82,8 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
            absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
 }
 
+// LogSeverityName()
+//
 // Returns the all-caps string representation (e.g. "INFO") of the specified
 // severity level if it is one of the standard levels and "UNKNOWN" otherwise.
 constexpr const char* LogSeverityName(absl::LogSeverity s) {
@@ -66,6 +96,8 @@ constexpr const char* LogSeverityName(absl::LogSeverity s) {
                          : s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN";
 }
 
+// NormalizeLogSeverity()
+//
 // Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`
 // normalize to `kError` (**NOT** `kFatal`).
 constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
@@ -77,6 +109,8 @@ constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
   return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
 }
 
+// operator<<
+//
 // The exact representation of a streamed `absl::LogSeverity` is deliberately
 // unspecified; do not rely on it.
 std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index b6fbd116ed2f..f18e9f56a5cc 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -384,11 +384,19 @@ ABSL_NAMESPACE_END
 //
 // `default_value` is only used as a double check on the type. `explanation` is
 // unused.
+//
+// ABSL_RETIRED_FLAG support omitting the default value for default
+// constructible value type, so that users can delete the code generatring this
+// value.
+//
 // TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
 // the unnamed namespace.
 #define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
-  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \
-      ([] { return type(default_value); },                            \
+  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =             \
+      ([] {                                                                \
+           return absl::flags_internal::MakeFromDefaultValueOrEmpty<type>( \
+                   default_value);                                         \
+       },                                                                  \
        absl::flags_internal::RetiredFlag<type>(#flagname))
 
 #endif  // ABSL_FLAGS_FLAG_H_
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 4e08da8589a5..465f018c5e4f 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -486,11 +486,30 @@ TEST_F(FlagTest, TestNonDefaultConstructibleType) {
 
 // --------------------------------------------------------------------
 
+struct Wrapper {
+  Wrapper() {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  Wrapper(const std::string& val) : val(val) {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  template <typename T>
+  Wrapper(T&& t) : val(std::forward<T>(t)) {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  operator std::string() const& { return val; }
+
+  std::string val;
+};
+
 }  // namespace
 
 ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
+ABSL_RETIRED_FLAG(Wrapper, old_wrapper_flag, {}, "old wrapper");
+ABSL_RETIRED_FLAG(Wrapper, old_wrapper_no_default_flag, ,
+                  "old wrapper no default");
 
 namespace {
 
@@ -502,6 +521,10 @@ TEST_F(FlagTest, TestRetiredFlagRegistration) {
   EXPECT_FALSE(is_bool);
   EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
   EXPECT_FALSE(is_bool);
+  EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_flag", &is_bool));
+  EXPECT_FALSE(is_bool);
+  EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_no_default_flag", &is_bool));
+  EXPECT_FALSE(is_bool);
   EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
 }
 
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 20de406f4615..21a10c7f85f8 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -416,6 +416,20 @@ T* MakeFromDefaultValue(EmptyBraces) {
   return new T;
 }
 
+// MakeFromDefaultValueOrEmpty is basically the same as MakeFromDefaultValue. It
+// also allows for empty macro parameter (hence no argument), which was somehow
+// widely used for ABSL_RETIRED_FLAG().
+
+template <typename T>
+T* MakeFromDefaultValueOrEmpty(T t) {
+  return MakeFromDefaultValue(std::move(t));
+}
+
+template <typename T>
+T* MakeFromDefaultValueOrEmpty() {
+  return MakeFromDefaultValue<T>(EmptyBraces());
+}
+
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/functional/bind_front.h b/absl/functional/bind_front.h
index 4c61d0ecfd12..8448d7b3c121 100644
--- a/absl/functional/bind_front.h
+++ b/absl/functional/bind_front.h
@@ -11,17 +11,44 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-
+//
+// -----------------------------------------------------------------------------
+// File: bind_front.h
+// -----------------------------------------------------------------------------
+//
 // `absl::bind_front()` returns a functor by binding a number of arguments to
-// the front of a provided functor, allowing you to avoid known problems with
-// `std::bind()`.  It is a form of partial function application
-// https://en.wikipedia.org/wiki/Partial_application.
+// the front of a provided (usually more generic) functor. Unlike `std::bind`,
+// it does not require the use of argument placeholders. The simpler syntax of
+// `absl::bind_front()` allows you to avoid known misuses with `std::bind()`.
+//
+// `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming
+// `std::bind_front()`, which similarly resolves these issues with
+// `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow
+// partial function application. (See
+// https://en.wikipedia.org/wiki/Partial_application).
+
+#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_
+#define ABSL_FUNCTIONAL_BIND_FRONT_H_
+
+#include "absl/functional/internal/front_binder.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// bind_front()
+//
+// Binds the first N arguments of an invocable object and stores them by value,
+// except types of `std::reference_wrapper` which are 'unwound' and stored by
+// reference.
 //
-// Like `std::bind()` it is implicitly convertible to `std::function`.  In
-// particular, it may be used as a simpler replacement for `std::bind()` in most
-// cases, as it does not require  placeholders to be specified.  More
-// importantly, it provides more reliable correctness guarantees than
-// `std::bind()`.
+// Like `std::bind()`, `absl::bind_front()` is implicitly convertible to
+// `std::function`.  In particular, it may be used as a simpler replacement for
+// `std::bind()` in most cases, as it does not require  placeholders to be
+// specified. More importantly, it provides more reliable correctness guarantees
+// than `std::bind()`; while `std::bind()` will silently ignore passing more
+// parameters than expected, for example, `absl::bind_front()` will report such
+// mis-uses as errors.
 //
 // absl::bind_front(a...) can be seen as storing the results of
 // std::make_tuple(a...).
@@ -125,19 +152,6 @@
 //   // dangling references.
 //   foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest"));  // BAD!
 //   auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD!
-
-#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_
-#define ABSL_FUNCTIONAL_BIND_FRONT_H_
-
-#include "absl/functional/internal/front_binder.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// Binds the first N arguments of an invocable object and stores them by value,
-// except types of std::reference_wrapper which are 'unwound' and stored by
-// reference.
 template <class F, class... BoundArgs>
 constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front(
     F&& func, BoundArgs&&... args) {