328 lines · cpp
1// RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t2 3#define NULL __null4 5namespace std {6 7template <typename T>8struct unique_ptr {9 T& operator*() const;10 T* operator->() const;11 T* get() const;12 explicit operator bool() const noexcept;13};14 15template <typename T>16struct unique_ptr<T[]> {17 T& operator[](unsigned) const;18 T* get() const;19 explicit operator bool() const noexcept;20};21 22template <typename T>23struct shared_ptr {24 T& operator*() const;25 T* operator->() const;26 T* get() const;27 explicit operator bool() const noexcept;28};29 30template <typename T>31struct shared_ptr<T[]> {32 T& operator[](unsigned) const;33 T* get() const;34 explicit operator bool() const noexcept;35};36 37template <typename T>38struct vector {39 vector();40 bool operator==(const vector<T>& other) const;41 bool operator!=(const vector<T>& other) const;42 unsigned long size() const;43 bool empty() const;44 45 using iterator = T*;46 47 iterator begin();48 iterator end();49 50 T* data;51 unsigned long sz;52};53 54} // namespace std55 56struct Bar {57 void Do();58 void ConstDo() const;59};60struct BarPtr {61 Bar* operator->();62 Bar& operator*();63 Bar* get();64 explicit operator bool() const;65};66struct int_ptr {67 int* get();68 int* operator->();69 int& operator*();70};71 72struct Fail1 {73 Bar* get();74};75struct Fail2 {76 Bar* get();77 int* operator->();78 int& operator*();79};80 81struct PointerWithOverloadedGet {82 int* get();83 template <typename T>84 T* get();85 int* operator->();86 int& operator*();87};88 89void Positive() {90 BarPtr u;91 // CHECK-FIXES: BarPtr u;92 BarPtr().get()->Do();93 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call on smart pointer [readability-redundant-smartptr-get]94 // CHECK-MESSAGES: BarPtr().get()->Do();95 // CHECK-FIXES: BarPtr()->Do();96 97 u.get()->ConstDo();98 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call99 // CHECK-MESSAGES: u.get()->ConstDo();100 // CHECK-FIXES: u->ConstDo();101 102 Bar& b = *BarPtr().get();103 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call104 // CHECK-MESSAGES: Bar& b = *BarPtr().get();105 // CHECK-FIXES: Bar& b = *BarPtr();106 107 Bar& b2 = *std::unique_ptr<Bar>().get();108 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call109 // CHECK-MESSAGES: Bar& b2 = *std::unique_ptr<Bar>().get();110 // CHECK-FIXES: Bar& b2 = *std::unique_ptr<Bar>();111 112 (*BarPtr().get()).ConstDo();113 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call114 // CHECK-MESSAGES: (*BarPtr().get()).ConstDo();115 // CHECK-FIXES: (*BarPtr()).ConstDo();116 117 (*std::unique_ptr<Bar>().get()).ConstDo();118 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call119 // CHECK-MESSAGES: (*std::unique_ptr<Bar>().get()).ConstDo();120 // CHECK-FIXES: (*std::unique_ptr<Bar>()).ConstDo();121 122 std::unique_ptr<Bar>* up;123 (*up->get()).Do();124 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call125 // CHECK-MESSAGES: (*up->get()).Do();126 // CHECK-FIXES: (**up).Do();127 128 int_ptr ip;129 int i = *ip.get();130 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant get() call131 // CHECK-MESSAGES: int i = *ip.get();132 // CHECK-FIXES: int i = *ip;133 134 auto ip2 = ip;135 i = *ip2.get();136 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call137 // CHECK-MESSAGES: i = *ip2.get();138 // CHECK-FIXES: i = *ip2;139 140 std::unique_ptr<int> uu;141 std::shared_ptr<double> *ss;142 bool bb = uu.get() == nullptr;143 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call144 // CHECK-MESSAGES: uu.get() == nullptr;145 // CHECK-FIXES: bool bb = uu == nullptr;146 147 if (up->get());148 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call149 // CHECK-MESSAGES: if (up->get());150 // CHECK-FIXES: if (*up);151 if ((uu.get()));152 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call153 // CHECK-MESSAGES: if ((uu.get()));154 // CHECK-FIXES: if ((uu));155 bb = !ss->get();156 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant get() call157 // CHECK-MESSAGES: bb = !ss->get();158 // CHECK-FIXES: bb = !*ss;159 bb = u.get() ? true : false;160 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call161 // CHECK-MESSAGES: bb = u.get() ? true : false;162 // CHECK-FIXES: bb = u ? true : false;163 164 bb = nullptr != ss->get();165 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call166 // CHECK-MESSAGES: nullptr != ss->get();167 // CHECK-FIXES: bb = nullptr != *ss;168 169 i = *PointerWithOverloadedGet().get();170 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call171 // CHECK-MESSAGES: i = *PointerWithOverloadedGet().get();172 // CHECK-FIXES: i = *PointerWithOverloadedGet();173 174 bb = std::unique_ptr<int>().get() == NULL;175 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call176 // CHECK-MESSAGES: bb = std::unique_ptr<int>().get() == NULL;177 // CHECK-FIXES: bb = std::unique_ptr<int>() == NULL;178 bb = ss->get() == NULL;179 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call180 // CHECK-MESSAGES: bb = ss->get() == NULL;181 // CHECK-FIXES: bb = *ss == NULL;182 183 std::unique_ptr<int> x, y;184 if (x.get() == nullptr);185 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call186 // CHECK-MESSAGES: if (x.get() == nullptr);187 // CHECK-FIXES: if (x == nullptr);188 if (nullptr == y.get());189 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant get() call190 // CHECK-MESSAGES: if (nullptr == y.get());191 // CHECK-FIXES: if (nullptr == y);192 if (x.get() == NULL);193 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call194 // CHECK-MESSAGES: if (x.get() == NULL);195 // CHECK-FIXES: if (x == NULL);196 if (NULL == x.get());197 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant get() call198 // CHECK-MESSAGES: if (NULL == x.get());199 // CHECK-FIXES: if (NULL == x);200}201 202template <typename T>203void testTemplate() {204 T().get()->Do();205}206 207template <typename T>208void testTemplate2() {209 std::unique_ptr<T> up;210 up.get()->Do();211 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call212 // CHECK-FIXES: up->Do();213}214 215void instantiate() {216 testTemplate<BarPtr>();217 testTemplate<std::unique_ptr<Bar>>();218 testTemplate<Fail2>();219 220 testTemplate2<Bar>();221}222 223struct S {224 225 void foo() {226 m_up.get()->Do();227 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call228 // CHECK-FIXES: m_up->Do();229 m_bp.get()->Do();230 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call231 // CHECK-FIXES: m_bp->Do();232 }233 234 std::unique_ptr<Bar> m_up;235 BarPtr m_bp;236};237 238#define MACRO(p) p.get()239 240void Negative() {241 struct NegPtr {242 int* get();243 int* operator->() {244 return &*this->get();245 }246 int& operator*() {247 return *get();248 }249 };250 251 long l = *PointerWithOverloadedGet().get<long>();252 253 std::unique_ptr<Bar>* u;254 u->get()->Do();255 256 Fail1().get()->Do();257 Fail2().get()->Do();258 const Bar& b = *Fail1().get();259 (*Fail2().get()).Do();260 261 int_ptr ip;262 bool bb = ip.get() == nullptr;263 bb = !ip.get();264 bb = ip.get() ? true : false;265 std::unique_ptr<int> x;266 if (MACRO(x) == nullptr)267 ;268}269 270void test_redundant_get() {271 std::vector<std::shared_ptr<int>> v;272 auto f = [](int) {};273 for (auto i = v.begin(); i != v.end(); ++i) {274 f(*i->get());275 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call276 // CHECK-FIXES: f(**i);277 }278}279 280struct Inner {281 int a;282 int *getValue() { return &a; }283};284 285struct Example {286 Inner inner;287 Inner* get() { return &inner; }288 int *getValue() { return inner.getValue(); }289};290 291void test_redundant_get_with_member() {292 std::vector<std::shared_ptr<Example>> v;293 auto f = [](int) {};294 for (auto i = v.begin(); i != v.end(); ++i) {295 f(*(*i).get()->get()->getValue());296 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call297 // CHECK-FIXES: f(**i->get()->getValue());298 }299}300 301void test_smart_ptr_to_array() {302 std::unique_ptr<int[]> i;303 // The array specialization does not have operator*(), so make sure304 // we do not incorrectly suggest sizeof(*i) here.305 // FIXME: alternatively, we could suggest sizeof(i[0])306 auto sz = sizeof(*i.get());307 308 std::shared_ptr<Inner[]> s;309 // The array specialization does not have operator->() either310 s.get()->getValue();311 312 bool b1 = !s.get();313 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call314 // CHECK-FIXES: bool b1 = !s;315 316 if (s.get()) {}317 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call318 // CHECK-FIXES: if (s) {}319 320 int x = s.get() ? 1 : 2;321 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant get() call322 // CHECK-FIXES: int x = s ? 1 : 2;323 324 bool b2 = s.get() == nullptr;325 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call326 // CHECK-FIXES: bool b2 = s == nullptr;327}328