215 lines · cpp
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 std75 76namespace llvm {77 78class StringRef {79 public:80 StringRef();81 StringRef(const char*);82 StringRef(const std::string&);83};84 85} // namespace llvm86 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 outlives100 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 outlives104 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives105 view3 = true ? "A" : str_ref;106 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives107 108 std::string_view view4(ReturnsAString());109 // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives110 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:26: warning: std::basic_string_view outlives111 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 value124 // CHECK-MESSAGES-CXX17: [[@LINE-2]]:25: warning: llvm::StringRef outlives its value125}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 cases136 case 0:137 return array; // refers to local138 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv139 case 1:140 return s; // refers to local141 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv142 case 2:143 return std::string(); // refers to temporary144 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv145 case 3:146 return value_arg; // refers to by-value arg147 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: std::basic_string_view outliv148 149 // Ok cases150 case 100:151 return ss; // refers to static152 case 101:153 return static_array; // refers to static154 case 102:155 return ptr; // pointer is ok156 case 103:157 return ref_arg; // refers to by-ref arg158 }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 local175 // 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(3, std::string());185 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives186 v.insert(nullptr, std::string());187 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives188 v.insert(nullptr, 3, std::string());189 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives190 v.push_back(std::string());191 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives192 v.resize(3, std::string());193 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives194 195 std::set<std::string_view> s;196 s.insert(std::string());197 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives198 s.insert(nullptr, std::string());199 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives200 201 std::map<std::string_view, int> m;202 m[std::string()];203 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives204}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