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(0); 61 itf1(param); 62 itf1(paramf); 63 itf2(0); 64 itf2(param); 65 itf2(paramf); 66 itf3<int>(0); 67 itf3<int>(param); 68 itf3<float>(paramf); 69 itf4<int>(0); 70 itf4<int>(param); 71 itf4<float>(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(0); 135 itf1(param); 136 itf1(paramf); 137 itf2(0); 138 itf2(param); 139 itf2(paramf); 140 itf3(0); 141 itf3(param); 142 itf3(paramf); 143 itf2(0); 144 itf2(param); 145 itf2(paramf); 146 itf3(0); 147 itf3(param); 148 itf3(paramf); 149 itf4(param); 150 itf4(paramf); 151 itf5(mut_param); 152 itf5(mut_paramf); 153 itf6(mut_param); 154 itf6(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