1f2e50009SIgnat Loskutov // RUN: %check_clang_tidy -std=c++11,c++14 -check-suffix=,CXX14 %s bugprone-dangling-handle %t -- \
289a1d03eSRichard // RUN: -config="{CheckOptions: \
3e8a3ddafSNathan James // RUN: {bugprone-dangling-handle.HandleClasses: \
4e8a3ddafSNathan James // RUN: 'std::basic_string_view; ::llvm::StringRef;'}}"
5f2e50009SIgnat Loskutov
6f2e50009SIgnat Loskutov // RUN: %check_clang_tidy -std=c++17-or-later -check-suffix=,CXX17 %s bugprone-dangling-handle %t -- \
7f2e50009SIgnat Loskutov // RUN: -config="{CheckOptions: \
8f2e50009SIgnat Loskutov // RUN: {bugprone-dangling-handle.HandleClasses: \
9f2e50009SIgnat Loskutov // RUN: 'std::basic_string_view; ::llvm::StringRef;'}}"
1089a1d03eSRichard
1189a1d03eSRichard namespace std {
1289a1d03eSRichard
1389a1d03eSRichard template <typename T>
1489a1d03eSRichard class vector {
1589a1d03eSRichard public:
1689a1d03eSRichard using const_iterator = const T*;
1789a1d03eSRichard using iterator = T*;
1889a1d03eSRichard using size_type = int;
1989a1d03eSRichard
2089a1d03eSRichard void assign(size_type count, const T& value);
2189a1d03eSRichard iterator insert(const_iterator pos, const T& value);
2289a1d03eSRichard iterator insert(const_iterator pos, T&& value);
2389a1d03eSRichard iterator insert(const_iterator pos, size_type count, const T& value);
2489a1d03eSRichard void push_back(const T&);
2589a1d03eSRichard void push_back(T&&);
2689a1d03eSRichard void resize(size_type count, const T& value);
2789a1d03eSRichard };
2889a1d03eSRichard
2989a1d03eSRichard template <typename, typename>
3089a1d03eSRichard class pair {};
3189a1d03eSRichard
3289a1d03eSRichard template <typename T>
3389a1d03eSRichard class set {
3489a1d03eSRichard public:
3589a1d03eSRichard using const_iterator = const T*;
3689a1d03eSRichard using iterator = T*;
3789a1d03eSRichard
3889a1d03eSRichard std::pair<iterator, bool> insert(const T& value);
3989a1d03eSRichard std::pair<iterator, bool> insert(T&& value);
4089a1d03eSRichard iterator insert(const_iterator hint, const T& value);
4189a1d03eSRichard iterator insert(const_iterator hint, T&& value);
4289a1d03eSRichard };
4389a1d03eSRichard
4489a1d03eSRichard template <typename Key, typename Value>
4589a1d03eSRichard class map {
4689a1d03eSRichard public:
4789a1d03eSRichard using value_type = pair<Key, Value>;
4889a1d03eSRichard value_type& operator[](const Key& key);
4989a1d03eSRichard value_type& operator[](Key&& key);
5089a1d03eSRichard };
5189a1d03eSRichard
5289a1d03eSRichard class basic_string_view;
5389a1d03eSRichard
5489a1d03eSRichard class basic_string {
5589a1d03eSRichard public:
5689a1d03eSRichard basic_string();
5789a1d03eSRichard basic_string(const char*);
5889a1d03eSRichard
5935f466ebSPiotr Zegar typedef basic_string_view str_view;
6035f466ebSPiotr Zegar operator str_view() const noexcept;
6189a1d03eSRichard
6289a1d03eSRichard ~basic_string();
6389a1d03eSRichard };
6489a1d03eSRichard
6589a1d03eSRichard typedef basic_string string;
6689a1d03eSRichard
6789a1d03eSRichard class basic_string_view {
6889a1d03eSRichard public:
6989a1d03eSRichard basic_string_view(const char*);
7089a1d03eSRichard };
7189a1d03eSRichard
7289a1d03eSRichard typedef basic_string_view string_view;
7389a1d03eSRichard
7489a1d03eSRichard } // namespace std
7589a1d03eSRichard
7689a1d03eSRichard namespace llvm {
7789a1d03eSRichard
7889a1d03eSRichard class StringRef {
7989a1d03eSRichard public:
8089a1d03eSRichard StringRef();
8189a1d03eSRichard StringRef(const char*);
8289a1d03eSRichard StringRef(const std::string&);
8389a1d03eSRichard };
8489a1d03eSRichard
8589a1d03eSRichard } // namespace llvm
8689a1d03eSRichard
8789a1d03eSRichard std::string ReturnsAString();
8889a1d03eSRichard
Positives()8989a1d03eSRichard void Positives() {
9089a1d03eSRichard std::string_view view1 = std::string();
91f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
92f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
9389a1d03eSRichard
9489a1d03eSRichard std::string_view view_2 = ReturnsAString();
95f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
96f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX17: [[@LINE-2]]:29: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
9789a1d03eSRichard
9889a1d03eSRichard view1 = std::string();
9989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
10089a1d03eSRichard
10189a1d03eSRichard const std::string& str_ref = "";
10289a1d03eSRichard std::string_view view3 = true ? "A" : str_ref;
103f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
104f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives
10589a1d03eSRichard view3 = true ? "A" : str_ref;
10689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
10789a1d03eSRichard
10889a1d03eSRichard std::string_view view4(ReturnsAString());
109f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
110f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX17: [[@LINE-2]]:26: warning: std::basic_string_view outlives
111*1097c71dSPiotr Zegar
112*1097c71dSPiotr Zegar std::string_view view5 = std::string("test");
113*1097c71dSPiotr Zegar // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
114*1097c71dSPiotr Zegar // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
115*1097c71dSPiotr Zegar
116*1097c71dSPiotr Zegar std::string_view view6 = std::string{"test"};
117*1097c71dSPiotr Zegar // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
118*1097c71dSPiotr Zegar // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
11989a1d03eSRichard }
12089a1d03eSRichard
OtherTypes()12189a1d03eSRichard void OtherTypes() {
12289a1d03eSRichard llvm::StringRef ref = std::string();
123f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX14: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
124f2e50009SIgnat Loskutov // CHECK-MESSAGES-CXX17: [[@LINE-2]]:25: warning: llvm::StringRef outlives its value
12589a1d03eSRichard }
12689a1d03eSRichard
12789a1d03eSRichard const char static_array[] = "A";
ReturnStatements(int i,std::string value_arg,const std::string & ref_arg)12889a1d03eSRichard std::string_view ReturnStatements(int i, std::string value_arg,
12989a1d03eSRichard const std::string &ref_arg) {
13089a1d03eSRichard const char array[] = "A";
13189a1d03eSRichard const char* ptr = "A";
13289a1d03eSRichard std::string s;
13389a1d03eSRichard static std::string ss;
13489a1d03eSRichard switch (i) {
13589a1d03eSRichard // Bad cases
13689a1d03eSRichard case 0:
13789a1d03eSRichard return array; // refers to local
13889a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
13989a1d03eSRichard case 1:
14089a1d03eSRichard return s; // refers to local
14189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
14289a1d03eSRichard case 2:
14389a1d03eSRichard return std::string(); // refers to temporary
14489a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
14589a1d03eSRichard case 3:
14689a1d03eSRichard return value_arg; // refers to by-value arg
14789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv
14889a1d03eSRichard
14989a1d03eSRichard // Ok cases
15089a1d03eSRichard case 100:
15189a1d03eSRichard return ss; // refers to static
15289a1d03eSRichard case 101:
15389a1d03eSRichard return static_array; // refers to static
15489a1d03eSRichard case 102:
15589a1d03eSRichard return ptr; // pointer is ok
15689a1d03eSRichard case 103:
15789a1d03eSRichard return ref_arg; // refers to by-ref arg
15889a1d03eSRichard }
15989a1d03eSRichard
16089a1d03eSRichard struct S {
16189a1d03eSRichard std::string_view view() { return value; }
16289a1d03eSRichard std::string value;
16389a1d03eSRichard };
16489a1d03eSRichard
16589a1d03eSRichard (void)[&]()->std::string_view {
16689a1d03eSRichard // This should not warn. The string is bound by reference.
16789a1d03eSRichard return s;
16889a1d03eSRichard };
16989a1d03eSRichard (void)[=]() -> std::string_view {
17089a1d03eSRichard // This should not warn. The reference is valid as long as the lambda.
17189a1d03eSRichard return s;
17289a1d03eSRichard };
17389a1d03eSRichard (void)[=]() -> std::string_view {
17489a1d03eSRichard // FIXME: This one should warn. We are returning a reference to a local
17589a1d03eSRichard // lambda variable.
17689a1d03eSRichard std::string local;
17789a1d03eSRichard return local;
17889a1d03eSRichard };
17989a1d03eSRichard return "";
18089a1d03eSRichard }
18189a1d03eSRichard
Containers()18289a1d03eSRichard void Containers() {
18389a1d03eSRichard std::vector<std::string_view> v;
18489a1d03eSRichard v.assign(3, std::string());
18589a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
18689a1d03eSRichard v.insert(nullptr, std::string());
18789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
18889a1d03eSRichard v.insert(nullptr, 3, std::string());
18989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
19089a1d03eSRichard v.push_back(std::string());
19189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
19289a1d03eSRichard v.resize(3, std::string());
19389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
19489a1d03eSRichard
19589a1d03eSRichard std::set<std::string_view> s;
19689a1d03eSRichard s.insert(std::string());
19789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
19889a1d03eSRichard s.insert(nullptr, std::string());
19989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
20089a1d03eSRichard
20189a1d03eSRichard std::map<std::string_view, int> m;
20289a1d03eSRichard m[std::string()];
20389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
20489a1d03eSRichard }
20589a1d03eSRichard
20689a1d03eSRichard void TakesAStringView(std::string_view);
20789a1d03eSRichard
Negatives(std::string_view default_arg=ReturnsAString ())20889a1d03eSRichard void Negatives(std::string_view default_arg = ReturnsAString()) {
20989a1d03eSRichard std::string str;
21089a1d03eSRichard std::string_view view = str;
21189a1d03eSRichard
21289a1d03eSRichard TakesAStringView(std::string());
21389a1d03eSRichard }
21435f466ebSPiotr Zegar
215