@@ -36,7 +36,7 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
3636 string_like sl, string_like_camel slc, prefer_underscore_version puv,
3737 prefer_underscore_version_flip puvf) {
3838 s.find (" a" ) == 0 ;
39- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of find() == 0
39+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of find [modernize-use-starts-ends-with]
4040 // CHECK-FIXES: s.starts_with("a");
4141
4242 (((((s)).find (" a" )))) == ((0 ));
@@ -68,7 +68,7 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
6868 // CHECK-FIXES: !s.starts_with("a");
6969
7070 s.rfind (" a" , 0 ) == 0 ;
71- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of rfind() == 0
71+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of rfind [modernize-use-starts-ends-with]
7272 // CHECK-FIXES: s.starts_with("a");
7373
7474 s.rfind (s, 0 ) == 0 ;
@@ -91,16 +91,6 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
9191 // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
9292 // CHECK-FIXES: !s.starts_with("a");
9393
94- #define STR (x ) std::string(x)
95- 0 == STR (s).find (" a" );
96- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
97- // CHECK-FIXES: STR(s).starts_with("a");
98-
99- #define STRING s
100- if (0 == STRING.find (" ala" )) { /* do something */ }
101- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
102- // CHECK-FIXES: if (STRING.starts_with("ala"))
103-
10494 #define FIND find
10595 s.FIND (" a" ) == 0 ;
10696 // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
@@ -149,11 +139,11 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
149139 // CHECK-FIXES: puvf.starts_with("a");
150140
151141 s.compare (0 , 1 , " a" ) == 0 ;
152- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare() == 0
142+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare [modernize-use-starts-ends-with]
153143 // CHECK-FIXES: s.starts_with("a");
154144
155145 s.compare (0 , 1 , " a" ) != 0 ;
156- // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare() != 0
146+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare [modernize-use-starts-ends-with]
157147 // CHECK-FIXES: !s.starts_with("a");
158148
159149 s.compare (0 , strlen (" a" ), " a" ) == 0 ;
@@ -265,4 +255,68 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
265255
266256 s.compare (0 , 1 , " ab" ) == 0 ;
267257 s.rfind (suffix, 1 ) == s.size () - suffix.size ();
258+
259+ #define STR (x ) std::string(x)
260+ 0 == STR (s).find (" a" );
261+
262+ #define STRING s
263+ if (0 == STRING.find (" ala" )) { /* do something */ }
264+ }
265+
266+ void test_substr () {
267+ std::string str (" hello world" );
268+ std::string prefix = " hello" ;
269+
270+ // Basic pattern
271+ str.substr (0 , 5 ) == " hello" ;
272+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
273+ // CHECK-FIXES: str.starts_with("hello");
274+
275+ // With string literal on left side
276+ " hello" == str.substr (0 , 5 );
277+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
278+ // CHECK-FIXES: str.starts_with("hello");
279+
280+ // Inequality comparison
281+ str.substr (0 , 5 ) != " world" ;
282+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
283+ // CHECK-FIXES: !str.starts_with("world");
284+
285+ // Ensure non-zero start position is not transformed
286+ str.substr (1 , 5 ) == " hello" ;
287+ str.substr (0 , 4 ) == " hello" ; // Length mismatch
288+
289+ size_t len = 5 ;
290+ str.substr (0 , len) == " hello" ; // Non-constant length
291+
292+ // String literal with size calculation
293+ str.substr (0 , strlen (" hello" )) == " hello" ;
294+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
295+ // CHECK-FIXES: str.starts_with("hello");
296+
297+ str.substr (0 , prefix.size ()) == prefix;
298+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
299+ // CHECK-FIXES: str.starts_with(prefix);
300+
301+ str.substr (0 , prefix.length ()) == prefix;
302+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
303+ // CHECK-FIXES: str.starts_with(prefix);
304+
305+ // Tests to verify macro behavior
306+ #define MSG " hello"
307+ str.substr (0 , strlen (MSG)) == MSG;
308+ // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
309+ // CHECK-FIXES: str.starts_with(MSG);
310+
311+ #define STARTS_WITH (X, Y ) (X).substr(0 , (Y).size()) == (Y)
312+ STARTS_WITH (str, prefix);
313+
314+ #define SUBSTR (X, A, B ) (X).substr((A), (B))
315+ SUBSTR (str, 0 , 6 ) == " prefix" ;
316+
317+ #define STR () str
318+ SUBSTR (STR (), 0 , 6 ) == " prefix" ;
319+ " prefix" == SUBSTR (STR (), 0 , 6 );
320+
321+ str.substr (0 , strlen (" hello123" )) == " hello" ;
268322}
0 commit comments