1// RUN: %check_clang_tidy -std=c++11,c++14 -check-suffix=,CXX14 %s bugprone-dangling-handle %t -- \
2// RUN: -config="{CheckOptions: \
3// RUN: {bugprone-dangling-handle.HandleClasses: \
4// RUN: 'std::basic_string_view; ::llvm::StringRef;'}}"
5
6// RUN: %check_clang_tidy -std=c++17-or-later -check-suffix=,CXX17 %s bugprone-dangling-handle %t -- \
7// RUN: -config="{CheckOptions: \
8// RUN: {bugprone-dangling-handle.HandleClasses: \
9// RUN: 'std::basic_string_view; ::llvm::StringRef;'}}"
10
11namespace std {
12
13template <typename T>
14class vector {
15 public:
16 using const_iterator = const T*;
17 using iterator = T*;
18 using size_type = int;
19
20 void assign(size_type count, const T& value);
21 iterator insert(const_iterator pos, const T& value);
22 iterator insert(const_iterator pos, T&& value);
23 iterator insert(const_iterator pos, size_type count, const T& value);
24 void push_back(const T&);
25 void push_back(T&&);
26 void resize(size_type count, const T& value);
27};
28
29template <typename, typename>
30class pair {};
31
32template <typename T>
33class set {
34 public:
35 using const_iterator = const T*;
36 using iterator = T*;
37
38 std::pair<iterator, bool> insert(const T& value);
39 std::pair<iterator, bool> insert(T&& value);
40 iterator insert(const_iterator hint, const T& value);
41 iterator insert(const_iterator hint, T&& value);
42};
43
44template <typename Key, typename Value>
45class map {
46 public:
47 using value_type = pair<Key, Value>;
48 value_type& operator[](const Key& key);
49 value_type& operator[](Key&& key);
50};
51
52class basic_string_view;
53
54class basic_string {
55 public:
56 basic_string();
57 basic_string(const char*);
58
59 typedef basic_string_view str_view;
60 operator str_view() const noexcept;
61
62 ~basic_string();
63};
64
65typedef basic_string string;
66
67class basic_string_view {
68 public:
69 basic_string_view(const char*);
70};
71
72typedef basic_string_view string_view;
73
74} // namespace std
75
76namespace llvm {
77
78class StringRef {
79 public:
80 StringRef();
81 StringRef(const char*);
82 StringRef(const std::string&);
83};
84
85} // namespace llvm
86
87std::string ReturnsAString();
88
89void Positives() {
90 std::string_view view1 = std::string();
91 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
92 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
93
94 std::string_view view_2 = ReturnsAString();
95 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
96 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:29: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
97
98 view1 = std::string();
99 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
100
101 const std::string& str_ref = "";
102 std::string_view view3 = true ? "A" : str_ref;
103 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
104 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives
105 view3 = true ? "A" : str_ref;
106 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
107
108 std::string_view view4(ReturnsAString());
109 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
110 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:26: warning: std::basic_string_view outlives
111
112 std::string_view view5 = std::string("test");
113 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
114 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
115
116 std::string_view view6 = std::string{"test"};
117 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
118 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
119}
120
121void OtherTypes() {
122 llvm::StringRef ref = std::string();
123 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
124 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:25: warning: llvm::StringRef outlives its value
125}
126
127const char static_array[] = "A";
128std::string_view ReturnStatements(int i, std::string value_arg,
129 const std::string &ref_arg) {
130 const char array[] = "A";
131 const char* ptr = "A";
132 std::string s;
133 static std::string ss;
134 switch (i) {
135 // Bad cases
136 case 0:
137 return array; // refers to local
138 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
139 case 1:
140 return s; // refers to local
141 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
142 case 2:
143 return std::string(); // refers to temporary
144 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
145 case 3:
146 return value_arg; // refers to by-value arg
147 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
148
149 // Ok cases
150 case 100:
151 return ss; // refers to static
152 case 101:
153 return static_array; // refers to static
154 case 102:
155 return ptr; // pointer is ok
156 case 103:
157 return ref_arg; // refers to by-ref arg
158 }
159
160 struct S {
161 std::string_view view() { return value; }
162 std::string value;
163 };
164
165 (void)[&]()->std::string_view {
166 // This should not warn. The string is bound by reference.
167 return s;
168 };
169 (void)[=]() -> std::string_view {
170 // This should not warn. The reference is valid as long as the lambda.
171 return s;
172 };
173 (void)[=]() -> std::string_view {
174 // FIXME: This one should warn. We are returning a reference to a local
175 // lambda variable.
176 std::string local;
177 return local;
178 };
179 return "";
180}
181
182void Containers() {
183 std::vector<std::string_view> v;
184 v.assign(count: 3, value: std::string());
185 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
186 v.insert(pos: nullptr, value: std::string());
187 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
188 v.insert(pos: nullptr, count: 3, value: std::string());
189 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
190 v.push_back(std::string());
191 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
192 v.resize(count: 3, value: std::string());
193 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
194
195 std::set<std::string_view> s;
196 s.insert(value: std::string());
197 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
198 s.insert(hint: nullptr, value: std::string());
199 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
200
201 std::map<std::string_view, int> m;
202 m[std::string()];
203 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
204}
205
206void TakesAStringView(std::string_view);
207
208void Negatives(std::string_view default_arg = ReturnsAString()) {
209 std::string str;
210 std::string_view view = str;
211
212 TakesAStringView(std::string());
213}
214
215

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp