1 // RUN: %check_clang_tidy %s readability-uniqueptr-delete-release %t -check-suffix=NULLPTR
2 // RUN: %check_clang_tidy %s readability-uniqueptr-delete-release %t -check-suffix=RESET -config='{ \
3 // RUN: CheckOptions: [{key: readability-uniqueptr-delete-release.PreferResetCall, value: true}]}'
4 namespace std {
5 template <typename T>
6 struct default_delete {};
7 
8 template <typename T, typename D = default_delete<T>>
9 class unique_ptr {
10  public:
11   unique_ptr();
12   ~unique_ptr();
13   explicit unique_ptr(T*);
14   template <typename U, typename E>
15   unique_ptr(unique_ptr<U, E>&&);
16   T* release();
17   void reset(T *P = nullptr);
18   T &operator*() const;
19   T *operator->() const;
20 };
21 }  // namespace std
22 
23 std::unique_ptr<int>& ReturnsAUnique();
24 
Positives()25 void Positives() {
26   std::unique_ptr<int> P;
27   delete P.release();
28   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr' to reset 'unique_ptr<>' objects
29   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()' to reset 'unique_ptr<>' objects
30   // CHECK-FIXES-NULLPTR: {{^}}  P = nullptr;
31   // CHECK-FIXES-RESET: {{^}}  P.reset();
32 
33   auto P2 = P;
34   delete P2.release();
35   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr' to reset 'unique_ptr<>' objects
36   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()' to reset 'unique_ptr<>' objects
37   // CHECK-FIXES-NULLPTR: {{^}}  P2 = nullptr;
38   // CHECK-FIXES-RESET: {{^}}  P2.reset();
39 
40   delete (P2.release());
41   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
42   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
43   // CHECK-FIXES-NULLPTR: {{^}}  (P2 = nullptr);
44   // CHECK-FIXES-RESET: {{^}}  (P2.reset());
45 
46   std::unique_ptr<int> Array[20];
47   delete Array[4].release();
48   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
49   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
50   // CHECK-FIXES-NULLPTR: {{^}}  Array[4] = nullptr;
51   // CHECK-FIXES-RESET: {{^}}  Array[4].reset();
52 
53   delete ReturnsAUnique().release();
54   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
55   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
56   // CHECK-FIXES-NULLPTR: {{^}}  ReturnsAUnique() = nullptr;
57   // CHECK-FIXES-RESET: {{^}}  ReturnsAUnique().reset();
58 
59   std::unique_ptr<int> *P3(&P);
60   delete P3->release();
61   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
62   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
63   // CHECK-FIXES-NULLPTR: {{^}}  *P3 = nullptr;
64   // CHECK-FIXES-RESET: {{^}}  P3->reset();
65 
66   std::unique_ptr<std::unique_ptr<int>> P4;
67   delete (*P4).release();
68   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
69   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
70   // CHECK-FIXES-NULLPTR: {{^}}  (*P4) = nullptr;
71   // CHECK-FIXES-RESET: {{^}}  (*P4).reset();
72 
73   delete P4->release();
74   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
75   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
76   // CHECK-FIXES-NULLPTR: {{^}}  *P4 = nullptr;
77   // CHECK-FIXES-RESET: {{^}}  P4->reset();
78 
79   delete (P4)->release();
80   // CHECK-MESSAGES-NULLPTR: :[[@LINE-1]]:3: warning: prefer '= nullptr'
81   // CHECK-MESSAGES-RESET: :[[@LINE-2]]:3: warning: prefer 'reset()'
82   // CHECK-FIXES-NULLPTR: {{^}}  *(P4) = nullptr;
83   // CHECK-FIXES-RESET: {{^}}  (P4)->reset();
84 }
85 
86 struct NotDefaultDeleter {};
87 
88 struct NotUniquePtr {
89   int* release();
90 };
91 
Negatives()92 void Negatives() {
93   std::unique_ptr<int, NotDefaultDeleter> P;
94   delete P.release();
95 
96   NotUniquePtr P2;
97   delete P2.release();
98 
99   // We don't trigger on bound member function calls.
100   delete (P2.release)();
101 }
102 
103 template <typename T, typename D>
NegativeDeleterT()104 void NegativeDeleterT() {
105   // Ideally this would trigger a warning, but we have all dependent types
106   // disabled for now.
107   std::unique_ptr<T> P;
108   delete P.release();
109 
110   // We ignore this one because the deleter is a template argument.
111   // Not all instantiations will use the default deleter.
112   std::unique_ptr<int, D> P2;
113   delete P2.release();
114 }
115 template void NegativeDeleterT<int, std::default_delete<int>>();
116 
117 // Test some macros
118 
119 #define DELETE_RELEASE(x) delete (x).release()
NegativesWithTemplate()120 void NegativesWithTemplate() {
121   std::unique_ptr<int> P;
122   DELETE_RELEASE(P);
123 }
124