xref: /llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.cpp (revision f8c99297d35dbc1a5cccbda8949b21679b67e94a)
1 //===--- UseToStringCheck.cpp - clang-tidy---------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "UseToStringCheck.h"
11 
12 using namespace clang::ast_matchers;
13 
14 namespace clang {
15 namespace tidy {
16 namespace boost {
17 
18 namespace {
19 AST_MATCHER(Type, isStrictlyInteger) {
20   return Node.isIntegerType() && !Node.isAnyCharacterType() &&
21          !Node.isBooleanType();
22 }
23 } // namespace
24 
25 void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
26   if (!getLangOpts().CPlusPlus)
27     return;
28 
29   Finder->addMatcher(
30       callExpr(
31           hasDeclaration(functionDecl(
32               returns(hasDeclaration(classTemplateSpecializationDecl(
33                   hasName("std::basic_string"),
34                   hasTemplateArgument(0,
35                                       templateArgument().bind("char_type"))))),
36               hasName("boost::lexical_cast"),
37               hasParameter(0, hasType(qualType(has(substTemplateTypeParmType(
38                                   isStrictlyInteger()))))))),
39           argumentCountIs(1), unless(isInTemplateInstantiation()))
40           .bind("to_string"),
41       this);
42 }
43 
44 void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
45   const auto *Call = Result.Nodes.getNodeAs<CallExpr>("to_string");
46   auto CharType =
47       Result.Nodes.getNodeAs<TemplateArgument>("char_type")->getAsType();
48 
49   StringRef StringType;
50   if (CharType->isSpecificBuiltinType(BuiltinType::Char_S) ||
51       CharType->isSpecificBuiltinType(BuiltinType::Char_U))
52     StringType = "string";
53   else if (CharType->isSpecificBuiltinType(BuiltinType::WChar_S) ||
54            CharType->isSpecificBuiltinType(BuiltinType::WChar_U))
55     StringType = "wstring";
56   else
57     return;
58 
59   auto Loc = Call->getLocStart();
60   auto Diag =
61       diag(Loc, "use std::to_%0 instead of boost::lexical_cast<std::%0>")
62       << StringType;
63 
64   if (Loc.isMacroID())
65     return;
66 
67   Diag << FixItHint::CreateReplacement(
68       CharSourceRange::getCharRange(Call->getLocStart(),
69                                     Call->getArg(0)->getLocStart()),
70       (llvm::Twine("std::to_") + StringType + "(").str());
71 }
72 
73 } // namespace boost
74 } // namespace tidy
75 } // namespace clang
76