// RUN: %check_clang_tidy %s bugprone-return-const-ref-from-parameter %t -- -- -fno-delayed-template-parsing
using T = int;
using TConst = int const;
using TConstRef = int const&;
template <typename T>
struct Wrapper { Wrapper(T); };
template <typename T>
struct Identity { using type = T; };
template <typename T>
struct ConstRef { using type = const T&; };
namespace invalid {
int const &f1(int const &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter
int const &f2(T const &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter
int const &f3(TConstRef a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: returning a constant reference parameter
int const &f4(TConst &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
template <typename T>
const T& tf1(const T &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
template <typename T>
const T& itf1(const T &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter
template <typename T>
typename ConstRef<T>::type itf2(const T &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter
template <typename T>
typename ConstRef<T>::type itf3(typename ConstRef<T>::type a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:72: warning: returning a constant reference parameter
template <typename T>
const T& itf4(typename ConstRef<T>::type a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter
void instantiate(const int ¶m, const float ¶mf, int &mut_param, float &mut_paramf) {
itf1(0);
itf1(param);
itf1(paramf);
itf2(0);
itf2(param);
itf2(paramf);
itf3<int>(0);
itf3<int>(param);
itf3<float>(paramf);
itf4<int>(0);
itf4<int>(param);
itf4<float>(paramf);
}
struct C {
const C& foo(const C&c) { return c; }
// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter
};
} // namespace invalid
namespace false_negative_because_dependent_and_not_instantiated {
template <typename T>
typename ConstRef<T>::type tf2(const T &a) { return a; }
template <typename T>
typename ConstRef<T>::type tf3(typename ConstRef<T>::type a) { return a; }
template <typename T>
const T& tf4(typename ConstRef<T>::type a) { return a; }
} // false_negative_because_dependent_and_not_instantiated
namespace valid {
int const &f1(int &a) { return a; }
int const &f2(int &&a) { return a; }
int f1(int const &a) { return a; }
template <typename T>
T tf1(T a) { return a; }
template <typename T>
T tf2(const T a) { return a; }
template <typename T>
T tf3(const T &a) { return a; }
template <typename T>
Identity<T>::type tf4(const T &a) { return a; }
template <typename T>
T itf1(T a) { return a; }
template <typename T>
T itf2(const T a) { return a; }
template <typename T>
T itf3(const T &a) { return a; }
template <typename T>
Wrapper<T> itf4(const T& a) { return a; }
template <typename T>
const T& itf5(T& a) { return a; }
template <typename T>
T itf6(T& a) { return a; }
void instantiate(const int ¶m, const float ¶mf, int &mut_param, float &mut_paramf) {
itf1(0);
itf1(param);
itf1(paramf);
itf2(0);
itf2(param);
itf2(paramf);
itf3(0);
itf3(param);
itf3(paramf);
itf2(0);
itf2(param);
itf2(paramf);
itf3(0);
itf3(param);
itf3(paramf);
itf4(param);
itf4(paramf);
itf5(mut_param);
itf5(mut_paramf);
itf6(mut_param);
itf6(mut_paramf);
}
} // namespace valid
namespace overload {
int const &overload_base(int const &a) { return a; }
int const &overload_base(int &&a);
int const &overload_ret_type(int const &a) { return a; }
void overload_ret_type(int &&a);
int const &overload_params1(int p1, int const &a) { return a; }
int const & overload_params1(int p1, int &&a);
int const &overload_params2(int p1, int const &a, int p2) { return a; }
int const &overload_params2(int p1, int &&a, int p2);
int const &overload_params3(T p1, int const &a, int p2) { return a; }
int const &overload_params3(int p1, int &&a, T p2);
int const &overload_params_const(int p1, int const &a, int const p2) { return a; }
int const &overload_params_const(int const p1, int &&a, int p2);
int const &overload_params_difference1(int p1, int const &a, int p2) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter
int const &overload_params_difference1(long p1, int &&a, int p2);
int const &overload_params_difference2(int p1, int const &a, int p2) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter
int const &overload_params_difference2(int p1, int &&a, long p2);
int const &overload_params_difference3(int p1, int const &a, int p2) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:79: warning: returning a constant reference parameter
int const &overload_params_difference3(int p1, long &&a, int p2);
} // namespace overload