diff --git a/libc/src/__support/CPP/algorithm.h b/libc/src/__support/CPP/algorithm.h index 7704b3fa81f0c..3ea48db5b2d5e 100644 --- a/libc/src/__support/CPP/algorithm.h +++ b/libc/src/__support/CPP/algorithm.h @@ -18,11 +18,15 @@ namespace LIBC_NAMESPACE_DECL { namespace cpp { -template LIBC_INLINE constexpr const T &max(const T &a, const T &b) { +template +LIBC_INLINE constexpr const T &max(LIBC_LIFETIMEBOUND const T &a, + LIBC_LIFETIMEBOUND const T &b) { return (a < b) ? b : a; } -template LIBC_INLINE constexpr const T &min(const T &a, const T &b) { +template +LIBC_INLINE constexpr const T &min(LIBC_LIFETIMEBOUND const T &a, + LIBC_LIFETIMEBOUND const T &b) { return (a < b) ? a : b; } diff --git a/libc/src/__support/CPP/array.h b/libc/src/__support/CPP/array.h index db0a986b71205..b0c0add5f9727 100644 --- a/libc/src/__support/CPP/array.h +++ b/libc/src/__support/CPP/array.h @@ -31,15 +31,22 @@ template struct array { LIBC_INLINE constexpr T *data() { return Data; } LIBC_INLINE constexpr const T *data() const { return Data; } - LIBC_INLINE constexpr T &front() { return Data[0]; } - LIBC_INLINE constexpr const T &front() const { return Data[0]; } + LIBC_INLINE constexpr T &front() LIBC_LIFETIMEBOUND { return Data[0]; } + LIBC_INLINE constexpr const T &front() const LIBC_LIFETIMEBOUND { + return Data[0]; + } - LIBC_INLINE constexpr T &back() { return Data[N - 1]; } - LIBC_INLINE constexpr const T &back() const { return Data[N - 1]; } + LIBC_INLINE constexpr T &back() LIBC_LIFETIMEBOUND { return Data[N - 1]; } + LIBC_INLINE constexpr const T &back() const LIBC_LIFETIMEBOUND { + return Data[N - 1]; + } - LIBC_INLINE constexpr T &operator[](size_t Index) { return Data[Index]; } + LIBC_INLINE constexpr T &operator[](size_t Index) LIBC_LIFETIMEBOUND { + return Data[Index]; + } - LIBC_INLINE constexpr const T &operator[](size_t Index) const { + LIBC_INLINE constexpr const T & + operator[](size_t Index) const LIBC_LIFETIMEBOUND { return Data[Index]; } diff --git a/libc/src/__support/CPP/atomic.h b/libc/src/__support/CPP/atomic.h index 2f00b3ed32811..4e084beaf8ef5 100644 --- a/libc/src/__support/CPP/atomic.h +++ b/libc/src/__support/CPP/atomic.h @@ -255,7 +255,7 @@ template struct Atomic { LIBC_INLINE void set(T rhs) { val = rhs; } }; -template struct AtomicRef { +template struct LIBC_GSL_POINTER AtomicRef { static_assert(is_trivially_copyable_v && is_copy_constructible_v && is_move_constructible_v && is_copy_assignable_v && is_move_assignable_v, diff --git a/libc/src/__support/CPP/mutex.h b/libc/src/__support/CPP/mutex.h index 8a3102426e2d6..407125c6e452b 100644 --- a/libc/src/__support/CPP/mutex.h +++ b/libc/src/__support/CPP/mutex.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H #define LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H +#include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { @@ -28,14 +29,17 @@ template class lock_guard { public: // Calls `m.lock()` upon resource acquisition. - explicit lock_guard(MutexType &m) : mutex(m) { mutex.lock(); } + LIBC_INLINE explicit lock_guard(LIBC_LIFETIMEBOUND MutexType &m) : mutex(m) { + mutex.lock(); + } // Acquires ownership of the mutex object `m` without attempting to lock // it. The behavior is undefined if the current thread does not hold the // lock on `m`. Does not call `m.lock()` upon resource acquisition. - lock_guard(MutexType &m, adopt_lock_t /* t */) : mutex(m) {} + LIBC_INLINE lock_guard(LIBC_LIFETIMEBOUND MutexType &m, adopt_lock_t /* t */) + : mutex(m) {} - ~lock_guard() { mutex.unlock(); } + LIBC_INLINE ~lock_guard() { mutex.unlock(); } // non-copyable lock_guard &operator=(const lock_guard &) = delete; diff --git a/libc/src/__support/CPP/optional.h b/libc/src/__support/CPP/optional.h index aed2269db1b11..06cb0e3e992d1 100644 --- a/libc/src/__support/CPP/optional.h +++ b/libc/src/__support/CPP/optional.h @@ -108,11 +108,13 @@ template class optional { LIBC_INLINE constexpr void reset() { storage.reset(); } - LIBC_INLINE constexpr const T &value() const & { + LIBC_INLINE constexpr const T &value() const &LIBC_LIFETIMEBOUND { return storage.stored_value; } - LIBC_INLINE constexpr T &value() & { return storage.stored_value; } + LIBC_INLINE constexpr T &value() & LIBC_LIFETIMEBOUND { + return storage.stored_value; + } LIBC_INLINE constexpr explicit operator bool() const { return storage.in_use; @@ -122,10 +124,12 @@ template class optional { return &storage.stored_value; } LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; } - LIBC_INLINE constexpr const T &operator*() const & { + LIBC_INLINE constexpr const T &operator*() const &LIBC_LIFETIMEBOUND { + return storage.stored_value; + } + LIBC_INLINE constexpr T &operator*() & LIBC_LIFETIMEBOUND { return storage.stored_value; } - LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; } LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); } LIBC_INLINE constexpr T &&operator*() && { diff --git a/libc/src/__support/CPP/span.h b/libc/src/__support/CPP/span.h index 9234a26d201cd..c02a139299e51 100644 --- a/libc/src/__support/CPP/span.h +++ b/libc/src/__support/CPP/span.h @@ -28,7 +28,7 @@ namespace cpp { // - No implicit type conversion (e.g. Span, initialized with As where A // inherits from B), // - No reverse iterators -template class span { +template class LIBC_GSL_POINTER span { template LIBC_INLINE_VAR static constexpr bool is_const_view_v = !cpp::is_const_v && cpp::is_const_v && @@ -64,11 +64,12 @@ template class span { template , bool> = true> - LIBC_INLINE constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {} + LIBC_INLINE constexpr span(LIBC_LIFETIMEBOUND U (&arr)[N]) + : span_data(arr), span_size(N) {} template , bool> = true> - LIBC_INLINE constexpr span(array &arr) + LIBC_INLINE constexpr span(LIBC_LIFETIMEBOUND array &arr) : span_data(arr.data()), span_size(arr.size()) {} template , bool> = true> diff --git a/libc/src/__support/CPP/string.h b/libc/src/__support/CPP/string.h index 1ac04c7f1f9dc..59d5cffa0ddb9 100644 --- a/libc/src/__support/CPP/string.h +++ b/libc/src/__support/CPP/string.h @@ -106,16 +106,23 @@ class string { LIBC_INLINE constexpr const char *end() const { return data() + size_; } LIBC_INLINE char *end() { return data() + size_; } - LIBC_INLINE constexpr const char &front() const { return data()[0]; } - LIBC_INLINE char &front() { return data()[0]; } + LIBC_INLINE constexpr const char &front() const LIBC_LIFETIMEBOUND { + return data()[0]; + } + LIBC_INLINE char &front() LIBC_LIFETIMEBOUND { return data()[0]; } - LIBC_INLINE constexpr const char &back() const { return data()[size_ - 1]; } - LIBC_INLINE char &back() { return data()[size_ - 1]; } + LIBC_INLINE constexpr const char &back() const LIBC_LIFETIMEBOUND { + return data()[size_ - 1]; + } + LIBC_INLINE char &back() LIBC_LIFETIMEBOUND { return data()[size_ - 1]; } - LIBC_INLINE constexpr const char &operator[](size_t index) const { + LIBC_INLINE constexpr const char & + operator[](size_t index) const LIBC_LIFETIMEBOUND { + return data()[index]; + } + LIBC_INLINE char &operator[](size_t index) LIBC_LIFETIMEBOUND { return data()[index]; } - LIBC_INLINE char &operator[](size_t index) { return data()[index]; } LIBC_INLINE const char *c_str() const { return data(); } diff --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h index aa15814b2e149..bcdfe0eec4758 100644 --- a/libc/src/__support/CPP/string_view.h +++ b/libc/src/__support/CPP/string_view.h @@ -23,7 +23,7 @@ namespace cpp { // do the checks before invoking the methods. // // This class will be extended as needed in future. -class string_view { +class LIBC_GSL_POINTER string_view { private: const char *Data; size_t Len; @@ -77,6 +77,10 @@ class string_view { LIBC_INLINE constexpr string_view(const char *Str, size_t N) : Data(Str), Len(N) {} + template + LIBC_INLINE constexpr string_view(LIBC_LIFETIMEBOUND const char (&Str)[N]) + : Data(Str), Len(N) {} + LIBC_INLINE constexpr const char *data() const { return Data; } // Returns the size of the string_view. diff --git a/libc/src/__support/CPP/stringstream.h b/libc/src/__support/CPP/stringstream.h index a16084c848688..a0039f2de4858 100644 --- a/libc/src/__support/CPP/stringstream.h +++ b/libc/src/__support/CPP/stringstream.h @@ -48,7 +48,9 @@ class StringStream { // null terminator was not explicitly written, then the return value // will not include one. In order to produce a string_view to a null // terminated string, write ENDS explicitly. - string_view str() const { return string_view(data.data(), write_ptr); } + [[nodiscard]] LIBC_INLINE string_view str() const { + return string_view(data.data(), write_ptr); + } // Write the characters from |str| to the stream. StringStream &operator<<(string_view str) { diff --git a/libc/src/__support/CPP/utility/forward.h b/libc/src/__support/CPP/utility/forward.h index 085b3d16f999b..7383687d7b7c8 100644 --- a/libc/src/__support/CPP/utility/forward.h +++ b/libc/src/__support/CPP/utility/forward.h @@ -18,12 +18,14 @@ namespace cpp { // forward template -LIBC_INLINE constexpr T &&forward(remove_reference_t &value) { +LIBC_INLINE constexpr T && +forward(LIBC_LIFETIMEBOUND remove_reference_t &value) { return static_cast(value); } template -LIBC_INLINE constexpr T &&forward(remove_reference_t &&value) { +LIBC_INLINE constexpr T && +forward(LIBC_LIFETIMEBOUND remove_reference_t &&value) { static_assert(!is_lvalue_reference_v, "cannot forward an rvalue as an lvalue"); return static_cast(value); diff --git a/libc/src/__support/CPP/utility/move.h b/libc/src/__support/CPP/utility/move.h index b61f723e8d4cb..3bbc5f1df4498 100644 --- a/libc/src/__support/CPP/utility/move.h +++ b/libc/src/__support/CPP/utility/move.h @@ -17,7 +17,8 @@ namespace cpp { // move template -LIBC_INLINE constexpr cpp::remove_reference_t &&move(T &&t) { +LIBC_INLINE constexpr cpp::remove_reference_t && +move(LIBC_LIFETIMEBOUND T &&t) { return static_cast &&>(t); } diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h index c6474673de85a..72fb3bd6e204b 100644 --- a/libc/src/__support/macros/attributes.h +++ b/libc/src/__support/macros/attributes.h @@ -48,4 +48,28 @@ #define LIBC_PREFERED_TYPE(TYPE) #endif +#if __has_attribute(lifetimebound) +#define LIBC_LIFETIMEBOUND [[clang::lifetimebound]] +#else +#define LIBC_LIFETIMEBOUND +#endif + +#if __has_attribute(lifetime_capture_by) +#define LIBC_LIFETIME_CAPTURE_BY(X) [[clang::lifetime_capture_by(X)]] +#else +#define LIBC_LIFETIME_CAPTURE_BY(X) +#endif + +#if defined(__clang__) +#define LIBC_GSL_POINTER [[gsl::Pointer]] +#else +#define LIBC_GSL_POINTER +#endif + +#if defined(__clang__) +#define LIBC_GSL_OWNER [[gsl::Owner]] +#else +#define LIBC_GSL_OWNER +#endif + #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H