15625f656SPiotr Padlewski //===--- UseToStringCheck.cpp - clang-tidy---------------------------------===//
25625f656SPiotr Padlewski //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65625f656SPiotr Padlewski //
75625f656SPiotr Padlewski //===----------------------------------------------------------------------===//
85625f656SPiotr Padlewski
95625f656SPiotr Padlewski #include "UseToStringCheck.h"
105625f656SPiotr Padlewski
115625f656SPiotr Padlewski using namespace clang::ast_matchers;
125625f656SPiotr Padlewski
13*7d2ea6c4SCarlos Galvez namespace clang::tidy::boost {
145625f656SPiotr Padlewski
15f8c99297SBenjamin Kramer namespace {
AST_MATCHER(Type,isStrictlyInteger)165625f656SPiotr Padlewski AST_MATCHER(Type, isStrictlyInteger) {
175625f656SPiotr Padlewski return Node.isIntegerType() && !Node.isAnyCharacterType() &&
185625f656SPiotr Padlewski !Node.isBooleanType();
195625f656SPiotr Padlewski }
20f8c99297SBenjamin Kramer } // namespace
215625f656SPiotr Padlewski
registerMatchers(MatchFinder * Finder)225625f656SPiotr Padlewski void UseToStringCheck::registerMatchers(MatchFinder *Finder) {
235625f656SPiotr Padlewski Finder->addMatcher(
245625f656SPiotr Padlewski callExpr(
255625f656SPiotr Padlewski hasDeclaration(functionDecl(
265625f656SPiotr Padlewski returns(hasDeclaration(classTemplateSpecializationDecl(
275625f656SPiotr Padlewski hasName("std::basic_string"),
285625f656SPiotr Padlewski hasTemplateArgument(0,
295625f656SPiotr Padlewski templateArgument().bind("char_type"))))),
305625f656SPiotr Padlewski hasName("boost::lexical_cast"),
315625f656SPiotr Padlewski hasParameter(0, hasType(qualType(has(substTemplateTypeParmType(
325625f656SPiotr Padlewski isStrictlyInteger()))))))),
335625f656SPiotr Padlewski argumentCountIs(1), unless(isInTemplateInstantiation()))
345625f656SPiotr Padlewski .bind("to_string"),
355625f656SPiotr Padlewski this);
365625f656SPiotr Padlewski }
375625f656SPiotr Padlewski
check(const MatchFinder::MatchResult & Result)385625f656SPiotr Padlewski void UseToStringCheck::check(const MatchFinder::MatchResult &Result) {
395625f656SPiotr Padlewski const auto *Call = Result.Nodes.getNodeAs<CallExpr>("to_string");
405625f656SPiotr Padlewski auto CharType =
415625f656SPiotr Padlewski Result.Nodes.getNodeAs<TemplateArgument>("char_type")->getAsType();
425625f656SPiotr Padlewski
435625f656SPiotr Padlewski StringRef StringType;
445625f656SPiotr Padlewski if (CharType->isSpecificBuiltinType(BuiltinType::Char_S) ||
455625f656SPiotr Padlewski CharType->isSpecificBuiltinType(BuiltinType::Char_U))
465625f656SPiotr Padlewski StringType = "string";
475625f656SPiotr Padlewski else if (CharType->isSpecificBuiltinType(BuiltinType::WChar_S) ||
485625f656SPiotr Padlewski CharType->isSpecificBuiltinType(BuiltinType::WChar_U))
495625f656SPiotr Padlewski StringType = "wstring";
505625f656SPiotr Padlewski else
515625f656SPiotr Padlewski return;
525625f656SPiotr Padlewski
5343465bf3SStephen Kelly auto Loc = Call->getBeginLoc();
545625f656SPiotr Padlewski auto Diag =
555625f656SPiotr Padlewski diag(Loc, "use std::to_%0 instead of boost::lexical_cast<std::%0>")
565625f656SPiotr Padlewski << StringType;
575625f656SPiotr Padlewski
585625f656SPiotr Padlewski if (Loc.isMacroID())
595625f656SPiotr Padlewski return;
605625f656SPiotr Padlewski
615625f656SPiotr Padlewski Diag << FixItHint::CreateReplacement(
6243465bf3SStephen Kelly CharSourceRange::getCharRange(Call->getBeginLoc(),
6343465bf3SStephen Kelly Call->getArg(0)->getBeginLoc()),
645625f656SPiotr Padlewski (llvm::Twine("std::to_") + StringType + "(").str());
655625f656SPiotr Padlewski }
665625f656SPiotr Padlewski
67*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::boost
68