1 | // RUN: %check_clang_tidy %s bugprone-return-const-ref-from-parameter %t -- -- -fno-delayed-template-parsing |
---|---|
2 | |
3 | using T = int; |
4 | using TConst = int const; |
5 | using TConstRef = int const&; |
6 | |
7 | template <typename T> |
8 | struct Wrapper { Wrapper(T); }; |
9 | |
10 | template <typename T> |
11 | struct Identity { using type = T; }; |
12 | |
13 | template <typename T> |
14 | struct ConstRef { using type = const T&; }; |
15 | |
16 | namespace invalid { |
17 | |
18 | int const &f1(int const &a) { return a; } |
19 | // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter |
20 | |
21 | int const &f2(T const &a) { return a; } |
22 | // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter |
23 | |
24 | int const &f3(TConstRef a) { return a; } |
25 | // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: returning a constant reference parameter |
26 | |
27 | int const &f4(TConst &a) { return a; } |
28 | // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter |
29 | |
30 | int const &f5(TConst &a) { return true ? a : a; } |
31 | // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: returning a constant reference parameter |
32 | // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: returning a constant reference parameter |
33 | |
34 | template <typename T> |
35 | const T& tf1(const T &a) { return a; } |
36 | // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter |
37 | |
38 | template <typename T> |
39 | const T& itf1(const T &a) { return a; } |
40 | // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter |
41 | |
42 | template <typename T> |
43 | typename ConstRef<T>::type itf2(const T &a) { return a; } |
44 | // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter |
45 | |
46 | template <typename T> |
47 | typename ConstRef<T>::type itf3(typename ConstRef<T>::type a) { return a; } |
48 | // CHECK-MESSAGES: :[[@LINE-1]]:72: warning: returning a constant reference parameter |
49 | |
50 | template <typename T> |
51 | const T& itf4(typename ConstRef<T>::type a) { return a; } |
52 | // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter |
53 | |
54 | template <typename T> |
55 | const T& itf5(const T &a) { return true ? a : a; } |
56 | // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: returning a constant reference parameter |
57 | // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: returning a constant reference parameter |
58 | |
59 | void instantiate(const int ¶m, const float ¶mf, int &mut_param, float &mut_paramf) { |
60 | itf1(a: 0); |
61 | itf1(a: param); |
62 | itf1(a: paramf); |
63 | itf2(a: 0); |
64 | itf2(a: param); |
65 | itf2(a: paramf); |
66 | itf3<int>(a: 0); |
67 | itf3<int>(a: param); |
68 | itf3<float>(a: paramf); |
69 | itf4<int>(a: 0); |
70 | itf4<int>(a: param); |
71 | itf4<float>(a: paramf); |
72 | } |
73 | |
74 | struct C { |
75 | const C& foo(const C&c) { return c; } |
76 | // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter |
77 | }; |
78 | |
79 | const auto Lf1 = [](const T& t) -> const T& { return t; }; |
80 | // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter |
81 | |
82 | } // namespace invalid |
83 | |
84 | namespace false_negative_because_dependent_and_not_instantiated { |
85 | template <typename T> |
86 | typename ConstRef<T>::type tf2(const T &a) { return a; } |
87 | |
88 | template <typename T> |
89 | typename ConstRef<T>::type tf3(typename ConstRef<T>::type a) { return a; } |
90 | |
91 | template <typename T> |
92 | const T& tf4(typename ConstRef<T>::type a) { return a; } |
93 | } // false_negative_because_dependent_and_not_instantiated |
94 | |
95 | namespace valid { |
96 | |
97 | int const &f1(int &a) { return a; } |
98 | |
99 | int const &f2(int &&a) { return a; } |
100 | |
101 | int f1(int const &a) { return a; } |
102 | |
103 | template <typename T> |
104 | T tf1(T a) { return a; } |
105 | |
106 | template <typename T> |
107 | T tf2(const T a) { return a; } |
108 | |
109 | template <typename T> |
110 | T tf3(const T &a) { return a; } |
111 | |
112 | template <typename T> |
113 | Identity<T>::type tf4(const T &a) { return a; } |
114 | |
115 | template <typename T> |
116 | T itf1(T a) { return a; } |
117 | |
118 | template <typename T> |
119 | T itf2(const T a) { return a; } |
120 | |
121 | template <typename T> |
122 | T itf3(const T &a) { return a; } |
123 | |
124 | template <typename T> |
125 | Wrapper<T> itf4(const T& a) { return a; } |
126 | |
127 | template <typename T> |
128 | const T& itf5(T& a) { return a; } |
129 | |
130 | template <typename T> |
131 | T itf6(T& a) { return a; } |
132 | |
133 | void instantiate(const int ¶m, const float ¶mf, int &mut_param, float &mut_paramf) { |
134 | itf1(a: 0); |
135 | itf1(a: param); |
136 | itf1(a: paramf); |
137 | itf2(a: 0); |
138 | itf2(a: param); |
139 | itf2(a: paramf); |
140 | itf3(a: 0); |
141 | itf3(a: param); |
142 | itf3(a: paramf); |
143 | itf2(a: 0); |
144 | itf2(a: param); |
145 | itf2(a: paramf); |
146 | itf3(a: 0); |
147 | itf3(a: param); |
148 | itf3(a: paramf); |
149 | itf4(a: param); |
150 | itf4(a: paramf); |
151 | itf5(a&: mut_param); |
152 | itf5(a&: mut_paramf); |
153 | itf6(a&: mut_param); |
154 | itf6(a&: mut_paramf); |
155 | } |
156 | |
157 | template<class T> |
158 | void f(const T& t) { |
159 | const auto get = [&t] -> const T& { return t; }; |
160 | return T{}; |
161 | } |
162 | |
163 | const auto Lf1 = [](T& t) -> const T& { return t; }; |
164 | |
165 | } // namespace valid |
166 | |
167 | namespace overload { |
168 | |
169 | int const &overload_base(int const &a) { return a; } |
170 | int const &overload_base(int &&a); |
171 | |
172 | int const &overload_ret_type(int const &a) { return a; } |
173 | void overload_ret_type(int &&a); |
174 | |
175 | int const &overload_params1(int p1, int const &a) { return a; } |
176 | int const & overload_params1(int p1, int &&a); |
177 | |
178 | int const &overload_params2(int p1, int const &a, int p2) { return a; } |
179 | int const &overload_params2(int p1, int &&a, int p2); |
180 | |
181 | int const &overload_params3(T p1, int const &a, int p2) { return a; } |
182 | int const &overload_params3(int p1, int &&a, T p2); |
183 | |
184 | int const &overload_params_const(int p1, int const &a, int const p2) { return a; } |
185 | int const &overload_params_const(int const p1, int &&a, int p2); |
186 | |
187 | int const &overload_params_difference1(int p1, int const &a, int p2) { return a; } |
188 | // CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter |
189 | int const &overload_params_difference1(long p1, int &&a, int p2); |
190 | |
191 | int const &overload_params_difference2(int p1, int const &a, int p2) { return a; } |
192 | // CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter |
193 | int const &overload_params_difference2(int p1, int &&a, long p2); |
194 | |
195 | int const &overload_params_difference3(int p1, int const &a, int p2) { return a; } |
196 | // CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter |
197 | int const &overload_params_difference3(int p1, long &&a, int p2); |
198 | |
199 | } // namespace overload |
200 | |
201 | namespace gh117696 { |
202 | namespace use_lifetime_bound_attr { |
203 | int const &f(int const &a [[clang::lifetimebound]]) { return a; } |
204 | } // namespace use_lifetime_bound_attr |
205 | } // namespace gh117696 |
206 | |
207 | |
208 | namespace lambda { |
209 | using T = const int &; |
210 | using K = const float &; |
211 | T inner_valid_lambda(T a) { |
212 | [&]() -> T { return a; }; |
213 | return a; |
214 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter |
215 | } |
216 | T inner_invalid_lambda(T a) { |
217 | [&](T a) -> T { return a; }; |
218 | // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter |
219 | return a; |
220 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter |
221 | } |
222 | T inner_invalid_lambda2(T a) { |
223 | [&](K a) -> K { return a; }; |
224 | // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter |
225 | return a; |
226 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter |
227 | } |
228 | } // namespace lambda |
229 |
Definitions
- Wrapper
- Identity
- ConstRef
- f1
- f2
- f3
- f4
- f5
- tf1
- itf1
- itf2
- itf3
- itf4
- itf5
- instantiate
- C
- foo
- Lf1
- tf2
- tf3
- tf4
- f1
- f2
- f1
- tf1
- tf2
- tf3
- tf4
- itf1
- itf2
- itf3
- itf4
- itf5
- itf6
- instantiate
- f
- Lf1
- overload_base
- overload_ret_type
- overload_params1
- overload_params2
- overload_params3
- overload_params_const
- overload_params_difference1
- overload_params_difference2
- overload_params_difference3
- f
- inner_valid_lambda
- inner_invalid_lambda
Learn to use CMake with our Intro Training
Find out more