diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index cbeb96c..842c6b3 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -454,6 +454,7 @@
   "types/internal/span.h"
   "types/optional.h"
   "types/optional_ref.h"
+  "types/source_location.h"
   "types/span.h"
   "types/variant.h"
   "utility/utility.h"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a31c6a9..3583e3d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -227,7 +227,7 @@
 
   # Handle features that require at least C++20.
   if (ABSL_INTERNAL_AT_LEAST_CXX20)
-    foreach(FEATURE "ORDERING")
+    foreach(FEATURE "ORDERING" "SOURCE_LOCATION")
       string(REPLACE
       "#define ABSL_OPTION_USE_STD_${FEATURE} 2"
       "#define ABSL_OPTION_USE_STD_${FEATURE} 1"
diff --git a/absl/base/config.h b/absl/base/config.h
index 82e8009..b707654 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -531,6 +531,42 @@
 #define ABSL_HAVE_STD_VARIANT 1
 #define ABSL_USES_STD_VARIANT 1
 
+// ABSL_HAVE_STD_SOURCE_LOCATION
+//
+// Checks whether C++20 std::source_location is available.
+#ifdef ABSL_HAVE_STD_SOURCE_LOCATION
+#error "ABSL_HAVE_STD_SOURCE_LOCATION cannot be directly set."
+#elif (defined(__cpp_lib_source_location) &&    \
+       __cpp_lib_source_location >= 201907L) || \
+    (defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&   \
+     ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L)
+#ifdef __has_include
+#if __has_include(<source_location>)
+#define ABSL_HAVE_STD_SOURCE_LOCATION 1
+#endif
+#else
+// No __has_include support, so just assume C++ language version is correct.
+#define ABSL_HAVE_STD_SOURCE_LOCATION 1
+#endif
+#endif
+
+// ABSL_USES_STD_SOURCE_LOCATION
+//
+// Indicates whether absl::SourceLocation is an alias for std::source_location.
+#if !defined(ABSL_OPTION_USE_STD_SOURCE_LOCATION)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_SOURCE_LOCATION == 0 || \
+    (ABSL_OPTION_USE_STD_SOURCE_LOCATION == 2 &&  \
+     !defined(ABSL_HAVE_STD_SOURCE_LOCATION))
+#undef ABSL_USES_STD_SOURCE_LOCATION
+#elif ABSL_OPTION_USE_STD_SOURCE_LOCATION == 1 || \
+    (ABSL_OPTION_USE_STD_SOURCE_LOCATION == 2 &&  \
+     defined(ABSL_HAVE_STD_SOURCE_LOCATION))
+#define ABSL_USES_STD_SOURCE_LOCATION 1
+#else
+#error options.h is misconfigured.
+#endif
+
 // ABSL_HAVE_STD_ORDERING
 //
 // Checks whether C++20 std::{partial,weak,strong}_ordering are available.
@@ -799,6 +835,14 @@
 #define ABSL_INTERNAL_HAVE_ARM_NEON 1
 #endif
 
+#if ABSL_HAVE_BUILTIN(__builtin_LINE) && ABSL_HAVE_BUILTIN(__builtin_FILE)
+#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1
+#elif defined(__GNUC__) && !defined(__clang__) && 5 <= __GNUC__ && __GNUC__ < 10
+#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1
+#elif defined(_MSC_VER) && _MSC_VER >= 1926
+#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1
+#endif
+
 // ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of
 // constant evaluation support through `absl::is_constant_evaluated`.
 #ifdef ABSL_HAVE_CONSTANT_EVALUATED
diff --git a/absl/base/fast_type_id.h b/absl/base/fast_type_id.h
index a1214da..6e4c573 100644
--- a/absl/base/fast_type_id.h
+++ b/absl/base/fast_type_id.h
@@ -31,7 +31,7 @@
 }  // namespace base_internal
 
 // The type returned by `absl::FastTypeId<T>()`.
-class FastTypeIdType {
+class FastTypeIdType final {
  public:
   // Creates a value that does not correspond to any type. This value is
   // distinct from any value returned by `FastTypeId<T>()`.
diff --git a/absl/base/options.h b/absl/base/options.h
index 6f48e75..cfacc6e 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -73,6 +73,34 @@
 // Type Compatibility Options
 // -----------------------------------------------------------------------------
 
+// ABSL_OPTION_USE_STD_SOURCE_LOCATION
+//
+// This option controls whether absl::SourceLocation is implemented as an alias
+// to the std::source_location type, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++17
+// support, and is expected to run on every toolchain we support, and to
+// properly capture source location information on every toolchain that supports
+// the necessary built-ins (such as `__builtin_LINE`).
+//
+// A value of 1 means to use aliases.  This requires that all code using Abseil
+// is built in C++20 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if working std::source_location types are available.
+// This option is useful when you are building your program from source.  It
+// should not be used otherwise -- for example, if you are distributing Abseil
+// in a binary package manager -- since in mode 2, they will name different
+// types, with different mangled names and binary layout, depending on the
+// compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// the source location type is an alias of std::source_location type, use the
+// feature macro ABSL_USES_STD_SOURCE_LOCATION.
+//
+#define ABSL_OPTION_USE_STD_SOURCE_LOCATION 2
+
 // ABSL_OPTION_USE_STD_ORDERING
 //
 // This option controls whether absl::{partial,weak,strong}_ordering are
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 5e9a483..1a9fa1d 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -459,26 +459,41 @@
 
 // The size and also has additionally
 // 1) one bit that stores whether we have infoz.
-// 2) PerTableSeed::kBitCount bits for the seed.
+// 2) PerTableSeed::kBitCount bits for the seed. (For SOO tables, the lowest
+//    bit of the seed is repurposed to track if sampling has been tried).
 class HashtableSize {
  public:
   static constexpr size_t kSizeBitCount = 64 - PerTableSeed::kBitCount - 1;
 
   explicit HashtableSize(uninitialized_tag_t) {}
   explicit HashtableSize(no_seed_empty_tag_t) : data_(0) {}
-  explicit HashtableSize(full_soo_tag_t) : data_(kSizeOneNoMetadata) {}
+  HashtableSize(full_soo_tag_t, bool has_tried_sampling)
+      : data_(kSizeOneNoMetadata |
+              (has_tried_sampling ? kSooHasTriedSamplingMask : 0)) {}
 
   // Returns actual size of the table.
   size_t size() const { return static_cast<size_t>(data_ >> kSizeShift); }
   void increment_size() { data_ += kSizeOneNoMetadata; }
   void increment_size(size_t size) {
-    data_ += static_cast<uint64_t>(size) * kSizeOneNoMetadata;
+    data_ += static_cast<uint64_t>(size) << kSizeShift;
   }
   void decrement_size() { data_ -= kSizeOneNoMetadata; }
   // Returns true if the table is empty.
   bool empty() const { return data_ < kSizeOneNoMetadata; }
-  // Sets the size to zero, but keeps all the metadata bits.
-  void set_size_to_zero_keep_metadata() { data_ = data_ & kMetadataMask; }
+
+  // Returns true if an empty SOO table has already queried should_sample_soo().
+  bool soo_has_tried_sampling() const {
+    return (data_ & kSooHasTriedSamplingMask) != 0;
+  }
+
+  // Records that an empty SOO table has tried sampling.
+  void set_soo_has_tried_sampling() { data_ |= kSooHasTriedSamplingMask; }
+
+  // Sets the size, but keeps all the metadata bits.
+  void set_size_keep_metadata(size_t size) {
+    data_ =
+        (data_ & kMetadataMask) | (static_cast<uint64_t>(size) << kSizeShift);
+  }
 
   PerTableSeed seed() const {
     return PerTableSeed(static_cast<size_t>(data_) & kSeedMask);
@@ -509,6 +524,10 @@
 
  private:
   void set_seed(uint16_t seed) { data_ = (data_ & ~kSeedMask) | seed; }
+  // Bit layout of `data_`:
+  // [63 ... 17] (47 bits) : size
+  // [16]        (1 bit)   : has_infoz
+  // [15 ...  0] (16 bits) : seed
   static constexpr size_t kSizeShift = 64 - kSizeBitCount;
   static constexpr uint64_t kSizeOneNoMetadata = uint64_t{1} << kSizeShift;
   static constexpr uint64_t kMetadataMask = kSizeOneNoMetadata - 1;
@@ -516,6 +535,9 @@
       (uint64_t{1} << PerTableSeed::kBitCount) - 1;
   // The next bit after the seed.
   static constexpr uint64_t kHasInfozMask = kSeedMask + 1;
+  // For SOO tables, the seed is unused, and bit 0 is repurposed to track
+  // whether the table has already queried should_sample_soo().
+  static constexpr uint64_t kSooHasTriedSamplingMask = 1;
   uint64_t data_;
 };
 
@@ -907,8 +929,8 @@
  public:
   explicit CommonFields(soo_tag_t)
       : capacity_(SooCapacity()), size_(no_seed_empty_tag_t{}) {}
-  explicit CommonFields(full_soo_tag_t)
-      : capacity_(SooCapacity()), size_(full_soo_tag_t{}) {}
+  explicit CommonFields(full_soo_tag_t, bool has_tried_sampling)
+      : capacity_(SooCapacity()), size_(full_soo_tag_t{}, has_tried_sampling) {}
   explicit CommonFields(non_soo_tag_t)
       : capacity_(0), size_(no_seed_empty_tag_t{}) {}
   // For use in swapping.
@@ -963,14 +985,14 @@
   // The number of filled slots.
   size_t size() const { return size_.size(); }
   // Sets the size to zero, but keeps hashinfoz bit and seed.
-  void set_size_to_zero() { size_.set_size_to_zero_keep_metadata(); }
+  void set_size_to_zero() { size_.set_size_keep_metadata(0); }
   void set_empty_soo() {
     AssertInSooMode();
-    size_ = HashtableSize(no_seed_empty_tag_t{});
+    size_.set_size_keep_metadata(0);
   }
   void set_full_soo() {
     AssertInSooMode();
-    size_ = HashtableSize(full_soo_tag_t{});
+    size_.set_size_keep_metadata(1);
   }
   void increment_size() {
     ABSL_SWISSTABLE_ASSERT(size() < capacity());
@@ -985,6 +1007,8 @@
     size_.decrement_size();
   }
   bool empty() const { return size_.empty(); }
+  void set_soo_has_tried_sampling() { size_.set_soo_has_tried_sampling(); }
+  bool soo_has_tried_sampling() const { return size_.soo_has_tried_sampling(); }
 
   // The seed used for the hash function.
   PerTableSeed seed() const { return size_.seed(); }
@@ -2271,7 +2295,8 @@
          // Note: we avoid using exchange for better generated code.
         settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo()
                       ? std::move(that.common())
-                      : CommonFields{full_soo_tag_t{}},
+                      : CommonFields{full_soo_tag_t{},
+                                     that.common().soo_has_tried_sampling()},
                   that.hash_ref(), that.eq_ref(), that.char_alloc_ref()) {
     if (!PolicyTraits::transfer_uses_memcpy() && that.is_full_soo()) {
       transfer(soo_slot(), that.soo_slot());
@@ -3011,12 +3036,23 @@
     }
   }
 
-  // Returns true if the table needs to be sampled.
+  // Returns true if the table needs to be sampled. This keeps track of whether
+  // sampling has already been evaluated and ensures that it can only return
+  // true on its first evaluation. All subsequent calls will return false.
+  //
   // This should be called on insertion into an empty SOO table and in copy
   // construction when the size can fit in SOO capacity.
-  bool should_sample_soo() const {
+  bool should_sample_soo() {
     ABSL_SWISSTABLE_ASSERT(is_soo());
     if (!ShouldSampleHashtablezInfoForAlloc<CharAlloc>()) return false;
+    if (common().soo_has_tried_sampling()) {
+      // Already evaluated sampling on this SOO table; do not re-evaluate
+      // sampling each time it transitions from empty to full SOO state.
+      return false;
+    }
+    // TODO: b/396049910 -- consider managing this flag on the 1->0 size
+    // transition of SOO tables rather than the 0->1 transition.
+    common().set_soo_has_tried_sampling();
     return ABSL_PREDICT_FALSE(ShouldSampleNextTable());
   }
 
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index fd99b2c..9c33e3c 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -2932,6 +2932,70 @@
   }
 }
 
+// Verifies that repeated insertions and erasures on an SOO table do not cause
+// the sampling decision to be evaluated multiple times, preventing
+// oversampling.
+TEST(RawHashSamplerTest, SooTableRepeatedInsertEraseDoesNotOversample) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+  std::vector<const HashtablezInfo*> infos =
+      SampleSooMutation([](SooInt32Table& t) {
+        for (int i = 0; i < 10; ++i) {
+          t.insert(1);
+          t.erase(1);
+        }
+      });
+
+  // SampleSooMutation checks EXPECT_NEAR(sampled/total, 1%, 0.5%).
+  // If the sampling logic is incorrectly evaluated on every 0->1 element
+  // transition, the chance of being sampled per table approaches 10% (1 -
+  // 0.99^10), which is enough to cause this test to fail. By passing, this test
+  // verifies that the sampling decision is evaluated exactly once per SOO table
+  // instance.
+}
+
+// Verifies that copy-constructing or copy-assigning an SOO table does not
+// incorrectly trigger new sampling evaluations.
+TEST(RawHashSamplerTest, SooTableCopyDoesNotOversample) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+  std::vector<const HashtablezInfo*> infos =
+      SampleSooMutation([](SooInt32Table& t) {
+        t.insert(1);
+        t.erase(1);
+        SooInt32Table t_copy(t);
+        for (int i = 0; i < 10; ++i) {
+          t_copy.insert(1);
+          t_copy.erase(1);
+        }
+        t = std::move(t_copy);
+      });
+}
+
+// Verifies that move-constructing or move-assigning an SOO table correctly
+// transfers the sampling state and does not trigger oversampling.
+TEST(RawHashSamplerTest, SooTableMoveDoesNotOversample) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+  std::vector<const HashtablezInfo*> infos =
+      SampleSooMutation([](SooInt32Table& t) {
+        t.insert(1);
+        t.erase(1);
+        SooInt32Table t_moved(std::move(t));
+        for (int i = 0; i < 10; ++i) {
+          t_moved.insert(1);
+          t_moved.erase(1);
+        }
+        t = std::move(t_moved);
+      });
+}
+
 TEST(RawHashSamplerTest, SooTableReserveToEmpty) {
   if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
@@ -3029,6 +3093,63 @@
     ASSERT_EQ(info->total_probe_length, 0);
   }
 }
+
+// Verifies that a moved-from table does not retain the sampled state of the
+// original table, allowing it to be used without incorrectly updating global
+// sampling stats.
+TEST(RawHashSamplerTest, MovedFromTableIsNotSampled) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+
+  SetSamplingRateTo1Percent();
+  auto& sampler = GlobalHashtablezSampler();
+  size_t start_size = 0;
+  absl::flat_hash_set<const HashtablezInfo*> preexisting_info;
+  sampler.Iterate([&](const HashtablezInfo& info) {
+    preexisting_info.insert(&info);
+    ++start_size;
+  });
+
+  SooInt32Table t1;
+  // Loop until t1 is sampled
+  while (true) {
+    t1 = SooInt32Table();
+    t1.insert(1);
+    size_t new_size = 0;
+    sampler.Iterate([&](const HashtablezInfo&) { ++new_size; });
+    if (new_size > start_size) break;
+  }
+
+  // Move the table
+  SooInt32Table t2 = std::move(t1);
+
+  // Disable sampling to ensure any new sampling is a bug.
+  SetHashtablezEnabled(false);
+
+  // t2 is now the sampled table. t1 is moved-from.
+  // We want to verify that t2 is still sampled, and that t1 isn't sampled
+  // anymore, even if we insert a new entry into it.
+  t1.clear();  // Must clear before using a moved-from table.
+  t1.insert(2);
+  t2.insert(2);
+
+  // Verify no new sample was generated, and t2's sample size is now 2.
+  size_t final_size = 0;
+  const HashtablezInfo* latest_info = nullptr;
+  size_t dropped = sampler.Iterate([&](const HashtablezInfo& info) {
+    ++final_size;
+    if (!preexisting_info.contains(&info)) {
+      latest_info = &info;
+    }
+  });
+  EXPECT_EQ(0, dropped);
+  EXPECT_EQ(final_size, start_size + 1);
+  ASSERT_NE(latest_info, nullptr);
+  EXPECT_EQ(latest_info->size.load(std::memory_order_relaxed), 2);
+}
+
 #endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index a5c736c..e6f11e8 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -135,10 +135,13 @@
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:malloc_internal",
+        "//absl/cleanup",
         "//absl/log",
         "//absl/log:check",
         "//absl/memory",
         "//absl/strings",
+        "//absl/strings:str_format",
         "@googletest//:gtest",
     ],
 )
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index d8249fe..fbdb550 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -107,12 +107,15 @@
   DEPS
     absl::base
     absl::check
+    absl::cleanup
     absl::config
     absl::core_headers
     absl::log
+    absl::malloc_internal
     absl::memory
     absl::stack_consumption
     absl::strings
+    absl::str_format
     absl::symbolize
     GTest::gmock
 )
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index 509f426..bd2c9c7 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -22,6 +22,7 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <memory>
 
 #include "absl/base/config.h"
 #include "absl/strings/string_view.h"
@@ -35,7 +36,6 @@
 #include <elf.h>
 #include <link.h>  // For ElfW() macro.
 #include <functional>
-#include <string>
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -78,6 +78,7 @@
 ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
+// Legacy stateless symbol decorator API. Will be removed soon.
 struct SymbolDecoratorArgs {
   // The program counter we are getting symbolic name for.
   const void *pc;
@@ -101,13 +102,13 @@
   // User-provided argument
   void* arg;
 };
-using SymbolDecorator = void (*)(const SymbolDecoratorArgs *);
+using LegacySymbolDecorator = void (*)(const SymbolDecoratorArgs *);
 
 // Installs a function-pointer as a decorator. Returns a value less than zero
 // if the system cannot install the decorator. Otherwise, returns a unique
 // identifier corresponding to the decorator. This identifier can be used to
 // uninstall the decorator - See RemoveSymbolDecorator() below.
-int InstallSymbolDecorator(SymbolDecorator decorator, void* arg);
+int InstallSymbolDecorator(LegacySymbolDecorator decorator, void* arg);
 
 // Removes a previously installed function-pointer decorator. Parameter "ticket"
 // is the return-value from calling InstallSymbolDecorator().
@@ -117,6 +118,55 @@
 // symbolization is currently in progress.
 bool RemoveAllSymbolDecorators();
 
+class SymbolDecorator;
+
+class SymbolDecoratorDeleter {
+ public:
+  void operator()(SymbolDecorator* ptr);
+};
+
+using SymbolDecoratorPtr =
+    std::unique_ptr<SymbolDecorator, SymbolDecoratorDeleter>;
+
+// Represents an object that can add additional information to a symbol
+// name.
+class SymbolDecorator {
+ public:
+  // The signature of a factory function used to register and create a symbol
+  // decorator. This function may be called from a signal handler, so it must
+  // use an async-signal-safe allocation mechanism to allocate the returned
+  // object.
+  using Factory = SymbolDecoratorPtr(int fd);
+
+  virtual ~SymbolDecorator() = default;
+
+  // Decorates symbol name with additional information.
+  //
+  // pc represents the program counter we are getting symbolic name for.
+  // relocation is difference between the link-time and the load-time address.
+  // symbol_buf and symbol_buf_size represent the output buffer and its size.
+  // Note that the buffer may not be empty -- default symbolizer may have
+  // already produced some output. You are free to replace or augment the
+  // contents (within the symbol_buf_size limit). tmp_buf and tmp_buf_size
+  // represent temporary scratch space and its size. Use that space in
+  // preference to allocating your own stack buffer to conserve stack.
+  //
+  // This function will not be called concurrently for the same object, but it
+  // may be called from a signal handler, so it must avoid any operation that is
+  // not async-signal-safe. However, it does not have to be reentrant -- if it
+  // is interrupted by a signal and the handler tries to symbolize, the request
+  // will go to a new SymbolDecorator instance.
+  virtual void Decorate(
+      const void* pc,
+      ptrdiff_t relocation,
+      char* symbol_buf, size_t symbol_buf_size,
+      char* tmp_buf, size_t tmp_buf_size) const = 0;
+};
+
+// Registers a new symbol decorator factory and returns the previous one.
+SymbolDecorator::Factory* SetSymbolDecoratorFactory(
+    SymbolDecorator::Factory* factory);
+
 // Registers an address range to a file mapping.
 //
 // Preconditions:
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index 344436f..147fda9 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -12,10 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// SKIP_ABSL_INLINE_NAMESPACE_CHECK
-
 #include "absl/debugging/symbolize.h"
 
+#include "absl/base/config.h"
+#include "absl/base/internal/low_level_alloc.h"
+#include "absl/debugging/internal/symbolize.h"
+
 #ifdef _WIN32
 #include <winapifamily.h>
 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
@@ -42,3 +44,19 @@
 #else
 #include "absl/debugging/symbolize_unimplemented.inc"
 #endif
+
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace debugging_internal {
+
+void SymbolDecoratorDeleter::operator()(SymbolDecorator* ptr) {
+  ptr->~SymbolDecorator();
+  base_internal::LowLevelAlloc::Free(ptr);
+}
+
+}  // namespace debugging_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index 0317bbc..5630cc2 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -67,6 +67,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#include <memory>
 
 #include "absl/base/casts.h"
 #include "absl/base/dynamic_annotations.h"
@@ -148,7 +149,7 @@
 const int kMaxDecorators = 10;  // Seems like a reasonable upper limit.
 
 struct InstalledSymbolDecorator {
-  SymbolDecorator fn;
+  LegacySymbolDecorator fn;
   void *arg;
   int ticket;
 };
@@ -156,6 +157,8 @@
 int g_num_decorators;
 InstalledSymbolDecorator g_decorators[kMaxDecorators];
 
+std::atomic<SymbolDecorator::Factory*> g_decorator_factory = nullptr;
+
 struct FileMappingHint {
   const void *start;
   const void *end;
@@ -190,32 +193,23 @@
 }
 
 struct ObjFile {
-  ObjFile()
-      : filename(nullptr),
-        start_addr(nullptr),
-        end_addr(nullptr),
-        offset(0),
-        fd(-1),
-        elf_type(-1) {
-    SafeMemZero(&elf_header, sizeof(elf_header));
-    SafeMemZero(&phdr[0], sizeof(phdr));
-  }
-
-  char *filename;
-  const void *start_addr;
-  const void *end_addr;
-  uint64_t offset;
+  char *filename = nullptr;
+  const void *start_addr = nullptr;
+  const void *end_addr = nullptr;
+  uint64_t offset = 0;
 
   // The following fields are initialized on the first access to the
   // object file.
-  int fd;
-  int elf_type;
-  ElfW(Ehdr) elf_header;
+  int fd = -1;
+  int elf_type = -1;
+  ElfW(Ehdr) elf_header = {};
 
   // PT_LOAD program header describing executable code.
   // Normally we expect just one, but SWIFT binaries have two.
   // CUDA binaries have 3 (see cr/473913254 description).
-  std::array<ElfW(Phdr), 4> phdr;
+  std::array<ElfW(Phdr), 4> phdr = {};
+
+  SymbolDecoratorPtr decorator = {};
 };
 
 // Build 4-way associative cache for symbols. Within each cache line, symbols
@@ -266,7 +260,8 @@
         static_cast<ObjFile *>(base_internal::LowLevelAlloc::AllocWithArena(
             new_allocated * sizeof(*new_obj_), base_internal::SigSafeArena()));
     if (obj_) {
-      memcpy(new_obj_, obj_, allocated_ * sizeof(*new_obj_));
+      std::uninitialized_move_n(obj_, size_, new_obj_);
+      std::destroy_n(obj_, size_);
       base_internal::LowLevelAlloc::Free(obj_);
     }
     obj_ = new_obj_;
@@ -309,6 +304,8 @@
   ~Symbolizer();
   const char *GetSymbol(const void *const pc);
 
+  void UpdateDecoratorsIfNeeded(SymbolDecorator::Factory* decorator_factory);
+
  private:
   char *CopyString(const char *s) {
     size_t len = strlen(s);
@@ -345,6 +342,7 @@
   };
 
   AddrMap addr_map_;
+  SymbolDecorator::Factory* decorator_factory_ = nullptr;
 
   bool ok_;
   bool addr_map_read_;
@@ -422,11 +420,14 @@
   base_internal::InitSigSafeArena();
   Symbolizer *symbolizer =
       g_cached_symbolizer.exchange(nullptr, std::memory_order_acquire);
-  if (symbolizer != nullptr) {
-    return symbolizer;
+  if (symbolizer == nullptr) {
+    void* ptr = base_internal::LowLevelAlloc::AllocWithArena(
+        SymbolizerSize(), base_internal::SigSafeArena());
+    symbolizer = new (ptr) Symbolizer();
   }
-  return new (base_internal::LowLevelAlloc::AllocWithArena(
-      SymbolizerSize(), base_internal::SigSafeArena())) Symbolizer();
+  symbolizer->UpdateDecoratorsIfNeeded(
+      g_decorator_factory.load(std::memory_order_acquire));
+  return symbolizer;
 }
 
 // Set g_cached_symbolize_state to s if it is null, otherwise
@@ -443,7 +444,7 @@
 
 Symbolizer::Symbolizer() : ok_(true), addr_map_read_(false) {
   for (SymbolCacheLine &symbol_cache_line : symbol_cache_) {
-    for (size_t j = 0; j < ABSL_ARRAYSIZE(symbol_cache_line.name); ++j) {
+    for (size_t j = 0; j < std::size(symbol_cache_line.name); ++j) {
       symbol_cache_line.pc[j] = nullptr;
       symbol_cache_line.name[j] = nullptr;
       symbol_cache_line.age[j] = 0;
@@ -460,6 +461,26 @@
   ClearAddrMap();
 }
 
+void Symbolizer::UpdateDecoratorsIfNeeded(
+    SymbolDecorator::Factory* decorator_factory) {
+  if (decorator_factory_ == decorator_factory) return;
+
+  for (SymbolCacheLine& symbol_cache_line : symbol_cache_) {
+    for (size_t j = 0; j < std::size(symbol_cache_line.name); ++j) {
+      symbol_cache_line.pc[j] = nullptr;
+      base_internal::LowLevelAlloc::Free(symbol_cache_line.name[j]);
+      symbol_cache_line.name[j] = nullptr;
+      symbol_cache_line.age[j] = 0;
+    }
+  }
+
+  decorator_factory_ = decorator_factory;
+  for (size_t i = 0, end = addr_map_.Size(); i < end; ++i) {
+    ObjFile* obj = addr_map_.At(i);
+    obj->decorator.reset();
+  }
+}
+
 // We don't use assert() since it's not guaranteed to be
 // async-signal-safe.  Instead we define a minimal assertion
 // macro. So far, we don't need pretty printing for __FILE__, etc.
@@ -1387,7 +1408,8 @@
   obj->fd = fd;
 }
 
-static bool MaybeInitializeObjFile(ObjFile *obj) {
+static bool MaybeInitializeObjFile(
+    ObjFile* obj, SymbolDecorator::Factory* decorator_factory) {
   if (obj->fd < 0) {
     obj->fd = OpenReadOnlyWithHighFD(obj->filename);
 
@@ -1469,6 +1491,9 @@
       return false;
     }
   }
+  if (decorator_factory != nullptr && obj->decorator == nullptr) {
+    obj->decorator = decorator_factory(obj->fd);
+  }
   return true;
 }
 
@@ -1484,7 +1509,7 @@
   ptrdiff_t relocation = 0;
   int fd = -1;
   if (obj != nullptr) {
-    if (MaybeInitializeObjFile(obj)) {
+    if (MaybeInitializeObjFile(obj, decorator_factory_)) {
       const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
       if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
         // This object was relocated.
@@ -1561,6 +1586,10 @@
     }
     g_decorators_mu.unlock();
   }
+  if (obj != nullptr && obj->decorator != nullptr) {
+    obj->decorator->Decorate(pc, relocation, symbol_buf_, sizeof(symbol_buf_),
+                             tmp_buf_, sizeof(tmp_buf_));
+  }
   if (symbol_buf_[0] == '\0') {
     return nullptr;
   }
@@ -1604,7 +1633,9 @@
 #endif
 }
 
-bool RemoveAllSymbolDecorators(void) {
+bool RemoveAllSymbolDecorators() {
+  SetSymbolDecoratorFactory(nullptr);
+
   if (!g_decorators_mu.try_lock()) {
     // Someone else is using decorators. Get out.
     return false;
@@ -1633,7 +1664,7 @@
   return true;  // Decorator is known to be removed.
 }
 
-int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
+int InstallSymbolDecorator(LegacySymbolDecorator decorator, void *arg) {
   static int ticket = 0;
 
   if (!g_decorators_mu.try_lock()) {
@@ -1651,6 +1682,11 @@
   return ret;
 }
 
+SymbolDecorator::Factory* SetSymbolDecoratorFactory(
+    SymbolDecorator::Factory* factory) {
+  return g_decorator_factory.exchange(factory, std::memory_order_acq_rel);
+}
+
 bool RegisterFileMappingHint(const void *start, const void *end,
                              uint64_t offset, const char *filename) {
   SAFE_ASSERT(start <= end);
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 2dd5da5..5e1e65d 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -13,6 +13,10 @@
 // limitations under the License.
 
 #include "absl/debugging/symbolize.h"
+#include <cstddef>
+
+#include "absl/debugging/internal/symbolize.h"
+#include "absl/strings/str_format.h"
 
 #ifdef __EMSCRIPTEN__
 #include <emscripten.h>
@@ -32,8 +36,10 @@
 #include "absl/base/attributes.h"
 #include "absl/base/casts.h"
 #include "absl/base/config.h"
+#include "absl/base/internal/low_level_alloc.h"
 #include "absl/base/internal/per_thread_tls.h"
 #include "absl/base/optimization.h"
+#include "absl/cleanup/cleanup.h"
 #include "absl/debugging/internal/stack_consumption.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
@@ -411,6 +417,43 @@
   EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c));
 }
 
+template <char C>
+class TestSymbolDecorator final
+    : public absl::debugging_internal::SymbolDecorator {
+ public:
+  static absl::debugging_internal::SymbolDecoratorPtr Factory(int /*fd*/) {
+    void* ptr = absl::base_internal::LowLevelAlloc::AllocWithArena(
+        sizeof(TestSymbolDecorator), absl::base_internal::SigSafeArena());
+    return absl::debugging_internal::SymbolDecoratorPtr(
+        new (ptr) TestSymbolDecorator());
+  }
+
+  void Decorate(const void* /*pc*/, ptrdiff_t /*relocation*/, char* symbol_buf,
+                size_t symbol_buf_size, char* /*tmp_buf*/,
+                size_t /*tmp_buf_size*/) const override {
+    const size_t len = strlen(symbol_buf);
+    absl::SNPrintF(symbol_buf + len, symbol_buf_size - len, " hello %c", C);
+  }
+};
+
+TEST(Symbolize, SetSymbolDecorator) {
+  absl::Cleanup cleanup =
+      [old_decorator = absl::debugging_internal::SetSymbolDecoratorFactory(
+           &TestSymbolDecorator<'a'>::Factory)] {
+        absl::debugging_internal::SetSymbolDecoratorFactory(old_decorator);
+      };
+
+  EXPECT_STREQ("nonstatic_func hello a",
+               TrySymbolize(reinterpret_cast<void*>(&nonstatic_func)));
+
+  EXPECT_EQ(absl::debugging_internal::SetSymbolDecoratorFactory(
+                &TestSymbolDecorator<'b'>::Factory),
+            &TestSymbolDecorator<'a'>::Factory);
+
+  EXPECT_STREQ("nonstatic_func hello b",
+               TrySymbolize(reinterpret_cast<void*>(&nonstatic_func)));
+}
+
 // Some versions of Clang with optimizations enabled seem to be able
 // to optimize away the .data section if no variables live in the
 // section. This variable should get placed in the .data section, and
diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc
index db24456..1ba5bf4 100644
--- a/absl/debugging/symbolize_unimplemented.inc
+++ b/absl/debugging/symbolize_unimplemented.inc
@@ -14,16 +14,20 @@
 
 #include <cstdint>
 
-#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/internal/symbolize.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
 namespace debugging_internal {
 
-int InstallSymbolDecorator(SymbolDecorator, void*) { return -1; }
+int InstallSymbolDecorator(LegacySymbolDecorator, void*) { return -1; }
 bool RemoveSymbolDecorator(int) { return false; }
 bool RemoveAllSymbolDecorators(void) { return false; }
+
+SymbolDecorator::Factory* SetSymbolDecoratorFactory(SymbolDecorator::Factory*) {
+  return nullptr;
+}
 bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {
   return false;
 }
diff --git a/absl/status/internal/status_matchers.h b/absl/status/internal/status_matchers.h
index eb61d73..2eafd13 100644
--- a/absl/status/internal/status_matchers.h
+++ b/absl/status/internal/status_matchers.h
@@ -126,18 +126,24 @@
 class StatusCode {
  public:
   /*implicit*/ StatusCode(int code)  // NOLINT
-      : code_(static_cast<::absl::StatusCode>(code)) {}
-  /*implicit*/ StatusCode(::absl::StatusCode code) : code_(code) {}  // NOLINT
+      : code_(code) {}
+  /*implicit*/ StatusCode(::absl::StatusCode code)  // NOLINT
+      : code_(static_cast<int>(code)) {}
 
   explicit operator int() const { return static_cast<int>(code_); }
 
   friend inline void PrintTo(const StatusCode& code, std::ostream* os) {
-    // TODO(b/321095377): Change this to print the status code as a string.
-    *os << static_cast<int>(code);
+    absl::string_view text =
+        absl::StatusCodeToStringView(static_cast<absl::StatusCode>(code.code_));
+    if (!text.empty()) {
+      *os << text;
+    } else {
+      *os << code.code_;
+    }
   }
 
  private:
-  ::absl::StatusCode code_;
+  int code_;
 };
 
 // Relational operators to handle matchers like Eq, Lt, etc..
diff --git a/absl/status/status_matchers_test.cc b/absl/status/status_matchers_test.cc
index 8656b2d..54cc733 100644
--- a/absl/status/status_matchers_test.cc
+++ b/absl/status/status_matchers_test.cc
@@ -122,10 +122,9 @@
               StatusIs(absl::StatusCode::kInvalidArgument, "ungueltig"));
 
   auto m = StatusIs(absl::StatusCode::kInternal, "internal error");
-  EXPECT_THAT(
-      ::testing::DescribeMatcher<absl::Status>(m),
-      MatchesRegex(
-          "has a status code that .*, and has an error message that .*"));
+  EXPECT_THAT(::testing::DescribeMatcher<absl::Status>(m),
+              MatchesRegex("has a status code that is equal to INTERNAL, and "
+                           "has an error message that .*"));
   EXPECT_THAT(
       ::testing::DescribeMatcher<absl::Status>(m, /*negation=*/true),
       MatchesRegex(
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 6281438..00e75de 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -17,15 +17,8 @@
 ** Thank you!
 */
 
-/*
-** Information about time zone files.
-*/
-
-#ifndef TZDEFRULES
-#define TZDEFRULES "posixrules"
-#endif /* !defined TZDEFRULES */
-
-/* See Internet RFC 9636 for more details about the following format.  */
+/* Information about time zone files.
+   See Internet RFC 9636 for more details about the following format.  */
 
 /*
 ** Each file begins with. . .
@@ -96,23 +89,25 @@
 */
 
 #ifndef TZ_MAX_TIMES
-/* This must be at least 242 for Europe/London with 'zic -b fat'.  */
+/* The following limit applies to localtime.c; zic has no such limit.
+   The limit must be at least 310 for Asia/Hebron with 'zic -b fat'.  */
 #define TZ_MAX_TIMES 2000
 #endif /* !defined TZ_MAX_TIMES */
 
 #ifndef TZ_MAX_TYPES
 /* This must be at least 18 for Europe/Vilnius with 'zic -b fat'.  */
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
+#define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636.  */
 #endif                   /* !defined TZ_MAX_TYPES */
 
 #ifndef TZ_MAX_CHARS
 /* This must be at least 40 for America/Anchorage.  */
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
-                        /* (limited by what unsigned chars can hold) */
-#endif                  /* !defined TZ_MAX_CHARS */
+#define TZ_MAX_CHARS 256 /* Maximum number of abbreviation characters */
+                         /* (limited to 256 by Internet RFC 9636) */
+#endif                   /* !defined TZ_MAX_CHARS */
 
 #ifndef TZ_MAX_LEAPS
-/* This must be at least 27 for leap seconds from 1972 through mid-2023.
+/* The following limit applies to localtime.c; zic has no such limit.
+   The limit must be at least 27 for leap seconds from 1972 through mid-2023.
    There's a plan to discontinue leap seconds by 2035.  */
 #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
 #endif                  /* !defined TZ_MAX_LEAPS */
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index cb3be9a..5d91260 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2025c
+2026a
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
index 166e434..247caa6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
index 9152e68..a60bddd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
index 9152e68..a60bddd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
index 1d64b39..aa3a64f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
@@ -166,9 +166,6 @@
 # +02/+03 - EET/EEST (Lebanon DST)
 XX	+3353+03530	Asia/Beirut	Lebanon
 #
-# +02/+03 - EET/EEST (Moldova DST)
-XX	+4700+02850	Europe/Chisinau	Moldova
-#
 # +02/+03 - EET/EEST (Palestine DST)
 XX	+3130+03428	Asia/Gaza	Palestine
 #
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index a52c358..19709a5 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -51,6 +51,32 @@
 )
 
 cc_library(
+    name = "source_location",
+    hdrs = ["source_location.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:nullability",
+    ],
+)
+
+cc_test(
+    name = "source_location_test",
+    size = "small",
+    srcs = ["source_location_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":source_location",
+        "//absl/base:config",
+        "//absl/strings:string_view",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "span",
     srcs = [
         "internal/span.h",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 75dd07d..f69a1ea 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -129,6 +129,32 @@
 
 absl_cc_library(
   NAME
+    source_location
+  HDRS
+    "source_location.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::nullability
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    source_location_test
+  SRCS
+    "source_location_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::source_location
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
     compare
   HDRS
     "compare.h"
diff --git a/absl/types/source_location.h b/absl/types/source_location.h
new file mode 100644
index 0000000..6e14836
--- /dev/null
+++ b/absl/types/source_location.h
@@ -0,0 +1,172 @@
+// Copyright 2017 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.
+//
+// -----------------------------------------------------------------------------
+// File: source_location.h
+// -----------------------------------------------------------------------------
+//
+// absl::SourceLocation provides source-code location info for C++17 and later.
+//
+// Critically, it is a **view type** (like std::string_view). Unlike
+// std::source_location, it is not permanently valid and must not outlive its
+// source. Using an invalid location is an error and may result in warnings
+// or crashes.
+//
+// Additionally, it does not guarantee the retention of all caller information
+// (e.g. column or function name) and may e.g. return unspecified values for
+// performance reasons.
+//
+// To define a function that has access to the source location of the
+// callsite, define it with a parameter of type `absl::SourceLocation`. The
+// caller can then invoke the function, passing
+// `absl::SourceLocation::current()` as the argument.
+//
+// If at all possible, make the `absl::SourceLocation` parameter be the
+// function's last parameter. That way, when `std::source_location` is
+// available, you will be able to switch to it, and give the parameter a default
+// argument of `std::source_location::current()`. Users will then be able to
+// omit that argument, and the default will automatically capture the location
+// of the callsite.
+
+#ifndef ABSL_TYPES_SOURCE_LOCATION_H_
+#define ABSL_TYPES_SOURCE_LOCATION_H_
+
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/nullability.h"
+
+// This needs to come after absl/base/config.h, which is responsible for
+// defining ABSL_HAVE_STD_SOURCE_LOCATION
+#ifdef ABSL_HAVE_STD_SOURCE_LOCATION
+#include <source_location>  // NOLINT(build/c++20)
+#endif
+
+// For OSS release, whether to alias to std::source_location is configurable via
+// config.h/options.h, similar to std::string_view/variant/etc.
+#if defined(ABSL_USES_STD_SOURCE_LOCATION) && \
+    defined(ABSL_HAVE_STD_SOURCE_LOCATION)
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+using SourceLocation = std::source_location;
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#else  // ABSL_HAVE_STD_SOURCE_LOCATION
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// C++17-compatible class representing a specific location in the source code of
+// a program. Similar to std::source_location, but with a few key differences
+// explained above.
+class SourceLocation {
+  struct PrivateTag {
+   private:
+    explicit PrivateTag() = default;
+    friend class SourceLocation;
+  };
+
+ public:
+  // Avoid this constructor; it populates the object with dummy values.
+  SourceLocation() = default;
+
+#ifdef ABSL_HAVE_STD_SOURCE_LOCATION
+  constexpr SourceLocation(  // NOLINT(google-explicit-constructor)
+      std::source_location loc)
+      : SourceLocation(loc.line(), loc.file_name()) {}
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE
+  // SourceLocation::current
+  //
+  // Creates a `SourceLocation` based on the current source location. Currently,
+  // it only captures file and line information for efficiency purposes, but
+  // that is subject to change. APIs that accept a `SourceLocation` as a default
+  // parameter can use this to capture their caller's locations.
+  //
+  // Example:
+  //
+  //   void TracedAdd(int i, SourceLocation loc = SourceLocation::current()) {
+  //     std::cout << loc.file_name() << ":" << loc.line() << " added " << i;
+  //     ...
+  //   }
+  //
+  //   void UserCode() {
+  //     TracedAdd(1);
+  //     TracedAdd(2);
+  //   }
+  static constexpr SourceLocation current(
+      PrivateTag = PrivateTag{}, std::uint_least32_t line = __builtin_LINE(),
+      const char* absl_nonnull file_name = __builtin_FILE()) {
+    return SourceLocation(line, file_name);
+  }
+#else
+  // Creates a dummy `SourceLocation` of "<source_location>" at line number 1,
+  // if no `SourceLocation::current()` implementation is available.
+  static constexpr SourceLocation current() {
+    return SourceLocation(1, "<source_location>");
+  }
+#endif
+  // The line number of the captured source location, or an unspecified value
+  // if this information is not available.
+  constexpr std::uint_least32_t line() const noexcept { return line_; }
+
+  // The column number of the captured source location, or an unspecified value
+  // if this information is not available.
+  constexpr std::uint_least32_t column() const noexcept { return 0; }
+
+  // The file name of the captured source location, or an unspecified string
+  // if this information is not available. Guaranteed to never be NULL.
+  constexpr const char* absl_nonnull file_name() const noexcept {
+    return file_name_;
+  }
+
+  // The function name of the captured source location, or an unspecified string
+  // if this information is not available. Guaranteed to never be NULL.
+  //
+  // NOTE: Currently, we deliberately avoid providing the function name, as it
+  // can bloat binary sizes and is non-critical. This may change in the future.
+  constexpr const char* absl_nonnull function_name() const noexcept {
+    return "";
+  }
+
+ private:
+  // `file_name` must outlive all copies of the `absl::SourceLocation` object,
+  // so in practice it should be a string literal.
+  constexpr SourceLocation(std::uint_least32_t line,
+                           const char* absl_nonnull file_name)
+      : line_(line), file_name_(file_name) {}
+
+  // We would use [[maybe_unused]] here, but it doesn't work on all supported
+  // toolchains at the moment.
+  friend constexpr int UseUnused() {
+    static_assert(SourceLocation(0, nullptr).unused_column_ == 0,
+                  "Use the otherwise-unused member.");
+    return 0;
+  }
+
+  // "unused" members are present to minimize future changes in the size of this
+  // type.
+  std::uint_least32_t line_ = 0;
+  std::uint_least32_t unused_column_ = 0;
+  const char* absl_nonnull file_name_ = "";
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+#endif  // ABSL_HAVE_STD_SOURCE_LOCATION
+
+#endif  // ABSL_TYPES_SOURCE_LOCATION_H_
diff --git a/absl/types/source_location_test.cc b/absl/types/source_location_test.cc
new file mode 100644
index 0000000..a312aa9
--- /dev/null
+++ b/absl/types/source_location_test.cc
@@ -0,0 +1,139 @@
+// Copyright 2017 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/types/source_location.h"
+
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_STD_SOURCE_LOCATION
+#include <source_location>  // NOLINT(build/c++20)
+#endif
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+
+using ::absl::SourceLocation;
+using ::testing::EndsWith;
+
+TEST(SourceLocationTest, DefaultConstructionWorks) {
+  static_assert(!std::is_trivially_default_constructible_v<SourceLocation>);
+  static_assert(std::is_nothrow_default_constructible_v<SourceLocation>);
+  constexpr SourceLocation loc1 [[maybe_unused]];
+  SourceLocation loc2 [[maybe_unused]]{};
+  EXPECT_EQ(loc1.line(), loc2.line());
+}
+
+#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE
+
+TEST(SourceLocationTest, ConstexprMembers) {
+  constexpr SourceLocation loc1 = absl::SourceLocation::current();
+  const SourceLocation loc2 = absl::SourceLocation::current();
+  EXPECT_EQ(loc1.line(), loc2.line() - 1);
+  EXPECT_EQ(absl::string_view(loc1.file_name()), loc2.file_name());
+}
+
+TEST(SourceLocationTest, ConversionFromStdSourceLocationWorks) {
+#ifndef ABSL_HAVE_STD_SOURCE_LOCATION
+  GTEST_SKIP() << "std::source_location is not available";
+#else
+  constexpr SourceLocation loc1 = std::source_location::current();
+  const std::source_location loc2 = std::source_location::current();
+  EXPECT_EQ(loc1.line(), loc2.line() - 1);
+  EXPECT_EQ(absl::string_view(loc1.file_name()), loc2.file_name());
+#endif
+}
+
+TEST(SourceLocationTest, CopyConstructionWorks) {
+  constexpr SourceLocation location = absl::SourceLocation::current();
+  constexpr int line = __LINE__ - 1;
+
+  EXPECT_EQ(location.line(), line);
+  EXPECT_THAT(location.file_name(), EndsWith("source_location_test.cc"));
+}
+
+TEST(SourceLocationTest, CopyAssignmentWorks) {
+  SourceLocation location;
+  location = absl::SourceLocation::current();
+  constexpr int line = __LINE__ - 1;
+
+  EXPECT_EQ(location.line(), line);
+  EXPECT_THAT(location.file_name(), EndsWith("source_location_test.cc"));
+}
+
+SourceLocation Echo(const SourceLocation& location) { return location; }
+
+TEST(SourceLocationTest, ExpectedUsageWorks) {
+  SourceLocation location = Echo(absl::SourceLocation::current());
+  constexpr int line = __LINE__ - 1;
+
+  EXPECT_EQ(location.line(), line);
+  EXPECT_THAT(location.file_name(), EndsWith("source_location_test.cc"));
+}
+
+TEST(SourceLocationTest, CurrentWorks) {
+  constexpr SourceLocation location = SourceLocation::current();
+  constexpr int line = __LINE__ - 1;
+
+  EXPECT_EQ(location.line(), line);
+  EXPECT_THAT(location.file_name(), EndsWith("source_location_test.cc"));
+}
+
+SourceLocation FuncWithDefaultParam(
+    SourceLocation loc = SourceLocation::current()) {
+  return loc;
+}
+
+TEST(SourceLocationTest, CurrentWorksAsDefaultParam) {
+  SourceLocation location = FuncWithDefaultParam();
+  constexpr int line = __LINE__ - 1;
+
+  EXPECT_EQ(location.line(), line);
+  EXPECT_THAT(location.file_name(), EndsWith("source_location_test.cc"));
+}
+
+#endif
+
+template <typename T>
+bool TryPassLineAndFile(decltype(T::current(0, ""))*) {
+  return true;
+}
+template <typename T>
+bool TryPassLineAndFile(decltype(T::current({}, 0, ""))*) {
+  return true;
+}
+template <typename T>
+bool TryPassLineAndFile(decltype(T::current(typename T::Tag{}, 0, ""))*) {
+  return true;
+}
+template <typename T>
+bool TryPassLineAndFile(...) {
+  return false;
+}
+
+TEST(SourceLocationTest, CantPassLineAndFile) {
+#ifdef ABSL_HAVE_STD_SOURCE_LOCATION
+  using StdSourceLocation = std::source_location;
+#else
+  using StdSourceLocation = void;
+#endif
+  if constexpr (!std::is_same_v<absl::SourceLocation, StdSourceLocation>) {
+    EXPECT_FALSE(TryPassLineAndFile<absl::SourceLocation>(nullptr));
+  }
+}
+
+}  // namespace
diff --git a/ci/absl_alternate_options.h b/ci/absl_alternate_options.h
index d5567f3..7f70aad 100644
--- a/ci/absl_alternate_options.h
+++ b/ci/absl_alternate_options.h
@@ -20,6 +20,7 @@
 #ifndef ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_
 #define ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_
 
+#define ABSL_OPTION_USE_STD_SOURCE_LOCATION 0
 #define ABSL_OPTION_USE_STD_ORDERING 0
 #define ABSL_OPTION_USE_INLINE_NAMESPACE 1
 #define ABSL_OPTION_INLINE_NAMESPACE_NAME ns