1 // RUN: %clang_cc1 -std=c++2a -verify %s 2 3 namespace usage_invalid { 4 // FIXME: Should we diagnose a void return type? 5 void voidreturn(int ¶m [[clang::lifetimebound]]); 6 7 int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}} 8 struct A { 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}} 14 }; 15 int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}} 16 } 17 18 namespace usage_ok { 19 struct IntRef { int *target; }; 20 21 int &refparam(int ¶m [[clang::lifetimebound]]); 22 int &classparam(IntRef param [[clang::lifetimebound]]); 23 24 // Do not diagnose non-void return types; they can still be lifetime-bound. ptrintcast(int & param)25 long long ptrintcast(int ¶m [[clang::lifetimebound]]) { 26 return (long long)¶m; 27 } 28 // Likewise. intptrcast(long long param)29 int &intptrcast(long long param [[clang::lifetimebound]]) { 30 return *(int*)param; 31 } 32 33 struct A { 34 A(); 35 A(int); 36 int *class_member() [[clang::lifetimebound]]; 37 operator int*() [[clang::lifetimebound]]; 38 }; 39 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}} 43 } 44 45 # 1 "<std>" 1 3 46 namespace std { 47 using size_t = __SIZE_TYPE__; 48 struct string { 49 string(); 50 string(const char*); 51 52 char &operator[](size_t) const [[clang::lifetimebound]]; 53 }; 54 string operator""s(const char *, size_t); 55 56 struct string_view { 57 string_view(); 58 string_view(const char *p [[clang::lifetimebound]]); 59 string_view(const string &s [[clang::lifetimebound]]); 60 }; 61 string_view operator""sv(const char *, size_t); 62 63 struct vector { 64 int *data(); 65 size_t size(); 66 }; 67 68 template<typename K, typename V> struct map {}; 69 } 70 # 68 "attr-lifetimebound.cpp" 2 71 72 using std::operator""s; 73 using std::operator""sv; 74 75 namespace p0936r0_examples { 76 std::string_view s = "foo"s; // expected-warning {{temporary}} 77 78 std::string operator+(std::string_view s1, std::string_view s2); f()79 void f() { 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? 83 } 84 85 struct X { int a, b; }; f(const X & x)86 const int &f(const X &x [[clang::lifetimebound]]) { return x.a; } 87 const int &r = f(X()); // expected-warning {{temporary}} 88 89 char &c = std::string("hello my pretty long strong")[0]; // expected-warning {{temporary}} 90 91 struct reversed_range { 92 int *begin(); 93 int *end(); 94 int *p; 95 std::size_t n; 96 }; reversed(R && r)97 template <typename R> reversed_range reversed(R &&r [[clang::lifetimebound]]) { 98 return reversed_range{r.data(), r.size()}; 99 } 100 101 std::vector make_vector(); use_reversed_range()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}} 105 } 106 107 template <typename K, typename V> 108 const V &findOrDefault(const std::map<K, V> &m [[clang::lifetimebound]], 109 const K &key, 110 const V &defvalue [[clang::lifetimebound]]); 111 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'}} 115 } 116