[clang-tools-extra] [clang-tidy] Enhance modernize-use-starts-ends-with to handle substr patterns (PR #116033)

Congcong Cai via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 17 17:55:02 PST 2024


================
@@ -266,3 +269,53 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
   s.compare(0, 1, "ab") == 0;
   s.rfind(suffix, 1) == s.size() - suffix.size();
 }
+
+void test_substr() {
+    std::string str("hello world");
+    std::string prefix = "hello";
+    
+    // Basic pattern
+    str.substr(0, 5) == "hello";
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr == [modernize-use-starts-ends-with]
+    // CHECK-FIXES: str.starts_with("hello");
+    
+    // With string literal on left side
+    "hello" == str.substr(0, 5);
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr == [modernize-use-starts-ends-with]
+    // CHECK-FIXES: str.starts_with("hello");
+    
+    // Inequality comparison
+    str.substr(0, 5) != "world";
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr != [modernize-use-starts-ends-with]
+    // CHECK-FIXES: !str.starts_with("world");
+    
+    // Ensure non-zero start position is not transformed
+    str.substr(1, 5) == "hello";
+    str.substr(0, 4) == "hello"; // Length mismatch
+    
+    size_t len = 5;
+    str.substr(0, len) == "hello"; // Non-constant length
+
+    // String literal with size calculation
+    str.substr(0, strlen("hello")) == "hello";
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr == [modernize-use-starts-ends-with]
+    // CHECK-FIXES: str.starts_with("hello");
+
+    str.substr(0, prefix.size()) == prefix;
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr == [modernize-use-starts-ends-with]
+    // CHECK-FIXES: str.starts_with(prefix);
+
+      // Tests to verify macro behavior
+    #define STARTS_WITH(X, Y) (X).substr(0, (Y).size()) == (Y)
+    STARTS_WITH(str, prefix);
+
+    #define SUBSTR(X, A, B) (X).substr((A), (B))
+    SUBSTR(str, 0, 6) == "prefix";
+
+    #define STR() str
+    SUBSTR(STR(), 0, 6) == "prefix";
+
+    "prefix" == SUBSTR(STR(), 0, 6);
+    // CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr == [modernize-use-starts-ends-with]
----------------
HerrCai0907 wrote:

You can try to check whether fixhint location is invalid.

https://github.com/llvm/llvm-project/pull/116033


More information about the cfe-commits mailing list