xref: /llvm-project/clang-tools-extra/clang-tidy/boost/UseToStringCheck.cpp (revision 5625f656678a7d03fa65398d6d751dc88cba75a8)
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 AST_MATCHER(Type, isStrictlyInteger) {
19   return Node.isIntegerType() && !Node.isAnyCharacterType() &&
20          !Node.isBooleanType();
21 }
22 
23 void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
24   if (!getLangOpts().CPlusPlus)
25     return;
26 
27   Finder->addMatcher(
28       callExpr(
29           hasDeclaration(functionDecl(
30               returns(hasDeclaration(classTemplateSpecializationDecl(
31                   hasName("std::basic_string"),
32                   hasTemplateArgument(0,
33                                       templateArgument().bind("char_type"))))),
34               hasName("boost::lexical_cast"),
35               hasParameter(0, hasType(qualType(has(substTemplateTypeParmType(
36                                   isStrictlyInteger()))))))),
37           argumentCountIs(1), unless(isInTemplateInstantiation()))
38           .bind("to_string"),
39       this);
40 }
41 
42 void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
43   const auto *Call = Result.Nodes.getNodeAs<CallExpr>("to_string");
44   auto CharType =
45       Result.Nodes.getNodeAs<TemplateArgument>("char_type")->getAsType();
46 
47   StringRef StringType;
48   if (CharType->isSpecificBuiltinType(BuiltinType::Char_S) ||
49       CharType->isSpecificBuiltinType(BuiltinType::Char_U))
50     StringType = "string";
51   else if (CharType->isSpecificBuiltinType(BuiltinType::WChar_S) ||
52            CharType->isSpecificBuiltinType(BuiltinType::WChar_U))
53     StringType = "wstring";
54   else
55     return;
56 
57   auto Loc = Call->getLocStart();
58   auto Diag =
59       diag(Loc, "use std::to_%0 instead of boost::lexical_cast<std::%0>")
60       << StringType;
61 
62   if (Loc.isMacroID())
63     return;
64 
65   Diag << FixItHint::CreateReplacement(
66       CharSourceRange::getCharRange(Call->getLocStart(),
67                                     Call->getArg(0)->getExprLoc()),
68       (llvm::Twine("std::to_") + StringType + "(").str());
69 }
70 
71 } // namespace boost
72 } // namespace tidy
73 } // namespace clang
74