void AssignOperatorSignatureCheck::registerMatchers(
    ast_matchers::MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (getLangOpts().CPlusPlus) {
    const auto HasGoodReturnType = methodDecl(returns(lValueReferenceType(
        pointee(unless(isConstQualified()),
                hasDeclaration(equalsBoundNode("class"))))));

    const auto IsSelf = qualType(anyOf(
        hasDeclaration(equalsBoundNode("class")),
        referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
    const auto IsSelfAssign =
        methodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
                   hasName("operator="), ofClass(recordDecl().bind("class")),
                   hasParameter(0, parmVarDecl(hasType(IsSelf))))
            .bind("method");

    Finder->addMatcher(
        methodDecl(IsSelfAssign, unless(HasGoodReturnType)).bind("ReturnType"),
        this);

    const auto BadSelf = referenceType(
        anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
              rValueReferenceType(pointee(isConstQualified()))));

    Finder->addMatcher(
        methodDecl(IsSelfAssign, hasParameter(0, parmVarDecl(hasType(BadSelf))))
            .bind("ArgumentType"),
        this);

    Finder->addMatcher(methodDecl(IsSelfAssign, isConst()).bind("Const"), this);
  }
}
void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const std::string Algorithms =
      "^::std::(find|count|equal_range|lower_bound|upper_bound)$";
  const auto ContainerMatcher = classTemplateSpecializationDecl(
      matchesName("^::std::(unordered_)?(multi)?(set|map)$"));
  const auto Matcher =
      callExpr(
          callee(functionDecl(matchesName(Algorithms))),
          hasArgument(
              0, constructExpr(has(memberCallExpr(
                     callee(methodDecl(hasName("begin"))),
                     on(declRefExpr(
                            hasDeclaration(decl().bind("IneffContObj")),
                            anyOf(hasType(ContainerMatcher.bind("IneffCont")),
                                  hasType(pointsTo(
                                      ContainerMatcher.bind("IneffContPtr")))))
                            .bind("IneffContExpr")))))),
          hasArgument(1, constructExpr(has(memberCallExpr(
                             callee(methodDecl(hasName("end"))),
                             on(declRefExpr(hasDeclaration(
                                 equalsBoundNode("IneffContObj")))))))),
          hasArgument(2, expr().bind("AlgParam")),
          unless(isInTemplateInstantiation()))
          .bind("IneffAlg");

  Finder->addMatcher(Matcher, this);
}
namespace EffectiveCPP {

    StatementMatcher ctorCallVtlMatcherEC = compoundStmt(
            hasParent(constructorDecl().bind("cDecl")),
            hasDescendant(callExpr(callee(methodDecl(isVirtual()))))
            );
    
    StatementMatcher dtorCallVtlMatcherEC = compoundStmt(
            hasParent(destructorDecl().bind("dDecl")),
            hasDescendant(callExpr(callee(methodDecl(isVirtual()))))
            );
}
void
OverloadedUnaryAndCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
    // Match unary methods that overload operator&.
    Finder->addMatcher(methodDecl(parameterCountIs(0), hasOverloadedOperatorName(
                                      "&")).bind("overload"),
                       this);
    // Also match freestanding unary operator& overloads. Be careful not to match
    // binary methods.
    Finder->addMatcher(
        functionDecl(
            allOf(unless(methodDecl()),
                  functionDecl(parameterCountIs(1),
                               hasOverloadedOperatorName("&")).bind("overload"))),
        this);
}
void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
  const auto WrongUse = anyOf(
      hasParent(
          binaryOperator(
              anyOf(has(integerLiteral(equals(0))),
                    allOf(anyOf(hasOperatorName("<"), hasOperatorName(">="),
                                hasOperatorName(">"), hasOperatorName("<=")),
                          hasEitherOperand(integerLiteral(equals(1))))))
              .bind("SizeBinaryOp")),
      hasParent(implicitCastExpr(
          hasImplicitDestinationType(isBoolType()),
          anyOf(
              hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")),
              anything()))),
      hasParent(explicitCastExpr(hasDestinationType(isBoolType()))));

  Finder->addMatcher(
      memberCallExpr(
          on(expr(anyOf(hasType(namedDecl(stlContainer())),
                        hasType(pointsTo(namedDecl(stlContainer()))),
                        hasType(references(namedDecl(stlContainer())))))
                 .bind("STLObject")),
          callee(methodDecl(hasName("size"))), WrongUse).bind("SizeCallExpr"),
      this);
}
void NoexceptMoveConstructorCheck::registerMatchers(MatchFinder *Finder) {
    Finder->addMatcher(
        methodDecl(anyOf(constructorDecl(), hasOverloadedOperatorName("=")),
                   unless(isImplicit()), unless(isDeleted()))
        .bind("decl"),
        this);
}
void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
  // Swap as a function need not to be considered, because rvalue can not
  // be bound to a non-const reference.
  const auto ShrinkableAsMember =
      memberExpr(member(valueDecl().bind("ContainerDecl")));
  const auto ShrinkableAsDecl =
      declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
  const auto CopyCtorCall = constructExpr(
      hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
                           unaryOperator(has(ShrinkableAsMember)),
                           unaryOperator(has(ShrinkableAsDecl)))));
  const auto SwapParam = expr(anyOf(
      memberExpr(member(equalsBoundNode("ContainerDecl"))),
      declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
      unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))),
      unaryOperator(
          has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl")))))));

  Finder->addMatcher(
      memberCallExpr(on(hasType(namedDecl(stlShrinkableContainer()))),
                     callee(methodDecl(hasName("swap"))),
                     has(memberExpr(hasDescendant(CopyCtorCall))),
                     hasArgument(0, SwapParam.bind("ContainerToShrink")),
                     unless(isInTemplateInstantiation()))
          .bind("CopyAndSwapTrick"),
      this);
}
void UniqueptrResetReleaseCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++11; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus11)
    return;

  Finder->addMatcher(
      memberCallExpr(
          on(expr().bind("left")), callee(memberExpr().bind("reset_member")),
          callee(methodDecl(hasName("reset"),
                            ofClass(recordDecl(hasName("::std::unique_ptr"),
                                               decl().bind("left_class"))))),
          has(memberCallExpr(
              on(expr().bind("right")),
              callee(memberExpr().bind("release_member")),
              callee(methodDecl(
                  hasName("release"),
                  ofClass(recordDecl(hasName("::std::unique_ptr"),
                                     decl().bind("right_class"))))))))
          .bind("reset_call"),
      this);
}
Example #9
0
void UseOverride::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(methodDecl(isOverride()).bind("method"), this);
}
void UseOverrideCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matcher for C++11.
  if (getLangOpts().CPlusPlus11)
    Finder->addMatcher(methodDecl(isOverride()).bind("method"), this);
}