UseCmstrlenCheck.cxx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file LICENSE.rst or https://cmake.org/licensing for details. */
  3. #include "UseCmstrlenCheck.h"
  4. #include <clang/ASTMatchers/ASTMatchFinder.h>
  5. namespace clang {
  6. namespace tidy {
  7. namespace cmake {
  8. using namespace ast_matchers;
  9. UseCmstrlenCheck::UseCmstrlenCheck(StringRef Name, ClangTidyContext* Context)
  10. : ClangTidyCheck(Name, Context)
  11. {
  12. }
  13. void UseCmstrlenCheck::registerMatchers(MatchFinder* Finder)
  14. {
  15. Finder->addMatcher(callExpr(callee(functionDecl(hasName("::strlen"))),
  16. callee(expr().bind("strlen")),
  17. hasArgument(0, stringLiteral())),
  18. this);
  19. auto IsSizeOfStringLiteral =
  20. unaryExprOrTypeTraitExpr(
  21. ofKind(UETT_SizeOf),
  22. anyOf(has(parenExpr(has(stringLiteral())).bind("paren")),
  23. has(stringLiteral())))
  24. .bind("sizeOf");
  25. Finder->addMatcher(
  26. binaryOperator(
  27. hasOperatorName("-"),
  28. hasLHS(anyOf(
  29. binaryOperator(hasOperatorName("+"), hasRHS(IsSizeOfStringLiteral)),
  30. IsSizeOfStringLiteral)),
  31. hasRHS(implicitCastExpr(has(integerLiteral(equals(1)).bind("literal")))))
  32. .bind("sizeOfMinus"),
  33. this);
  34. }
  35. void UseCmstrlenCheck::check(MatchFinder::MatchResult const& Result)
  36. {
  37. Expr const* Strlen = Result.Nodes.getNodeAs<Expr>("strlen");
  38. BinaryOperator const* SizeOfMinus =
  39. Result.Nodes.getNodeAs<BinaryOperator>("sizeOfMinus");
  40. if (Strlen) {
  41. this->diag(Strlen->getBeginLoc(), "use cmStrLen() for string literals")
  42. << FixItHint::CreateReplacement(Strlen->getSourceRange(), "cmStrLen");
  43. }
  44. if (SizeOfMinus) {
  45. ParenExpr const* Paren = Result.Nodes.getNodeAs<ParenExpr>("paren");
  46. UnaryExprOrTypeTraitExpr const* SizeOf =
  47. Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeOf");
  48. IntegerLiteral const* Literal =
  49. Result.Nodes.getNodeAs<IntegerLiteral>("literal");
  50. std::vector<FixItHint> FixIts;
  51. if (Paren) {
  52. FixIts.push_back(
  53. FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen"));
  54. FixIts.push_back(FixItHint::CreateRemoval(
  55. SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation())));
  56. } else {
  57. FixIts.push_back(
  58. FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen("));
  59. FixIts.push_back(FixItHint::CreateReplacement(
  60. SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation()),
  61. ")"));
  62. }
  63. this->diag(SizeOf->getOperatorLoc(), "use cmStrLen() for string literals")
  64. << FixIts;
  65. }
  66. }
  67. }
  68. }
  69. }