Skip to content

[libc] add basic lifetime annotations for support data structures #145933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions libc/src/__support/CPP/algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

template <class T> LIBC_INLINE constexpr const T &max(const T &a, const T &b) {
template <class T>
LIBC_INLINE constexpr const T &max(LIBC_LIFETIMEBOUND const T &a,
LIBC_LIFETIMEBOUND const T &b) {
return (a < b) ? b : a;
}

template <class T> LIBC_INLINE constexpr const T &min(const T &a, const T &b) {
template <class T>
LIBC_INLINE constexpr const T &min(LIBC_LIFETIMEBOUND const T &a,
LIBC_LIFETIMEBOUND const T &b) {
return (a < b) ? a : b;
}

Expand Down
19 changes: 13 additions & 6 deletions libc/src/__support/CPP/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,22 @@ template <class T, size_t N> 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];
}

Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/CPP/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ template <typename T> struct Atomic {
LIBC_INLINE void set(T rhs) { val = rhs; }
};

template <typename T> struct AtomicRef {
template <typename T> struct LIBC_GSL_POINTER AtomicRef {
static_assert(is_trivially_copyable_v<T> && is_copy_constructible_v<T> &&
is_move_constructible_v<T> && is_copy_assignable_v<T> &&
is_move_assignable_v<T>,
Expand Down
10 changes: 7 additions & 3 deletions libc/src/__support/CPP/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -28,14 +29,17 @@ template <typename MutexType> 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;
Expand Down
12 changes: 8 additions & 4 deletions libc/src/__support/CPP/optional.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,13 @@ template <typename T> 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;
Expand All @@ -122,10 +124,12 @@ template <typename T> 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*() && {
Expand Down
7 changes: 4 additions & 3 deletions libc/src/__support/CPP/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace cpp {
// - No implicit type conversion (e.g. Span<B>, initialized with As where A
// inherits from B),
// - No reverse iterators
template <typename T> class span {
template <typename T> class LIBC_GSL_POINTER span {
template <typename U>
LIBC_INLINE_VAR static constexpr bool is_const_view_v =
!cpp::is_const_v<U> && cpp::is_const_v<T> &&
Expand Down Expand Up @@ -64,11 +64,12 @@ template <typename T> class span {

template <typename U, size_t N,
cpp::enable_if_t<is_compatible_v<U>, 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 <typename U, size_t N,
cpp::enable_if_t<is_compatible_v<U>, bool> = true>
LIBC_INLINE constexpr span(array<U, N> &arr)
LIBC_INLINE constexpr span(LIBC_LIFETIMEBOUND array<U, N> &arr)
: span_data(arr.data()), span_size(arr.size()) {}

template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
Expand Down
19 changes: 13 additions & 6 deletions libc/src/__support/CPP/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }

Expand Down
6 changes: 5 additions & 1 deletion libc/src/__support/CPP/string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -77,6 +77,10 @@ class string_view {
LIBC_INLINE constexpr string_view(const char *Str, size_t N)
: Data(Str), Len(N) {}

template <size_t N>
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.
Expand Down
4 changes: 3 additions & 1 deletion libc/src/__support/CPP/stringstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 4 additions & 2 deletions libc/src/__support/CPP/utility/forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ namespace cpp {

// forward
template <typename T>
LIBC_INLINE constexpr T &&forward(remove_reference_t<T> &value) {
LIBC_INLINE constexpr T &&
forward(LIBC_LIFETIMEBOUND remove_reference_t<T> &value) {
return static_cast<T &&>(value);
}

template <typename T>
LIBC_INLINE constexpr T &&forward(remove_reference_t<T> &&value) {
LIBC_INLINE constexpr T &&
forward(LIBC_LIFETIMEBOUND remove_reference_t<T> &&value) {
static_assert(!is_lvalue_reference_v<T>,
"cannot forward an rvalue as an lvalue");
return static_cast<T &&>(value);
Expand Down
3 changes: 2 additions & 1 deletion libc/src/__support/CPP/utility/move.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ namespace cpp {

// move
template <class T>
LIBC_INLINE constexpr cpp::remove_reference_t<T> &&move(T &&t) {
LIBC_INLINE constexpr cpp::remove_reference_t<T> &&
move(LIBC_LIFETIMEBOUND T &&t) {
return static_cast<typename cpp::remove_reference_t<T> &&>(t);
}

Expand Down
24 changes: 24 additions & 0 deletions libc/src/__support/macros/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading