/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "UseCmstrlenCheck.h" #include namespace clang { namespace tidy { namespace cmake { using namespace ast_matchers; UseCmstrlenCheck::UseCmstrlenCheck(StringRef Name, ClangTidyContext* Context) : ClangTidyCheck(Name, Context) { } void UseCmstrlenCheck::registerMatchers(MatchFinder* Finder) { Finder->addMatcher(callExpr(callee(functionDecl(hasName("::strlen"))), callee(expr().bind("strlen")), hasArgument(0, stringLiteral())), this); auto IsSizeOfStringLiteral = unaryExprOrTypeTraitExpr( ofKind(UETT_SizeOf), anyOf(has(parenExpr(has(stringLiteral())).bind("paren")), has(stringLiteral()))) .bind("sizeOf"); Finder->addMatcher( binaryOperator( hasOperatorName("-"), hasLHS(anyOf( binaryOperator(hasOperatorName("+"), hasRHS(IsSizeOfStringLiteral)), IsSizeOfStringLiteral)), hasRHS(implicitCastExpr(has(integerLiteral(equals(1)).bind("literal"))))) .bind("sizeOfMinus"), this); } void UseCmstrlenCheck::check(const MatchFinder::MatchResult& Result) { const Expr* Strlen = Result.Nodes.getNodeAs("strlen"); const BinaryOperator* SizeOfMinus = Result.Nodes.getNodeAs("sizeOfMinus"); if (Strlen) { this->diag(Strlen->getBeginLoc(), "use cmStrLen() for string literals") << FixItHint::CreateReplacement(Strlen->getSourceRange(), "cmStrLen"); } if (SizeOfMinus) { const ParenExpr* Paren = Result.Nodes.getNodeAs("paren"); const UnaryExprOrTypeTraitExpr* SizeOf = Result.Nodes.getNodeAs("sizeOf"); const IntegerLiteral* Literal = Result.Nodes.getNodeAs("literal"); std::vector FixIts; if (Paren) { FixIts.push_back( FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen")); FixIts.push_back(FixItHint::CreateRemoval( SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation()))); } else { FixIts.push_back( FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen(")); FixIts.push_back(FixItHint::CreateReplacement( SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation()), ")")); } this->diag(SizeOf->getOperatorLoc(), "use cmStrLen() for string literals") << FixIts; } } } } }