diff options
Diffstat (limited to 'Utilities/ClangTidyModule/UseCmstrlenCheck.cxx')
-rw-r--r-- | Utilities/ClangTidyModule/UseCmstrlenCheck.cxx | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx new file mode 100644 index 0000000000..d4bae1f794 --- /dev/null +++ b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx @@ -0,0 +1,78 @@ +/* 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 <clang/ASTMatchers/ASTMatchFinder.h> + +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<Expr>("strlen"); + const BinaryOperator* SizeOfMinus = + Result.Nodes.getNodeAs<BinaryOperator>("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<ParenExpr>("paren"); + const UnaryExprOrTypeTraitExpr* SizeOf = + Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeOf"); + const IntegerLiteral* Literal = + Result.Nodes.getNodeAs<IntegerLiteral>("literal"); + + std::vector<FixItHint> 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; + } +} +} +} +} |