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 | |
11 | namespace std { |
12 | |
13 | template <typename T> |
14 | class 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 | |
29 | template <typename, typename> |
30 | class pair {}; |
31 | |
32 | template <typename T> |
33 | class 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 | |
44 | template <typename Key, typename Value> |
45 | class 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 | |
52 | class basic_string_view; |
53 | |
54 | class 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 | |
65 | typedef basic_string string; |
66 | |
67 | class basic_string_view { |
68 | public: |
69 | basic_string_view(const char*); |
70 | }; |
71 | |
72 | typedef basic_string_view string_view; |
73 | |
74 | } // namespace std |
75 | |
76 | namespace llvm { |
77 | |
78 | class StringRef { |
79 | public: |
80 | StringRef(); |
81 | StringRef(const char*); |
82 | StringRef(const std::string&); |
83 | }; |
84 | |
85 | } // namespace llvm |
86 | |
87 | std::string ReturnsAString(); |
88 | |
89 | void 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 | |
121 | void 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 | |
127 | const char static_array[] = "A" ; |
128 | std::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 | |
182 | void 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 | |
206 | void TakesAStringView(std::string_view); |
207 | |
208 | void 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 | |