diff options
Diffstat (limited to 'Utilities/ClangTidyModule/UseCmstrlenCheck.cxx')
-rw-r--r-- | Utilities/ClangTidyModule/UseCmstrlenCheck.cxx | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx index 590d260..d4bae1f 100644 --- a/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx +++ b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx @@ -17,17 +17,61 @@ UseCmstrlenCheck::UseCmstrlenCheck(StringRef Name, ClangTidyContext* Context) void UseCmstrlenCheck::registerMatchers(MatchFinder* Finder) { Finder->addMatcher(callExpr(callee(functionDecl(hasName("::strlen"))), - callee(expr().bind("callee")), + 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* Node = Result.Nodes.getNodeAs<Expr>("callee"); + 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"); - this->diag(Node->getBeginLoc(), "use cmStrLen() for string literals") - << FixItHint::CreateReplacement(Node->getSourceRange(), "cmStrLen"); + 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; + } } } } |