|
@@ -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;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|