1 // RUN: %check_clang_tidy %s boost-use-to-string %t
2 
3 namespace std {
4 
5 template <typename T>
6 class basic_string {};
7 
8 using string = basic_string<char>;
9 using wstring = basic_string<wchar_t>;
10 }
11 
12 namespace boost {
13 template <typename T, typename V>
14 T lexical_cast(const V &) {
15   return T();
16 };
17 }
18 
19 struct my_weird_type {};
20 
fun(const std::string &)21 std::string fun(const std::string &) {}
22 
test_to_string1()23 void test_to_string1() {
24 
25   auto xa = boost::lexical_cast<std::string>(5);
26   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
27   // CHECK-FIXES: auto xa = std::to_string(5);
28 
29   auto z = boost::lexical_cast<std::string>(42LL);
30   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::to_string
31   // CHECK-FIXES: auto z = std::to_string(42LL);
32 
33   // this should not trigger
34   fun(boost::lexical_cast<std::string>(42.0));
35   auto non = boost::lexical_cast<my_weird_type>(42);
36   boost::lexical_cast<int>("12");
37 }
38 
test_to_string2()39 void test_to_string2() {
40   int a;
41   long b;
42   long long c;
43   unsigned d;
44   unsigned long e;
45   unsigned long long f;
46   float g;
47   double h;
48   long double i;
49   bool j;
50 
51   fun(boost::lexical_cast<std::string>(a));
52   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
53   // CHECK-FIXES: fun(std::to_string(a));
54   fun(boost::lexical_cast<std::string>(b));
55   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
56   // CHECK-FIXES: fun(std::to_string(b));
57   fun(boost::lexical_cast<std::string>(c));
58   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
59   // CHECK-FIXES: fun(std::to_string(c));
60   fun(boost::lexical_cast<std::string>(d));
61   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
62   // CHECK-FIXES: fun(std::to_string(d));
63   fun(boost::lexical_cast<std::string>(e));
64   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
65   // CHECK-FIXES: fun(std::to_string(e));
66   fun(boost::lexical_cast<std::string>(f));
67   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string
68   // CHECK-FIXES: fun(std::to_string(f));
69 
70   // No change for floating numbers.
71   fun(boost::lexical_cast<std::string>(g));
72   fun(boost::lexical_cast<std::string>(h));
73   fun(boost::lexical_cast<std::string>(i));
74   // And bool.
75   fun(boost::lexical_cast<std::string>(j));
76 }
77 
fun(const std::wstring &)78 std::string fun(const std::wstring &) {}
79 
test_to_wstring()80 void test_to_wstring() {
81   int a;
82   long b;
83   long long c;
84   unsigned d;
85   unsigned long e;
86   unsigned long long f;
87   float g;
88   double h;
89   long double i;
90   bool j;
91 
92   fun(boost::lexical_cast<std::wstring>(a));
93   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
94   // CHECK-FIXES: fun(std::to_wstring(a));
95   fun(boost::lexical_cast<std::wstring>(b));
96   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
97   // CHECK-FIXES: fun(std::to_wstring(b));
98   fun(boost::lexical_cast<std::wstring>(c));
99   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
100   // CHECK-FIXES: fun(std::to_wstring(c));
101   fun(boost::lexical_cast<std::wstring>(d));
102   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
103   // CHECK-FIXES: fun(std::to_wstring(d));
104   fun(boost::lexical_cast<std::wstring>(e));
105   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
106   // CHECK-FIXES: fun(std::to_wstring(e));
107   fun(boost::lexical_cast<std::wstring>(f));
108   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring
109   // CHECK-FIXES: fun(std::to_wstring(f));
110 
111   // No change for floating numbers
112   fun(boost::lexical_cast<std::wstring>(g));
113   fun(boost::lexical_cast<std::wstring>(h));
114   fun(boost::lexical_cast<std::wstring>(i));
115   // and bool.
116   fun(boost::lexical_cast<std::wstring>(j));
117 }
118 
119 const auto glob = boost::lexical_cast<std::string>(42);
120 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::to_string
121 // CHECK-FIXES: const auto glob = std::to_string(42);
122 
123 template <typename T>
string_as_T(T t=T ())124 void string_as_T(T t = T()) {
125   boost::lexical_cast<std::string>(42);
126   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
127   // CHECK-FIXES: std::to_string(42);
128 
129   boost::lexical_cast<T>(42);
130   string_as_T(boost::lexical_cast<T>(42));
131   auto p = boost::lexical_cast<T>(42);
132   auto p2 = (T)boost::lexical_cast<T>(42);
133   auto p3 = static_cast<T>(boost::lexical_cast<T>(42));
134 }
135 
136 #define my_to_string boost::lexical_cast<std::string>
137 
no_fixup_inside_macro()138 void no_fixup_inside_macro() {
139   my_to_string(12);
140   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string
141 }
142 
no_warnings()143 void no_warnings() {
144   fun(boost::lexical_cast<std::string>("abc"));
145   fun(boost::lexical_cast<std::wstring>("abc"));
146   fun(boost::lexical_cast<std::string>(my_weird_type{}));
147   string_as_T<int>();
148   string_as_T<std::string>();
149 }
150 
151 struct Fields {
152   int integer;
153   float floating;
154   Fields* wierd;
getConstIntegerFields155   const int &getConstInteger() const {return integer;}
156 };
157 
testFields()158 void testFields() {
159   Fields fields;
160   auto s1 = boost::lexical_cast<std::string>(fields.integer);
161   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
162   // CHECK-FIXES: auto s1 = std::to_string(fields.integer);
163 
164   auto s2 = boost::lexical_cast<std::string>(fields.floating);
165   auto s3 = boost::lexical_cast<std::string>(fields.wierd);
166   auto s4 = boost::lexical_cast<std::string>(fields.getConstInteger());
167   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string
168   // CHECK-FIXES: auto s4 = std::to_string(fields.getConstInteger());
169 }
170