================ @@ -0,0 +1,108 @@ +// RUN: %check_clang_tidy %s readability-stringview-substr %t + +namespace std { +template <typename T> +class basic_string_view { +public: + using size_type = unsigned long; + static constexpr size_type npos = -1; + + basic_string_view(const char*) {} + basic_string_view substr(size_type pos, size_type count = npos) const { return *this; } + void remove_prefix(size_type n) {} + void remove_suffix(size_type n) {} + size_type length() const { return 0; } + basic_string_view& operator=(const basic_string_view&) { return *this; } +}; + +using string_view = basic_string_view<char>; +} // namespace std + +void test_basic() { + std::string_view sv("test"); + std::string_view sv1("test"); + std::string_view sv2("test"); + + // Should match: remove_prefix + sv = sv.substr(5); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_prefix' over 'substr' for removing characters from the start [readability-stringview-substr] + // CHECK-FIXES: sv.remove_prefix(5) + + // Should match: remove_suffix + sv = sv.substr(0, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + // Should match: remove_suffix with complex expression + sv = sv.substr(0, sv.length() - (3 + 2)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix((3 + 2)) +} + +void test_copies() { + std::string_view sv("test"); + std::string_view sv1("test"); + std::string_view sv2("test"); + + // Should match: remove redundant self copies + sv = sv.substr(0, sv.length()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant self-copy [readability-stringview-substr] + + sv = sv.substr(0, sv.length() - 0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant self-copy [readability-stringview-substr] + + // Should match: simplify copies between different variables + sv1 = sv.substr(0, sv.length()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer direct copy over substr [readability-stringview-substr] + // CHECK-FIXES: sv1 = sv + + sv2 = sv.substr(0, sv.length() - 0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer direct copy over substr [readability-stringview-substr] + // CHECK-FIXES: sv2 = sv +} + +void test_zero_forms() { + std::string_view sv("test"); + const int kZero = 0; + constexpr std::string_view::size_type Zero = 0; + #define START_POS 0 + + // Should match: various forms of zero in first argument + sv = sv.substr(kZero, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + sv = sv.substr(Zero, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + sv = sv.substr(START_POS, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + sv = sv.substr((0), sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + sv = sv.substr(0u, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) + + sv = sv.substr(0UL, sv.length() - 3); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer 'remove_suffix' over 'substr' for removing characters from the end [readability-stringview-substr] + // CHECK-FIXES: sv.remove_suffix(3) +} + +void test_should_not_match() { + std::string_view sv("test"); + std::string_view sv1("test"); + std::string_view sv2("test"); + + // No match: substr used for prefix or mid-view + sv = sv.substr(1, sv.length() - 3); // No warning + + // No match: Different string_views + sv = sv2.substr(0, sv2.length() - 3); // No warning ---------------- denzor200 wrote:
Why no match? I don't see any trouble with ``` sv = sv2; sv.remove_suffix(3); ``` Of couse still no match for const version of `sv` https://github.com/llvm/llvm-project/pull/120055 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits