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