acoster updated this revision to Diff 486582.
acoster added a comment.
Fix length of comment at the top of StrlenStringCStrCheck.h
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D140968/new/
https://reviews.llvm.org/D140968
Files:
clang-tools-extra/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.cpp
clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/docs/clang-tidy/checks/readability/strlen-string-cstr.rst
clang-tools-extra/test/clang-tidy/checkers/readability/strlen-string-cstr.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/readability/strlen-string-cstr.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability/strlen-string-cstr.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s readability-strlen-string-cstr %t
+int strlen(const char *);
+int strnlen(const char *, int);
+int strnlen_s(const char *, int);
+
+int wcslen(const wchar_t *);
+int wcsnlen_s(const wchar_t *, int);
+
+namespace std {
+template <typename T> class allocator {};
+template <typename T> class char_traits {};
+
+template <typename C, typename T = std::char_traits<C>>
+class basic_string_view {
+public:
+ basic_string_view();
+ basic_string_view(const basic_string_view &other);
+ const C *data() const;
+ int size() const;
+ int length() const;
+};
+
+using string_view = basic_string_view<char>;
+using wstring_view = basic_string_view<wchar_t>;
+
+template <typename C, typename T = std::char_traits<C>,
+ typename A = std::allocator<C>>
+class basic_string {
+public:
+ basic_string();
+ basic_string(const C *, unsigned int size);
+ basic_string(const C *, const A &allocator = A());
+ const C *c_str() const;
+ const C *data() const;
+ int size() const;
+ int length() const;
+ operator basic_string_view<C, T>() const;
+};
+
+using wstring = basic_string<wchar_t>;
+using string = basic_string<char>;
+
+int strlen(const char *);
+int wcslen(const wchar_t *);
+} // namespace std
+
+void handlesBasicString() {
+ std::string str1("a", 1);
+ int length = strlen(str1.c_str());
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant call to 'strlen' {{.*}}
+ // CHECK-FIXES: {{^ }}int length = str1.size();{{$}}
+
+ length = strnlen(str1.data(), 30);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant call to 'strnlen' {{.*}}
+ // CHECK-FIXES: {{^ }}length = str1.size();{{$}}
+
+ const std::string *p1 = &str1;
+ length = std::strlen(p1->c_str()) + 30;
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant call {{.*}}
+ // CHECK-FIXES: {{^ }}length = p1->size() + 30;{{$}}
+
+ std::wstring wstr1;
+ length = wcslen(wstr1.c_str());
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant call to 'wcslen' {{.*}}
+ // CHECK-FIXES: {{^ }}length = wstr1.size();{{$}}
+
+ const std::wstring &wstr2 = wstr1;
+ length = std::wcslen(wstr2.data());
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant call to {{.*}}
+ // CHECK-FIXES: {{^ }}length = wstr2.size();{{$}}
+}
+
+void handlesStringView() {
+ std::string str1("foo");
+ std::string_view view = str1;
+ int length = strnlen_s(view.data(), 300);
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: redundant call to 'strnlen_s'
+ // {{.*}} CHECK-FIXES: {{^ }}int length = view.size();{{$}}
+
+ std::wstring wstr1;
+ std::wstring_view wview = wstr1;
+ length = wcsnlen_s(wview.data(), 300);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant call to 'wcsnlen_s'
+ // {{.*}} CHECK-FIXES: {{^ }}length = wview.size();{{$}}
+}
+
+class CustomStringClass {
+public:
+ CustomStringClass(int, char);
+ const char *data() const;
+ int length() const;
+
+private:
+ int size() const;
+};
+
+void handlesStringLikeTypes() {
+ CustomStringClass str(123, 'f');
+ int size = strlen(str.data());
+ // CHECK-MESSAGES: [[@LINE-1]]:14: warning: redundant call to
+ // CHECK-FIXES: {{^ }}int size = str.length();{{$}}
+}
+
+class StringWithoutPublicSizeMethod {
+public:
+ StringWithoutPublicSizeMethod(const char *);
+ const char *c_str();
+
+private:
+ int size() const;
+ int length() const;
+};
+
+void ignoresStringTypesWithoutPublicSizeMethod() {
+ StringWithoutPublicSizeMethod str("foo");
+ int length = strlen(str.c_str());
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability/strlen-string-cstr.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/readability/strlen-string-cstr.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - readability-strlen-string-cstr
+
+readability-strlen-string-cstr
+==============================
+
+Warns when the return value of ``c_str()`` or ``data()`` is used as an argument
+for ``strlen``, and suggests using ``size()``or ``length()`` if one of them is
+a member function.
+
+Example
+-------
+
+.. code-block:: c++
+
+ std::string str1{"foo"}
+
+ // Use str1.size()
+ size_t length = strlen(str1.c_str());
+
+ std::string_view view(str1);
+ // Use view.size()
+ length = strlen(view.data());
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -362,6 +362,7 @@
`readability-static-accessed-through-instance <readability/static-accessed-through-instance.html>`_, "Yes"
`readability-static-definition-in-anonymous-namespace <readability/static-definition-in-anonymous-namespace.html>`_, "Yes"
`readability-string-compare <readability/string-compare.html>`_, "Yes"
+ `readability-strlen-string-cstr <readability/strlen-string-cstr.html>`_, "Yes"
`readability-suspicious-call-argument <readability/suspicious-call-argument.html>`_,
`readability-uniqueptr-delete-release <readability/uniqueptr-delete-release.html>`_, "Yes"
`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix.html>`_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -129,6 +129,13 @@
Warns when `empty()` is used on a range and the result is ignored. Suggests `clear()`
if it is an existing member function.
+- New :doc:`readability-strlen-string-cstr
+ <clang-tidy/checks/readability/strlen-string-cstr>` check.
+
+ Warns when the return value of ``c_str()`` or ``data()`` is used as an argument for
+ ``strlen``, and suggests using ``size()``or ``length()`` if one of them is a member
+ function.
+
New check aliases
^^^^^^^^^^^^^^^^^
Index: clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.h
@@ -0,0 +1,35 @@
+//===--- StrlenStringCStrCheck.h - clang-tidy -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRLENSTRINGCSTRCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRLENSTRINGCSTRCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Finds calls to `strlen(std::string::c_str())`.
+class StrlenStringCStrCheck : public ClangTidyCheck {
+public:
+ StrlenStringCStrCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRLENSTRINGCSTRCHECK_H
Index: clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/readability/StrlenStringCStrCheck.cpp
@@ -0,0 +1,65 @@
+//===- StrlenStringCStrCheck.cpp - Check for strlen(string::c_str()) calls-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a check for calls to `strlen(std::string::c_str())`.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StrlenStringCStrCheck.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void StrlenStringCStrCheck::registerMatchers(
+ ast_matchers::MatchFinder *Finder) {
+ const auto StrlenFunctions = functionDecl(
+ hasAnyName("::strlen", "::std::strlen", "::strnlen", "::strnlen_s",
+ "::wcslen", "::std::wcslen", "::wcsnlen_s"));
+ const auto CStrCall = cxxMemberCallExpr(callee(
+ cxxMethodDecl(hasAnyName("c_str", "data"),
+ ofClass(cxxRecordDecl(has(
+ cxxMethodDecl(hasAnyName("size", "length"), isPublic())
+ .bind("size-method")))))));
+ const auto StrlenCall =
+ callExpr(callee(StrlenFunctions), hasArgument(0, CStrCall.bind("arg")))
+ .bind("strlen");
+ Finder->addMatcher(StrlenCall, this);
+}
+
+void StrlenStringCStrCheck::check(
+ const ast_matchers::MatchFinder::MatchResult &Result) {
+ const auto *StrlenCall = Result.Nodes.getNodeAs<CallExpr>("strlen");
+ const auto *Arg = Result.Nodes.getNodeAs<CXXMemberCallExpr>("arg");
+ const auto *SizeMethod = Result.Nodes.getNodeAs<CXXMethodDecl>("size-method");
+
+ // Remove the `strlen(` (or similar) prefix.
+ CharSourceRange StrlenRange = CharSourceRange::getCharRange(
+ StrlenCall->getBeginLoc(), Arg->getBeginLoc());
+ // Remove the `)` (and additional strnlen arguments, if any) from the strlen
+ // call.
+ CharSourceRange CloseParenRange =
+ CharSourceRange::getCharRange(Arg->getEndLoc(), StrlenCall->getEndLoc());
+
+ const auto *CStrCallee = cast<MemberExpr>(Arg->getCallee());
+ diag(StrlenCall->getBeginLoc(), "redundant call to %0 and %1")
+ << StrlenCall->getDirectCallee() << Arg->getMethodDecl()
+ << FixItHint::CreateRemoval(StrlenRange)
+ << FixItHint::CreateRemoval(CloseParenRange)
+ << FixItHint::CreateReplacement(CStrCallee->getMemberLoc(),
+ SizeMethod->getName());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -47,6 +47,7 @@
#include "StaticAccessedThroughInstanceCheck.h"
#include "StaticDefinitionInAnonymousNamespaceCheck.h"
#include "StringCompareCheck.h"
+#include "StrlenStringCStrCheck.h"
#include "SuspiciousCallArgumentCheck.h"
#include "UniqueptrDeleteReleaseCheck.h"
#include "UppercaseLiteralSuffixCheck.h"
@@ -135,6 +136,8 @@
"readability-redundant-string-init");
CheckFactories.registerCheck<SimplifyBooleanExprCheck>(
"readability-simplify-boolean-expr");
+ CheckFactories.registerCheck<StrlenStringCStrCheck>(
+ "readability-strlen-string-cstr");
CheckFactories.registerCheck<SuspiciousCallArgumentCheck>(
"readability-suspicious-call-argument");
CheckFactories.registerCheck<UniqueptrDeleteReleaseCheck>(
Index: clang-tools-extra/clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -44,6 +44,7 @@
StaticAccessedThroughInstanceCheck.cpp
StaticDefinitionInAnonymousNamespaceCheck.cpp
StringCompareCheck.cpp
+ StrlenStringCStrCheck.cpp
SuspiciousCallArgumentCheck.cpp
UniqueptrDeleteReleaseCheck.cpp
UppercaseLiteralSuffixCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits