diff --git a/absl/status/status.cc b/absl/status/status.cc index 577dea4bbd2..911f4b2869c 100644 --- a/absl/status/status.cc +++ b/absl/status/status.cc @@ -46,6 +46,10 @@ namespace absl { ABSL_NAMESPACE_BEGIN +static_assert( + alignof(status_internal::StatusRep) >= 4, + "absl::Status assumes it can use the bottom 2 bits of a StatusRep*."); + std::string StatusCodeToString(StatusCode code) { switch (code) { case StatusCode::kOk: diff --git a/absl/status/status.h b/absl/status/status.h index 595064c0f1d..2dac2fea7c7 100644 --- a/absl/status/status.h +++ b/absl/status/status.h @@ -51,10 +51,15 @@ #ifndef ABSL_STATUS_STATUS_H_ #define ABSL_STATUS_STATUS_H_ +#include +#include #include #include #include +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" #include "absl/functional/function_ref.h" #include "absl/status/internal/status_internal.h" #include "absl/strings/cord.h" @@ -644,13 +649,13 @@ class Status final { std::string ToStringSlow(StatusToStringMode mode) const; // Status supports two different representations. - // - When the low bit is off it is an inlined representation. + // - When the low bit is set it is an inlined representation. // It uses the canonical error space, no message or payload. // The error code is (rep_ >> 2). // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom(). - // - When the low bit is on it is an external representation. + // - When the low bit is off it is an external representation. // In this case all the data comes from a heap allocated Rep object. - // (rep_ - 1) is a status_internal::StatusRep* pointer to that structure. + // rep_ is a status_internal::StatusRep* pointer to that structure. uintptr_t rep_; }; @@ -839,18 +844,16 @@ inline status_internal::Payloads* Status::GetPayloads() { return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); } -inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; } +inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; } -inline bool Status::IsMovedFrom(uintptr_t rep) { - return IsInlined(rep) && (rep & 2) != 0; -} +inline bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; } inline uintptr_t Status::MovedFromRep() { return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; } inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { - return static_cast(code) << 2; + return (static_cast(code) << 2) + 1; } inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { @@ -860,11 +863,11 @@ inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { assert(!IsInlined(rep)); - return reinterpret_cast(rep - 1); + return reinterpret_cast(rep); } inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { - return reinterpret_cast(rep) + 1; + return reinterpret_cast(rep); } inline void Status::Ref(uintptr_t rep) {