Skip to content

Commit dd313d3

Browse files
hokeinschilkp
authored andcommitted
Add clang::lifetimebound annotation to ArrayRef constructors. (llvm#113547)
This enables clang to detect more dangling issues. ``` ArrayRef<int> func() { constexpr int array[] = {...}; // oops, missing the static return array; // return a dangling reference, bomb. } ``` See llvm#113533.
1 parent e2e867e commit dd313d3

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

llvm/include/llvm/ADT/ArrayRef.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,16 @@ namespace llvm {
7070
/*implicit*/ ArrayRef(std::nullopt_t) {}
7171

7272
/// Construct an ArrayRef from a single element.
73-
/*implicit*/ ArrayRef(const T &OneElt)
74-
: Data(&OneElt), Length(1) {}
73+
/*implicit*/ ArrayRef(const T &OneElt LLVM_LIFETIME_BOUND)
74+
: Data(&OneElt), Length(1) {}
7575

7676
/// Construct an ArrayRef from a pointer and length.
77-
constexpr /*implicit*/ ArrayRef(const T *data, size_t length)
77+
constexpr /*implicit*/ ArrayRef(const T *data LLVM_LIFETIME_BOUND,
78+
size_t length)
7879
: Data(data), Length(length) {}
7980

8081
/// Construct an ArrayRef from a range.
81-
constexpr ArrayRef(const T *begin, const T *end)
82+
constexpr ArrayRef(const T *begin LLVM_LIFETIME_BOUND, const T *end)
8283
: Data(begin), Length(end - begin) {
8384
assert(begin <= end);
8485
}
@@ -103,7 +104,8 @@ namespace llvm {
103104

104105
/// Construct an ArrayRef from a C array.
105106
template <size_t N>
106-
/*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {}
107+
/*implicit*/ constexpr ArrayRef(const T (&Arr LLVM_LIFETIME_BOUND)[N])
108+
: Data(Arr), Length(N) {}
107109

108110
/// Construct an ArrayRef from a std::initializer_list.
109111
#if LLVM_GNUC_PREREQ(9, 0, 0)
@@ -113,7 +115,8 @@ namespace llvm {
113115
#pragma GCC diagnostic push
114116
#pragma GCC diagnostic ignored "-Winit-list-lifetime"
115117
#endif
116-
constexpr /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
118+
constexpr /*implicit*/ ArrayRef(
119+
std::initializer_list<T> Vec LLVM_LIFETIME_BOUND)
117120
: Data(Vec.begin() == Vec.end() ? (T *)nullptr : Vec.begin()),
118121
Length(Vec.size()) {}
119122
#if LLVM_GNUC_PREREQ(9, 0, 0)

llvm/include/llvm/Support/Compiler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,12 @@
307307
#define LLVM_GSL_POINTER
308308
#endif
309309

310+
#if LLVM_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
311+
#define LLVM_LIFETIME_BOUND [[clang::lifetimebound]]
312+
#else
313+
#define LLVM_LIFETIME_BOUND
314+
#endif
315+
310316
#if LLVM_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L
311317
#define LLVM_CTOR_NODISCARD [[nodiscard]]
312318
#else

0 commit comments

Comments
 (0)