Unverified Commit c859a273 authored by Zinovy Nis's avatar Zinovy Nis Committed by GitHub
Browse files

[clang-tidy] An option for conditional skipping overloaded functions … (#194133)

…in modernize-use-string-view
parent fe3fd1e5
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {

namespace {
AST_MATCHER(FunctionDecl, isOverloaded) {
AST_MATCHER_P(FunctionDecl, isOverloaded, bool, CheckOverloadedFunctions) {
  if (CheckOverloadedFunctions)
    return false;
  const DeclarationName Name = Node.getDeclName();
  // Sanity check
  if (Name.isEmpty())
@@ -81,7 +83,8 @@ UseStringViewCheck::UseStringViewCheck(StringRef Name,
                                       ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      IgnoredFunctions(utils::options::parseStringList(
          Options.get("IgnoredFunctions", "toString$;ToString$;to_string$"))) {
          Options.get("IgnoredFunctions", "toString$;ToString$;to_string$"))),
      CheckOverloadedFunctions(Options.get("CheckOverloadedFunctions", false)) {
  parseReplacementStringViewClass(
      Options.get("ReplacementStringViewClass", ""));
}
@@ -89,6 +92,7 @@ UseStringViewCheck::UseStringViewCheck(StringRef Name,
void UseStringViewCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "IgnoredFunctions",
                utils::options::serializeStringList(IgnoredFunctions));
  Options.store(Opts, "CheckOverloadedFunctions", CheckOverloadedFunctions);
  Options.store(Opts, "ReplacementStringViewClass",
                (Twine("") + StringViewClassKey + "=" + StringViewClass + ";" +
                 WStringViewClassKey + "=" + WStringViewClass + ";" +
@@ -113,7 +117,7 @@ void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
      functionDecl(
          isDefinition(),
          unless(anyOf(VirtualOrOperator, IgnoredFunctionsMatcher,
                       isOverloaded(),
                       isOverloaded(CheckOverloadedFunctions),
                       ast_matchers::isExplicitTemplateSpecialization())),
          returns(IsStdString), hasDescendant(returnStmt()),
          unless(hasDescendant(returnStmt(hasReturnValue(unless(
+4 −0
Original line number Diff line number Diff line
@@ -42,6 +42,10 @@ private:
  StringRef U32StringViewClass = "std::u32string_view";

  const std::vector<StringRef> IgnoredFunctions;
  // If true, the check will also consider overloaded functions for
  // string_view conversion suggestions. When false (default), overloaded
  // functions are skipped to avoid potential issues with ambiguous conversions.
  bool CheckOverloadedFunctions = false;
};

} // namespace clang::tidy::modernize
+146 −0
Original line number Diff line number Diff line
// RUN: %check_clang_tidy -check-suffix=DONTCHECK \
// RUN: -std=c++20-or-later %s modernize-use-string-view %t -- \
// RUN: --config="{CheckOptions: {modernize-use-string-view.CheckOverloadedFunctions: false}}"

// RUN: %check_clang_tidy -check-suffix=CHECK \
// RUN: -std=c++20-or-later %s modernize-use-string-view %t -- \
// RUN: --config="{CheckOptions: {modernize-use-string-view.CheckOverloadedFunctions: true}}"
#include <string>
#include <utility>

namespace overload_funcs_redeclared {
std::basic_string<char> overload(int);
std::string overload(int);
std::string overload(int) { return "int"; }
// CHECK-MESSAGES-DONTCHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-MESSAGES-CHECK:[[@LINE-2]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-DONTCHECK: std::string_view overload(int) { return "int"; }
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
}

namespace overload_non_func {
struct overload {};
std::string overload(int) { return "int"; }
// CHECK-MESSAGES-DONTCHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-MESSAGES-CHECK:[[@LINE-2]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-DONTCHECK: std::string_view overload(int) { return "int"; }
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
}

namespace overload_with_inline {
  inline namespace inline_namespace {
    std::string overload1(int) { return "int"; }
// CHECK-MESSAGES-DONTCHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-MESSAGES-CHECK:[[@LINE-2]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-DONTCHECK: std::string_view overload1(int) { return "int"; }
// CHECK-FIXES-CHECK: std::string_view overload1(int) { return "int"; }
  }
  inline namespace regular_namespace {
    std::string overload1(int) { return "int"; }
// CHECK-MESSAGES-DONTCHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-MESSAGES-CHECK:[[@LINE-2]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-DONTCHECK: std::string_view overload1(int) { return "int"; }
// CHECK-FIXES-CHECK: std::string_view overload1(int) { return "int"; }
  }
}

////////////////////////////////////////////////////////////////////////////////

namespace overload_with_outer {
namespace overload_with_templates {
    template <typename T>
    std::string overload(T) { return "T"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
    std::string overload(std::string) { return "string"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(std::string) { return "string"; }
}
using overload_with_templates::overload;
std::string overload(char*) { return "char*"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(char*) { return "char*"; }
}

namespace overload_funcs {
std::string dbl2str(double f);
std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
std::string overload(double f) { return "f=" + dbl2str(f); }
std::string overload(std::string) { return "string"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(std::string) { return "string"; }
}

namespace overload_methods {
struct Foo {
  // Skip overloaded methods
  std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
  std::string overload(double f) { return "double"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(double f) { return "double"; }
  std::string overload(std::string) { return "string"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(std::string) { return "string"; }
};
}

namespace overload_methods_nested_classes {
struct Bar {
  std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
  std::string overload(std::string) { return "string"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(std::string) { return "string"; }
  struct FooBar {
    std::string overload(char*) { return "char*"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(char*) { return "char*"; }
    std::string overload(double f) { return "double"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(double f) { return "double"; }
  };
};
}

namespace overload_methods_nested_namespaces {
namespace foo {
  std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
  std::string overload(std::string) { return "string"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(std::string) { return "string"; }
}
using foo::overload;
std::string overload(char*) { return "char*"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(char*) { return "char*"; }
}

namespace overload_methods_templated {
    template <typename T>
    std::string overload(T value) { return "T";}
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(T value) { return "T";}
    std::string overload(int value) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int value) { return "int"; }
}

namespace two_overloads_with_inline {
  inline namespace inline_namespace {
    std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
    std::string overload(double) { return "double"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(double) { return "double"; }
  }
  std::string overload(int) { return "int"; }
// CHECK-MESSAGES-CHECK:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES-CHECK: std::string_view overload(int) { return "int"; }
}
 No newline at end of file
+0 −91
Original line number Diff line number Diff line
@@ -203,44 +203,6 @@ MyString<wchar_t> aliasedWChar() {
  return L"aliasedWChar";
}

namespace overload_funcs_redeclared {
std::basic_string<char> overload(int);
std::string overload(int);
std::string overload(int) { return "int"; }
// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES: std::string_view overload(int) { return "int"; }
}

namespace overload_non_func {
struct overload {};
std::string overload(int) { return "int"; }
// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES: std::string_view overload(int) { return "int"; }
}

namespace overload_with_inline {
  inline namespace inline_namespace {
    std::string overload(int) { return "int"; }
// CHECK-MESSAGES:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES: std::string_view overload(int) { return "int"; }
  }
  inline namespace regular_namespace {
    std::string overload(int) { return "int"; }
// CHECK-MESSAGES:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
// CHECK-FIXES: std::string_view overload(int) { return "int"; }
  }
}

namespace overload_with_outer {
namespace overload_with_templates {
    template <typename T>
    std::string overload(T) { return "T"; }
    std::string overload(std::string) { return "string"; }
}
using overload_with_templates::overload;
std::string overload(char*) { return "char*"; }
}

// ==========================================================
// Negative tests
// ==========================================================
@@ -395,59 +357,6 @@ std::string lambda() {
  }();
}

namespace overload_funcs {
std::string dbl2str(double f);
// Skip overloaded functions
std::string overload(int) { return "int"; }
// Because of this overload (non-literal return) the fix should not be applied
std::string overload(double f) { return "f=" + dbl2str(f); }
std::string overload(std::string) { return "string"; }
}

namespace overload_methods {
struct Foo {
  // Skip overloaded methods
  std::string overload(int) { return "int"; }
  std::string overload(double f) { return "double"; }
  std::string overload(std::string) { return "string"; }
};
}

namespace overload_methods_nested_classes {
struct Bar {
  std::string overload(int) { return "int"; }
  std::string overload(std::string) { return "string"; }

  struct FooBar {
    std::string overload(char*) { return "char*"; }
    std::string overload(double f) { return "double"; }
  };
};
}

namespace overload_methods_nested_namespaces {
namespace foo {
  std::string overload(int) { return "int"; }
  std::string overload(std::string) { return "string"; }
}
using foo::overload;
std::string overload(char*) { return "char*"; }
}

namespace overload_methods_templated {
    template <typename T>
    std::string overload(T value) { return "T";}
    std::string overload(int value) { return "int"; }
}

namespace two_overloads_with_inline {
  inline namespace inline_namespace {
    std::string overload(int) { return "int"; }
    std::string overload(double) { return "double"; }
  }
  std::string overload(int) { return "int"; }
}

struct TemplateString {
  static constexpr char* val = "TEMPLATE";
  template<typename T>