Merge pull request #1438 from Vertexwahn:fix-spelling

PiperOrigin-RevId: 528547013
Change-Id: I9b57ee062ef666d6a34696778ff16a46c5ccb17d
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 2a33143..32b5141 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -430,6 +430,7 @@
   "types/span.h"
   "types/internal/span.h"
   "types/variant.h"
+  "utility/internal/if_constexpr.h"
   "utility/utility.h"
   "debugging/leak_check.cc"
 )
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
index bdb10f2..4deca72 100644
--- a/absl/log/internal/log_message.cc
+++ b/absl/log/internal/log_message.cc
@@ -234,6 +234,13 @@
   LogBacktraceIfNeeded();
 }
 
+LogMessage::LogMessage(const char* file, int line, InfoTag)
+    : LogMessage(file, line, absl::LogSeverity::kInfo) {}
+LogMessage::LogMessage(const char* file, int line, WarningTag)
+    : LogMessage(file, line, absl::LogSeverity::kWarning) {}
+LogMessage::LogMessage(const char* file, int line, ErrorTag)
+    : LogMessage(file, line, absl::LogSeverity::kError) {}
+
 LogMessage::~LogMessage() {
 #ifdef ABSL_MIN_LOG_LEVEL
   if (data_->entry.log_severity() <
@@ -383,8 +390,7 @@
 template LogMessage& LogMessage::operator<<(const bool& v);
 
 void LogMessage::Flush() {
-  if (data_->entry.log_severity() < absl::MinLogLevel())
-    return;
+  if (data_->entry.log_severity() < absl::MinLogLevel()) return;
 
   if (data_->is_perror) {
     InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
@@ -427,7 +433,7 @@
                          &encoded_remaining_copy_);
   string_start_ =
       EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
-                       &encoded_remaining_copy_);
+                         &encoded_remaining_copy_);
   setp(encoded_remaining_copy_.data(),
        encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
   data_.manipulated.rdbuf(this);
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 3744276..6fdfa7b 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -51,9 +51,21 @@
 
 class LogMessage {
  public:
+  struct InfoTag {};
+  struct WarningTag {};
+  struct ErrorTag {};
+
   // Used for `LOG`.
   LogMessage(const char* file, int line,
              absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
+  // These constructors are slightly smaller/faster to call; the severity is
+  // curried into the function pointer.
+  LogMessage(const char* file, int line,
+             InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+  LogMessage(const char* file, int line,
+             WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+  LogMessage(const char* file, int line,
+             ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
   LogMessage(const LogMessage&) = delete;
   LogMessage& operator=(const LogMessage&) = delete;
   ~LogMessage() ABSL_ATTRIBUTE_COLD;
diff --git a/absl/log/internal/strip.h b/absl/log/internal/strip.h
index 848c386..adc86ff 100644
--- a/absl/log/internal/strip.h
+++ b/absl/log/internal/strip.h
@@ -42,15 +42,15 @@
 #define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
   ABSL_LOGGING_INTERNAL_LOG_QFATAL
 #else  // !defined(STRIP_LOG) || !STRIP_LOG
-#define ABSL_LOGGING_INTERNAL_LOG_INFO                 \
-  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
-                                   ::absl::LogSeverity::kInfo)
-#define ABSL_LOGGING_INTERNAL_LOG_WARNING              \
-  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
-                                   ::absl::LogSeverity::kWarning)
-#define ABSL_LOGGING_INTERNAL_LOG_ERROR                \
-  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
-                                   ::absl::LogSeverity::kError)
+#define ABSL_LOGGING_INTERNAL_LOG_INFO \
+  ::absl::log_internal::LogMessage(    \
+      __FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{})
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING \
+  ::absl::log_internal::LogMessage(       \
+      __FILE__, __LINE__, ::absl::log_internal::LogMessage::WarningTag{})
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR \
+  ::absl::log_internal::LogMessage(     \
+      __FILE__, __LINE__, ::absl::log_internal::LogMessage::ErrorTag{})
 #define ABSL_LOGGING_INTERNAL_LOG_FATAL \
   ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)
 #define ABSL_LOGGING_INTERNAL_LOG_QFATAL \
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 4467785..8b5a27e 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -1241,9 +1241,9 @@
   const NativePrintfTraits &native_traits = VerifyNativeImplementation();
   // If one of the following tests break then it is either because the above PP
   // macro guards failed to exclude a new platform (likely) or because something
-  // has changed in the implementation of glibc sprintf float formatting behavior.
-  // If the latter, then the code that computes these flags needs to be
-  // revisited and/or possibly the StrFormat implementation.
+  // has changed in the implementation of glibc sprintf float formatting
+  // behavior.  If the latter, then the code that computes these flags needs to
+  // be revisited and/or possibly the StrFormat implementation.
   EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding);
   EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr);
   EXPECT_TRUE(
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index ca4bc0a..061f4c5 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -52,3 +52,26 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "if_constexpr",
+    hdrs = [
+        "internal/if_constexpr.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+    ],
+)
+
+cc_test(
+    name = "if_constexpr_test",
+    srcs = ["internal/if_constexpr_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":if_constexpr",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/utility/CMakeLists.txt b/absl/utility/CMakeLists.txt
index 865b758..27ee0de 100644
--- a/absl/utility/CMakeLists.txt
+++ b/absl/utility/CMakeLists.txt
@@ -42,3 +42,27 @@
     absl::strings
     GTest::gmock_main
 )
+
+absl_cc_library(
+  NAME
+    if_constexpr
+  HDRS
+    "internal/if_constexpr.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    if_constexpr_test
+  SRCS
+    "internal/if_constexpr_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::if_constexpr
+    GTest::gmock_main
+)
diff --git a/absl/utility/internal/if_constexpr.h b/absl/utility/internal/if_constexpr.h
new file mode 100644
index 0000000..7a26311
--- /dev/null
+++ b/absl/utility/internal/if_constexpr.h
@@ -0,0 +1,70 @@
+// Copyright 2023 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// 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.
+
+// The IfConstexpr and IfConstexprElse utilities in this file are meant to be
+// used to emulate `if constexpr` in pre-C++17 mode in library implementation.
+// The motivation is to allow for avoiding complex SFINAE.
+//
+// The functions passed in must depend on the type(s) of the object(s) that
+// require SFINAE. For example:
+// template<typename T>
+// int MaybeFoo(T& t) {
+//   if constexpr (HasFoo<T>::value) return t.foo();
+//   return 0;
+// }
+//
+// can be written in pre-C++17 as:
+//
+// template<typename T>
+// int MaybeFoo(T& t) {
+//   int i = 0;
+//   absl::utility_internal::IfConstexpr<HasFoo<T>::value>(
+//       [&](const auto& fooer) { i = fooer.foo(); }, t);
+//   return i;
+// }
+
+#ifndef ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
+#define ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
+
+#include <tuple>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace utility_internal {
+
+template <bool condition, typename TrueFunc, typename FalseFunc,
+          typename... Args>
+auto IfConstexprElse(TrueFunc&& true_func, FalseFunc&& false_func,
+                     Args&&... args) {
+  return std::get<condition>(std::forward_as_tuple(
+      std::forward<FalseFunc>(false_func), std::forward<TrueFunc>(true_func)))(
+      std::forward<Args>(args)...);
+}
+
+template <bool condition, typename Func, typename... Args>
+void IfConstexpr(Func&& func, Args&&... args) {
+  IfConstexprElse<condition>(std::forward<Func>(func), [](auto&&...){},
+                             std::forward<Args>(args)...);
+}
+
+}  // namespace utility_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
diff --git a/absl/utility/internal/if_constexpr_test.cc b/absl/utility/internal/if_constexpr_test.cc
new file mode 100644
index 0000000..d1ee723
--- /dev/null
+++ b/absl/utility/internal/if_constexpr_test.cc
@@ -0,0 +1,79 @@
+// Copyright 2023 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// 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.
+
+#include "absl/utility/internal/if_constexpr.h"
+
+#include <utility>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+struct Empty {};
+struct HasFoo {
+  int foo() const { return 1; }
+};
+
+TEST(IfConstexpr, Basic) {
+  int i = 0;
+  absl::utility_internal::IfConstexpr<false>(
+      [&](const auto& t) { i = t.foo(); }, Empty{});
+  EXPECT_EQ(i, 0);
+
+  absl::utility_internal::IfConstexpr<false>(
+      [&](const auto& t) { i = t.foo(); }, HasFoo{});
+  EXPECT_EQ(i, 0);
+
+  absl::utility_internal::IfConstexpr<true>(
+      [&](const auto& t) { i = t.foo(); }, HasFoo{});
+  EXPECT_EQ(i, 1);
+}
+
+TEST(IfConstexprElse, Basic) {
+  EXPECT_EQ(absl::utility_internal::IfConstexprElse<false>(
+      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
+      Empty{}), 2);
+
+  EXPECT_EQ(absl::utility_internal::IfConstexprElse<false>(
+      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
+      HasFoo{}), 2);
+
+  EXPECT_EQ(absl::utility_internal::IfConstexprElse<true>(
+      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
+      HasFoo{}), 1);
+}
+
+struct HasFooRValue {
+  int foo() && { return 1; }
+};
+struct RValueFunc {
+  void operator()(HasFooRValue&& t) && { *i = std::move(t).foo(); }
+
+  int* i = nullptr;
+};
+
+TEST(IfConstexpr, RValues) {
+  int i = 0;
+  RValueFunc func = {&i};
+  absl::utility_internal::IfConstexpr<false>(
+      std::move(func), HasFooRValue{});
+  EXPECT_EQ(i, 0);
+
+  func = RValueFunc{&i};
+  absl::utility_internal::IfConstexpr<true>(
+      std::move(func), HasFooRValue{});
+  EXPECT_EQ(i, 1);
+}
+
+}  // namespace