1 // RUN: %clang_cc1 -std=c++2a -verify %s
3 namespace usage_invalid
{
4 // FIXME: Should we diagnose a void return type?
5 void voidreturn(int ¶m
[[clang::lifetimebound
]]);
7 int *not_class_member() [[clang::lifetimebound
]]; // expected-error {{non-member function has no implicit object parameter}}
9 A() [[clang::lifetimebound
]]; // expected-error {{cannot be applied to a constructor}}
10 ~A() [[clang::lifetimebound
]]; // expected-error {{cannot be applied to a destructor}}
11 static int *static_class_member() [[clang::lifetimebound
]]; // expected-error {{static member function has no implicit object parameter}}
12 int not_function
[[clang::lifetimebound
]]; // expected-error {{only applies to parameters and implicit object parameters}}
13 int [[clang::lifetimebound
]] also_not_function
; // expected-error {{cannot be applied to types}}
15 int *attr_with_param(int ¶m
[[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
19 struct IntRef
{ int *target
; };
21 int &refparam(int ¶m
[[clang::lifetimebound
]]);
22 int &classparam(IntRef param
[[clang::lifetimebound
]]);
24 // Do not diagnose non-void return types; they can still be lifetime-bound.
25 long long ptrintcast(int ¶m
[[clang::lifetimebound
]]) {
26 return (long long)¶m
;
29 int &intptrcast(long long param
[[clang::lifetimebound
]]) {
36 int *class_member() [[clang::lifetimebound
]];
37 operator int*() [[clang::lifetimebound
]];
40 int *p
= A().class_member(); // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}
41 int *q
= A(); // expected-warning {{temporary whose address is used as value of local variable 'q' will be destroyed at the end of the full-expression}}
42 int *r
= A(1); // expected-warning {{temporary whose address is used as value of local variable 'r' will be destroyed at the end of the full-expression}}
47 using size_t = __SIZE_TYPE__
;
52 char &operator[](size_t) const [[clang::lifetimebound
]];
54 string
operator""s(const char *, size_t);
58 string_view(const char *p
[[clang::lifetimebound
]]);
59 string_view(const string
&s
[[clang::lifetimebound
]]);
61 string_view
operator""sv(const char *, size_t);
68 template<typename K
, typename V
> struct map
{};
70 # 68 "attr-lifetimebound.cpp" 2
72 using std::operator""s
;
73 using std::operator""sv
;
75 namespace p0936r0_examples
{
76 std::string_view s
= "foo"s
; // expected-warning {{temporary}}
78 std::string
operator+(std::string_view s1
, std::string_view s2
);
80 std::string_view sv
= "hi";
81 std::string_view sv2
= sv
+ sv
; // expected-warning {{temporary}}
82 sv2
= sv
+ sv
; // FIXME: can we infer that we should warn here too?
85 struct X
{ int a
, b
; };
86 const int &f(const X
&x
[[clang::lifetimebound
]]) { return x
.a
; }
87 const int &r
= f(X()); // expected-warning {{temporary}}
89 char &c
= std::string("hello my pretty long strong")[0]; // expected-warning {{temporary}}
91 struct reversed_range
{
97 template <typename R
> reversed_range
reversed(R
&&r
[[clang::lifetimebound
]]) {
98 return reversed_range
{r
.data(), r
.size()};
101 std::vector
make_vector();
102 void use_reversed_range() {
103 // FIXME: Don't expose the name of the internal range variable.
104 for (auto x
: reversed(make_vector())) {} // expected-warning {{temporary implicitly bound to local reference will be destroyed at the end of the full-expression}}
107 template <typename K
, typename V
>
108 const V
&findOrDefault(const std::map
<K
, V
> &m
[[clang::lifetimebound
]],
110 const V
&defvalue
[[clang::lifetimebound
]]);
112 // FIXME: Maybe weaken the wording here: "local reference 'v' could bind to temporary that will be destroyed at end of full-expression"?
113 std::map
<std::string
, std::string
> m
;
114 const std::string
&v
= findOrDefault(m
, "foo"s
, "bar"s
); // expected-warning {{temporary bound to local reference 'v'}}
117 // definitions for std::move, std::forward et al.
119 inline namespace foo
{
121 template <class T
> struct remove_reference
{
124 template <class T
> struct remove_reference
<T
&> {
127 template <class T
> struct remove_reference
<T
&&> {
131 template <class T
> constexpr typename remove_reference
<T
>::type
&&move(T
&&t
) {
132 return static_cast<typename remove_reference
<T
>::type
>(t
);
136 constexpr T
&&forward(typename remove_reference
<T
>::type
&t
) {
137 return static_cast<T
&&>(t
);
141 constexpr T
&&forward(typename remove_reference
<T
>::type
&&t
) {
142 return static_cast<T
&&>(t
);
145 template <class T
> constexpr const T
&as_const(T
&x
) { return x
; }
147 template <class T
, bool RValueRef
> struct PickRef
{
148 using type
= typename remove_reference
<T
>::type
&;
150 template <class T
> struct PickRef
<T
, true> {
151 using type
= typename remove_reference
<T
>::type
&&;
154 template <class T
> struct is_lvalue_reference
{
155 static constexpr bool value
= false;
158 template <class T
> struct is_lvalue_reference
<T
&> {
159 static constexpr bool value
= true;
162 template <class T
> struct is_const
{
163 static constexpr bool value
= false;
166 template <class T
> struct is_const
<const T
> {
167 static constexpr bool value
= true;
170 template <bool B
, class T
, class F
> struct conditional
{
174 template <class T
, class F
> struct conditional
<false, T
, F
> {
178 template <class U
, class T
>
179 using CopyConst
= typename conditional
<is_const
<remove_reference
<U
>>::value
,
182 template <class U
, class T
>
184 typename conditional
<is_lvalue_reference
<U
&&>::value
,
185 typename remove_reference
<T
>::type
&,
186 typename remove_reference
<T
>::type
&&>::type
;
188 template <class U
, class T
>
189 using ForwardLikeRetType
= OverrideRef
<U
&&, CopyConst
<U
, T
>>;
192 constexpr auto forward_like(auto &&t
) -> ForwardLikeRetType
<U
, decltype(t
)> {
193 return static_cast<ForwardLikeRetType
<U
, decltype(t
)>>(t
);
197 auto move_if_noexcept(T
&t
) ->
198 typename PickRef
<T
, noexcept(T(static_cast<T
&&>(t
)))>::type
{
200 typename PickRef
<T
, noexcept(T(static_cast<T
&&>(t
)))>::type
>(t
);
203 template <class T
> T
*addressof(T
&arg
) {
204 return reinterpret_cast<T
*>(
205 &const_cast<char &>(reinterpret_cast<const volatile char &>(arg
)));
211 namespace move_forward_et_al_examples
{
213 S
&self() [[clang::lifetimebound
]] { return *this; }
216 S
&&Move
= std::move(S
{}); // expected-warning {{temporary bound to local reference 'Move' will be destroyed at the end of the full-expression}}
217 S MoveOk
= std::move(S
{});
219 S
&&Forward
= std::forward
<S
&&>(S
{}); // expected-warning {{temporary bound to local reference 'Forward' will be destroyed at the end of the full-expression}}
220 S ForwardOk
= std::forward
<S
&&>(S
{});
222 S
&&ForwardLike
= std::forward_like
<int&&>(S
{}); // expected-warning {{temporary bound to local reference 'ForwardLike' will be destroyed at the end of the full-expression}}
223 S ForwardLikeOk
= std::forward_like
<int&&>(S
{});
225 const S
&Const
= std::as_const(S
{}.self()); // expected-warning {{temporary bound to local reference 'Const' will be destroyed at the end of the full-expression}}
226 const S ConstOk
= std::as_const(S
{}.self());
228 S
&&MoveIfNoExcept
= std::move_if_noexcept(S
{}.self()); // expected-warning {{temporary bound to local reference 'MoveIfNoExcept' will be destroyed at the end of the full-expression}}
229 S MoveIfNoExceptOk
= std::move_if_noexcept(S
{}.self());
231 S
*AddressOf
= std::addressof(S
{}.self()); // expected-warning {{temporary whose address is used as value of local variable 'AddressOf' will be destroyed at the end of the full-expression}}
233 S
*AddressOfOk
= std::addressof(X
);
234 } // namespace move_forward_et_al_examples