Prazek created this revision.
Prazek added a reviewer: alexfh.
Prazek added a subscriber: cfe-commits.

todo fix docs.

Is there any better solution for the basic_string problem?

http://reviews.llvm.org/D18136

Files:
  clang-tidy/boost/BoostTidyModule.cpp
  clang-tidy/boost/CMakeLists.txt
  clang-tidy/boost/UseToStringCheck.cpp
  clang-tidy/boost/UseToStringCheck.h
  docs/clang-tidy/checks/boost-use-to-string.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/boost-use-to-string.cpp

Index: test/clang-tidy/boost-use-to-string.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/boost-use-to-string.cpp
@@ -0,0 +1,127 @@
+// RUN: %check_clang_tidy %s boost-use-to-string %t
+
+
+namespace std {
+
+template <typename T> class basic_string {};
+
+using string = basic_string<char>;
+using wstring = basic_string<wchar_t>;
+}
+
+namespace boost {
+template <typename T, typename V>
+T lexical_cast(const V&) {
+  return T();
+};
+}
+
+struct my_weird_type {};
+
+std::string fun(const std::string &) {}
+
+void test_to_string1() {
+
+  auto xa = boost::lexical_cast<std::string>(5);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: auto xa = std::to_string(5);
+
+  std::string y = boost::lexical_cast<std::string>(xa);
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: std::string y = std::to_string(xa);
+
+
+ auto z = boost::lexical_cast<std::string>(42LL);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: auto z = std::to_string(42LL);
+
+  fun(boost::lexical_cast<std::string>(42.0));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(42.0));
+
+  // this should not trigger
+  auto non = boost::lexical_cast<my_weird_type>(42);
+  boost::lexical_cast<int>("12");
+}
+
+void test_to_string2() {
+  int a;
+  long b;
+  long long c;
+  unsigned d;
+  unsigned long e;
+  unsigned long long f;
+  float g;
+  double h;
+  long double i;
+
+  fun(boost::lexical_cast<std::string>(a));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(a));
+  fun(boost::lexical_cast<std::string>(b));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(b));
+  fun(boost::lexical_cast<std::string>(c));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(c));
+  fun(boost::lexical_cast<std::string>(d));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(d));
+  fun(boost::lexical_cast<std::string>(e));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(e));
+  fun(boost::lexical_cast<std::string>(f));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(f));
+  fun(boost::lexical_cast<std::string>(g));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(g));
+  fun(boost::lexical_cast<std::string>(h));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(h));
+  fun(boost::lexical_cast<std::string>(i));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_string instead of boost::lexical_cast<std::string> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_string(i));
+}
+
+std::string fun(const std::wstring &) {}
+
+void test_to_wstring() {
+  int a;
+  long b;
+  long long c;
+  unsigned d;
+  unsigned long e;
+  unsigned long long f;
+  float g;
+  double h;
+  long double i;
+
+  fun(boost::lexical_cast<std::wstring>(a));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(a));
+  fun(boost::lexical_cast<std::wstring>(b));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(b));
+  fun(boost::lexical_cast<std::wstring>(c));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(c));
+  fun(boost::lexical_cast<std::wstring>(d));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(d));
+  fun(boost::lexical_cast<std::wstring>(e));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(e));
+  fun(boost::lexical_cast<std::wstring>(f));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(f));
+  fun(boost::lexical_cast<std::wstring>(g));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(g));
+  fun(boost::lexical_cast<std::wstring>(h));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(h));
+  fun(boost::lexical_cast<std::wstring>(i));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring instead of boost::lexical_cast<std::wstring> [boost-use-to-string]
+// CHECK-FIXES: fun(std::to_wstring(i));
+}
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -5,6 +5,7 @@
 
 .. toctree::   
    boost-LexicalCastRedundantType
+   boost-use-to-string
    cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
    cert-dcl50-cpp
    cert-dcl54-cpp (redirects to misc-new-delete-overloads) <cert-dcl54-cpp>
@@ -86,6 +87,7 @@
    modernize-use-default
    modernize-use-nullptr
    modernize-use-override
+   modernize-use-using
    performance-faster-string-find
    performance-for-range-copy
    performance-implicit-cast-in-loop
Index: docs/clang-tidy/checks/boost-use-to-string.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/boost-use-to-string.rst
@@ -0,0 +1,6 @@
+.. title:: clang-tidy - boost-use-to-string
+
+boost-use-to-string
+===================
+
+FIXME: Describe what patterns does the check detect and why. Give examples.
Index: clang-tidy/boost/UseToStringCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/boost/UseToStringCheck.h
@@ -0,0 +1,39 @@
+//===--- UseToStringCheck.h - clang-tidy-------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace boost {
+
+/// Matches calls to boost::lexical_cast<std::string> and
+/// boost::lexical_cast<std::wstring> and replaces it with to_string and
+/// to_wstring calls.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/boost-use-to-string.html
+class UseToStringCheck : public ClangTidyCheck {
+public:
+  UseToStringCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void apply(const CallExpr *MatchedExpr, const std::string &message,
+             const std::string &replacement);
+};
+
+} // namespace boost
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
Index: clang-tidy/boost/UseToStringCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/boost/UseToStringCheck.cpp
@@ -0,0 +1,75 @@
+//===--- UseToStringCheck.cpp - clang-tidy---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseToStringCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace boost {
+
+void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Gives matcher that looks for calls of boost::lexical_cast with
+  // returning type of className.
+  auto getMatcher = [](std::string className) {
+    return callExpr(
+        hasDeclaration(functionDecl(returns(asString(std::move(className))),
+                                    hasName("boost::lexical_cast"))),
+        argumentCountIs(1));
+  };
+
+  // FIXME: asString should work with class std::string instead of basic_string
+  Finder->addMatcher(
+      getMatcher("class std::__cxx11::basic_string<char>").bind("to_string"),
+      this);
+  Finder->addMatcher(
+      getMatcher("class std::basic_string<char>").bind("to_string"), this);
+  Finder->addMatcher(
+      getMatcher("class std::basic_string<wchar_t>").bind("to_wstring"), this);
+  Finder->addMatcher(
+      getMatcher("class std::__cxx11::basic_string<char>").bind("to_wstring"),
+      this);
+}
+
+void UseToStringCheck::apply(const CallExpr *MatchedExpr,
+                             const std::string &message,
+                             const std::string &replacement) {
+  auto *Argument = MatchedExpr->getArg(0);
+
+  diag(MatchedExpr->getLocStart(), message) << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(MatchedExpr->getLocStart(),
+                                    Argument->getExprLoc()),
+      replacement);
+}
+
+static const std::string toStringMSG =
+    "use std::to_string instead of boost::lexical_cast<std::string>";
+static const std::string toWStringMSG =
+    "use std::to_wstring instead of boost::lexical_cast<std::wstring>";
+
+void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedToString = Result.Nodes.getNodeAs<CallExpr>("to_string");
+  const auto *MatchedToWString = Result.Nodes.getNodeAs<CallExpr>("to_wstring");
+
+  if (MatchedToString) {
+    apply(MatchedToString, toStringMSG, "std::to_string(");
+  } else if (MatchedToWString) {
+    apply(MatchedToWString, toWStringMSG, "std::to_wstring(");
+  } else {
+    llvm_unreachable("Bad Callback. No node provided.");
+  }
+}
+
+} // namespace boost
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/boost/CMakeLists.txt
===================================================================
--- clang-tidy/boost/CMakeLists.txt
+++ clang-tidy/boost/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyBoostModule
   BoostTidyModule.cpp
   LexicalCastRedundantTypeCheck.cpp
+  UseToStringCheck.cpp
 
   LINK_LIBS
   clangAST
Index: clang-tidy/boost/BoostTidyModule.cpp
===================================================================
--- clang-tidy/boost/BoostTidyModule.cpp
+++ clang-tidy/boost/BoostTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LexicalCastRedundantTypeCheck.h"
+#include "UseToStringCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -22,6 +23,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<LexicalCastRedundantTypeCheck>(
         "boost-lexical-cast-redundant-type");
+    CheckFactories.registerCheck<UseToStringCheck>(
+        "boost-use-to-string");
   }
 
   ClangTidyOptions getModuleOptions() override {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to