Add boost-use-to-string
http://reviews.llvm.org/D18136 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@268079 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
80f25a0692
Коммит
889329f9f2
|
@ -27,6 +27,7 @@ add_clang_library(clangTidy
|
|||
|
||||
add_subdirectory(tool)
|
||||
add_subdirectory(plugin)
|
||||
add_subdirectory(boost)
|
||||
add_subdirectory(cert)
|
||||
add_subdirectory(llvm)
|
||||
add_subdirectory(cppcoreguidelines)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//===------- BoostTidyModule.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 "../ClangTidy.h"
|
||||
#include "../ClangTidyModule.h"
|
||||
#include "../ClangTidyModuleRegistry.h"
|
||||
#include "UseToStringCheck.h"
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace boost {
|
||||
|
||||
class BoostModule : public ClangTidyModule {
|
||||
public:
|
||||
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
|
||||
CheckFactories.registerCheck<UseToStringCheck>("boost-use-to-string");
|
||||
}
|
||||
};
|
||||
|
||||
// Register the BoostModule using this statically initialized variable.
|
||||
static ClangTidyModuleRegistry::Add<BoostModule> X("boost-module",
|
||||
"Add boost checks.");
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// This anchor is used to force the linker to link in the generated object file
|
||||
// and thus register the BoostModule.
|
||||
volatile int BoostModuleAnchorSource = 0;
|
||||
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,14 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_clang_library(clangTidyBoostModule
|
||||
BoostTidyModule.cpp
|
||||
UseToStringCheck.cpp
|
||||
|
||||
LINK_LIBS
|
||||
clangAST
|
||||
clangASTMatchers
|
||||
clangBasic
|
||||
clangLex
|
||||
clangTidy
|
||||
clangTidyUtils
|
||||
)
|
|
@ -0,0 +1,73 @@
|
|||
//===--- 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 {
|
||||
|
||||
AST_MATCHER(Type, isStrictlyInteger) {
|
||||
return Node.isIntegerType() && !Node.isAnyCharacterType() &&
|
||||
!Node.isBooleanType();
|
||||
}
|
||||
|
||||
void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
|
||||
if (!getLangOpts().CPlusPlus)
|
||||
return;
|
||||
|
||||
Finder->addMatcher(
|
||||
callExpr(
|
||||
hasDeclaration(functionDecl(
|
||||
returns(hasDeclaration(classTemplateSpecializationDecl(
|
||||
hasName("std::basic_string"),
|
||||
hasTemplateArgument(0,
|
||||
templateArgument().bind("char_type"))))),
|
||||
hasName("boost::lexical_cast"),
|
||||
hasParameter(0, hasType(qualType(has(substTemplateTypeParmType(
|
||||
isStrictlyInteger()))))))),
|
||||
argumentCountIs(1), unless(isInTemplateInstantiation()))
|
||||
.bind("to_string"),
|
||||
this);
|
||||
}
|
||||
|
||||
void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("to_string");
|
||||
auto CharType =
|
||||
Result.Nodes.getNodeAs<TemplateArgument>("char_type")->getAsType();
|
||||
|
||||
StringRef StringType;
|
||||
if (CharType->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
||||
CharType->isSpecificBuiltinType(BuiltinType::Char_U))
|
||||
StringType = "string";
|
||||
else if (CharType->isSpecificBuiltinType(BuiltinType::WChar_S) ||
|
||||
CharType->isSpecificBuiltinType(BuiltinType::WChar_U))
|
||||
StringType = "wstring";
|
||||
else
|
||||
return;
|
||||
|
||||
auto Loc = Call->getLocStart();
|
||||
auto Diag =
|
||||
diag(Loc, "use std::to_%0 instead of boost::lexical_cast<std::%0>")
|
||||
<< StringType;
|
||||
|
||||
if (Loc.isMacroID())
|
||||
return;
|
||||
|
||||
Diag << FixItHint::CreateReplacement(
|
||||
CharSourceRange::getCharRange(Call->getLocStart(),
|
||||
Call->getArg(0)->getExprLoc()),
|
||||
(llvm::Twine("std::to_") + StringType + "(").str());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,37 @@
|
|||
//===--- 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 {
|
||||
|
||||
/// Finds calls to ``boost::lexical_cast<std::string>`` and
|
||||
/// ``boost::lexical_cast<std::wstring>`` and replaces them with
|
||||
/// ``std::to_string`` and ``std::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;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
|
|
@ -8,6 +8,7 @@ add_clang_library(clangTidyPlugin
|
|||
clangFrontend
|
||||
clangSema
|
||||
clangTidy
|
||||
clangTidyBoostModule
|
||||
clangTidyCERTModule
|
||||
clangTidyCppCoreGuidelinesModule
|
||||
clangTidyGoogleModule
|
||||
|
|
|
@ -10,6 +10,7 @@ target_link_libraries(clang-tidy
|
|||
clangASTMatchers
|
||||
clangBasic
|
||||
clangTidy
|
||||
clangTidyBoostModule
|
||||
clangTidyCERTModule
|
||||
clangTidyCppCoreGuidelinesModule
|
||||
clangTidyGoogleModule
|
||||
|
|
|
@ -418,6 +418,11 @@ extern volatile int CERTModuleAnchorSource;
|
|||
static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination =
|
||||
CERTModuleAnchorSource;
|
||||
|
||||
// This anchor is used to force the linker to link the BoostModule.
|
||||
extern volatile int BoostModuleAnchorSource;
|
||||
static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
|
||||
BoostModuleAnchorSource;
|
||||
|
||||
// This anchor is used to force the linker to link the LLVMModule.
|
||||
extern volatile int LLVMModuleAnchorSource;
|
||||
static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
|
||||
|
|
|
@ -217,6 +217,13 @@ identified. The improvements since the 3.8 release include:
|
|||
|
||||
Finds static function and variable definitions in anonymous namespace.
|
||||
|
||||
- New Boost module containing checks for issues with Boost library
|
||||
|
||||
- New `boost-use-to-string
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/boost-use-to-string.html>`_ check
|
||||
|
||||
Finds usages of boost::lexical_cast<std::string> and changes it to std::to_string.
|
||||
|
||||
Fixed bugs:
|
||||
|
||||
- Crash when running on compile database with relative source files paths.
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
.. title:: clang-tidy - boost-use-to-string
|
||||
|
||||
boost-use-to-string
|
||||
===================
|
||||
|
||||
This check finds conversion from integer type like ``int`` to ``std::string`` or
|
||||
``std::wstring`` using ``boost::lexical_cast``, and replace it with calls to
|
||||
``std::to_string`` and ``std::to_wstring``.
|
||||
|
||||
It doesn't replace conversion from floating points despite the ``to_string``
|
||||
overloads, because it would change the behaviour.
|
||||
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
auto str = boost::lexical_cast<std::string>(42);
|
||||
auto wstr = boost::lexical_cast<std::wstring>(2137LL);
|
||||
|
||||
// Will be changed to
|
||||
auto str = std::to_string(42);
|
||||
auto wstr = std::to_wstring(2137LL);
|
||||
|
|
@ -4,6 +4,8 @@ Clang-Tidy Checks
|
|||
=========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
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>
|
||||
|
|
|
@ -67,6 +67,8 @@ There are currently the following groups of checks:
|
|||
|
||||
* Clang static analyzer checks are named starting with ``clang-analyzer-``.
|
||||
|
||||
* Checks related to Boost library starts with ``boost-``.
|
||||
|
||||
Clang diagnostics are treated in a similar way as check diagnostics. Clang
|
||||
diagnostics are displayed by clang-tidy and can be filtered out using
|
||||
``-checks=`` option. However, the ``-checks=`` option does not affect
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
// 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);
|
||||
|
||||
auto z = boost::lexical_cast<std::string>(42LL);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::to_string {{..}}
|
||||
// CHECK-FIXES: auto z = std::to_string(42LL);
|
||||
|
||||
// this should not trigger
|
||||
fun(boost::lexical_cast<std::string>(42.0));
|
||||
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;
|
||||
bool j;
|
||||
|
||||
fun(boost::lexical_cast<std::string>(a));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::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 {{..}}
|
||||
// CHECK-FIXES: fun(std::to_string(b));
|
||||
fun(boost::lexical_cast<std::string>(c));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::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 {{..}}
|
||||
// CHECK-FIXES: fun(std::to_string(d));
|
||||
fun(boost::lexical_cast<std::string>(e));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::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 {{..}}
|
||||
// CHECK-FIXES: fun(std::to_string(f));
|
||||
|
||||
// No change for floating numbers.
|
||||
fun(boost::lexical_cast<std::string>(g));
|
||||
fun(boost::lexical_cast<std::string>(h));
|
||||
fun(boost::lexical_cast<std::string>(i));
|
||||
// And bool.
|
||||
fun(boost::lexical_cast<std::string>(j));
|
||||
}
|
||||
|
||||
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;
|
||||
bool j;
|
||||
|
||||
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 {{..}}
|
||||
// CHECK-FIXES: fun(std::to_wstring(b));
|
||||
fun(boost::lexical_cast<std::wstring>(c));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring {{..}}
|
||||
// CHECK-FIXES: fun(std::to_wstring(c));
|
||||
fun(boost::lexical_cast<std::wstring>(d));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring {{..}}
|
||||
// CHECK-FIXES: fun(std::to_wstring(d));
|
||||
fun(boost::lexical_cast<std::wstring>(e));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring {{..}}
|
||||
// CHECK-FIXES: fun(std::to_wstring(e));
|
||||
fun(boost::lexical_cast<std::wstring>(f));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::to_wstring {{..}}
|
||||
// CHECK-FIXES: fun(std::to_wstring(f));
|
||||
|
||||
// No change for floating numbers
|
||||
fun(boost::lexical_cast<std::wstring>(g));
|
||||
fun(boost::lexical_cast<std::wstring>(h));
|
||||
fun(boost::lexical_cast<std::wstring>(i));
|
||||
// and bool.
|
||||
fun(boost::lexical_cast<std::wstring>(j));
|
||||
}
|
||||
|
||||
const auto glob = boost::lexical_cast<std::string>(42);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::to_string{{..}}
|
||||
// CHECK-FIXES: const auto glob = std::to_string(42);
|
||||
|
||||
template <typename T>
|
||||
void string_as_T(T t = T()) {
|
||||
boost::lexical_cast<std::string>(42);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string{{..}}
|
||||
// CHECK-FIXES: std::to_string(42);
|
||||
|
||||
boost::lexical_cast<T>(42);
|
||||
string_as_T(boost::lexical_cast<T>(42));
|
||||
auto p = boost::lexical_cast<T>(42);
|
||||
auto p2 = (T)boost::lexical_cast<T>(42);
|
||||
auto p3 = static_cast<T>(boost::lexical_cast<T>(42));
|
||||
}
|
||||
|
||||
#define my_to_string boost::lexical_cast<std::string>
|
||||
|
||||
void no_fixup_inside_macro() {
|
||||
my_to_string(12);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use std::to_string{{..}}
|
||||
}
|
||||
|
||||
void no_warnings() {
|
||||
fun(boost::lexical_cast<std::string>("abc"));
|
||||
fun(boost::lexical_cast<std::wstring>("abc"));
|
||||
fun(boost::lexical_cast<std::string>(my_weird_type{}));
|
||||
string_as_T<int>();
|
||||
string_as_T<std::string>();
|
||||
}
|
Загрузка…
Ссылка в новой задаче