summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--absl/base/internal/raw_logging.h14
-rw-r--r--absl/base/macros.h11
-rw-r--r--absl/status/internal/statusor_internal.h9
-rw-r--r--absl/strings/internal/str_split_internal.h51
4 files changed, 40 insertions, 45 deletions
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index 2508f3cf..20f4291b 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -72,12 +72,14 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message) \
- do { \
- constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
- ::absl::raw_logging_internal::internal_log_function( \
- ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_filename, __LINE__, message); \
+#define ABSL_INTERNAL_LOG(severity, message) \
+ do { \
+ constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
+ ::absl::raw_logging_internal::internal_log_function( \
+ ABSL_RAW_LOGGING_INTERNAL_##severity, \
+ absl_raw_logging_internal_filename, __LINE__, message); \
+ if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
+ ABSL_INTERNAL_UNREACHABLE; \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
diff --git a/absl/base/macros.h b/absl/base/macros.h
index 02dd9ff4..3e085a91 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -144,4 +144,15 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
+// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
+// reaches one has undefined behavior, and the compiler may optimize
+// accordingly.
+#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_UNREACHABLE __assume(0)
+#else
+#define ABSL_INTERNAL_UNREACHABLE
+#endif
+
#endif // ABSL_BASE_MACROS_H_
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
index 7cc76256..eaac2c0b 100644
--- a/absl/status/internal/statusor_internal.h
+++ b/absl/status/internal/statusor_internal.h
@@ -17,6 +17,7 @@
#include <type_traits>
#include <utility>
+#include "absl/base/attributes.h"
#include "absl/meta/type_traits.h"
#include "absl/status/status.h"
#include "absl/utility/utility.h"
@@ -135,18 +136,14 @@ class Helper {
public:
// Move type-agnostic error handling to the .cc.
static void HandleInvalidStatusCtorArg(Status*);
- static void Crash(const absl::Status& status);
+ ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
};
// Construct an instance of T in `p` through placement new, passing Args... to
// the constructor.
// This abstraction is here mostly for the gcc performance fix.
template <typename T, typename... Args>
-void PlacementNew(void* p, Args&&... args) {
-#if defined(__GNUC__) && !defined(__clang__)
- // Teach gcc that 'p' cannot be null, fixing code size issues.
- if (p == nullptr) __builtin_unreachable();
-#endif
+ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
new (p) T(std::forward<Args>(args)...);
}
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 76924771..49ec5392 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -66,56 +66,41 @@ class ConvertibleToStringView {
// Matches rvalue strings and moves their data to a member.
ConvertibleToStringView(std::string&& s) // NOLINT(runtime/explicit)
- : copy_(std::move(s)), value_(copy_), self_referential_(true) {}
+ : copy_(std::move(s)), value_(copy_) {}
ConvertibleToStringView(const ConvertibleToStringView& other)
- : value_(other.value_), self_referential_(other.self_referential_) {
- if (other.self_referential_) {
- new (&copy_) std::string(other.copy_);
- value_ = copy_;
- }
- }
+ : copy_(other.copy_),
+ value_(other.IsSelfReferential() ? copy_ : other.value_) {}
- ConvertibleToStringView(ConvertibleToStringView&& other)
- : value_(other.value_), self_referential_(other.self_referential_) {
- if (other.self_referential_) {
- new (&copy_) std::string(std::move(other.copy_));
- value_ = copy_;
- }
+ ConvertibleToStringView(ConvertibleToStringView&& other) {
+ StealMembers(std::move(other));
}
ConvertibleToStringView& operator=(ConvertibleToStringView other) {
- this->~ConvertibleToStringView();
- new (this) ConvertibleToStringView(std::move(other));
+ StealMembers(std::move(other));
return *this;
}
absl::string_view value() const { return value_; }
- ~ConvertibleToStringView() { MaybeReleaseCopy(); }
-
private:
- void MaybeReleaseCopy() {
- if (self_referential_) {
- // An explicit destructor call cannot be a qualified name such as
- // std::string. The "using" declaration works around this
- // issue by creating an unqualified name for the destructor.
- using string_type = std::string;
- copy_.~string_type();
+ // Returns true if ctsp's value refers to its internal copy_ member.
+ bool IsSelfReferential() const { return value_.data() == copy_.data(); }
+
+ void StealMembers(ConvertibleToStringView&& other) {
+ if (other.IsSelfReferential()) {
+ copy_ = std::move(other.copy_);
+ value_ = copy_;
+ other.value_ = other.copy_;
+ } else {
+ value_ = other.value_;
}
}
- struct Unused { // MSVC disallows unions with only 1 member.
- };
+
// Holds the data moved from temporary std::string arguments. Declared first
// so that 'value' can refer to 'copy_'.
- union {
- std::string copy_;
- Unused unused_;
- };
-
+ std::string copy_;
absl::string_view value_;
- // true if value_ refers to the internal copy_ member.
- bool self_referential_ = false;
};
// An iterator that enumerates the parts of a string from a Splitter. The text