void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
  if (!isLanguageVersionSupported(getLangOpts()))
    return;

  // Calling make_smart_ptr from within a member function of a type with a
  // private or protected constructor would be ill-formed.
  auto CanCallCtor = unless(has(ignoringImpCasts(
      cxxConstructExpr(hasDeclaration(decl(unless(isPublic())))))));

  Finder->addMatcher(
      cxxBindTemporaryExpr(has(ignoringParenImpCasts(
          cxxConstructExpr(
              hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
              hasArgument(0,
                          cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
                                         equalsBoundNode(PointerType))))),
                                     CanCallCtor)
                              .bind(NewExpression)),
              unless(isInTemplateInstantiation()))
              .bind(ConstructorCall)))),
      this);

  Finder->addMatcher(
      cxxMemberCallExpr(
          thisPointerType(getSmartPointerTypeMatcher()),
          callee(cxxMethodDecl(hasName("reset"))),
          hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)),
          unless(isInTemplateInstantiation()))
          .bind(ResetCall),
      this);
}
Ejemplo n.º 2
0
void FoldInitTypeCheck::registerMatchers(MatchFinder *Finder) {
  // We match functions of interest and bind the iterator and init value types.
  // Note: Right now we check only builtin types.
  const auto BuiltinTypeWithId = [](const char *ID) {
    return hasCanonicalType(builtinType().bind(ID));
  };
  const auto IteratorWithValueType = [&BuiltinTypeWithId](const char *ID) {
    return anyOf(
        // Pointer types.
        pointsTo(BuiltinTypeWithId(ID)),
        // Iterator types.
        recordType(hasDeclaration(has(typedefNameDecl(
            hasName("value_type"), hasType(BuiltinTypeWithId(ID)))))));
  };

  const auto IteratorParam = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
  const auto Iterator2Param = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
  const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));

  // std::accumulate, std::reduce.
  Finder->addMatcher(
      callExpr(callee(functionDecl(
                   hasAnyName("::std::accumulate", "::std::reduce"),
                   hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
               argumentCountIs(3))
          .bind("Call"),
      this);
  // std::inner_product.
  Finder->addMatcher(
      callExpr(callee(functionDecl(hasName("::std::inner_product"),
                                   hasParameter(0, IteratorParam),
                                   hasParameter(2, Iterator2Param),
                                   hasParameter(3, InitParam))),
               argumentCountIs(4))
          .bind("Call"),
      this);
  // std::reduce with a policy.
  Finder->addMatcher(
      callExpr(callee(functionDecl(hasName("::std::reduce"),
                                   hasParameter(1, IteratorParam),
                                   hasParameter(3, InitParam))),
               argumentCountIs(4))
          .bind("Call"),
      this);
  // std::inner_product with a policy.
  Finder->addMatcher(
      callExpr(callee(functionDecl(hasName("::std::inner_product"),
                                   hasParameter(1, IteratorParam),
                                   hasParameter(3, Iterator2Param),
                                   hasParameter(4, InitParam))),
               argumentCountIs(5))
          .bind("Call"),
      this);
}
void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) {
  const auto ExpensiveValueParamDecl =
      parmVarDecl(hasType(hasCanonicalType(allOf(matchers::isExpensiveToCopy(),
                                                 unless(referenceType())))),
                  decl().bind("param"));
  Finder->addMatcher(
      functionDecl(isDefinition(), unless(cxxMethodDecl(isOverride())),
                   unless(isInstantiated()),
                   has(typeLoc(forEach(ExpensiveValueParamDecl))),
                   decl().bind("functionDecl")),
      this);
}
void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType(
                             hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
                                 hasName("std::exception")))))))))),
                         has(expr(unless(cxxUnresolvedConstructExpr()))),
                         eachOf(has(expr(hasType(namedDecl().bind("decl")))),
                                anything())))
          .bind("bad_throw"),
      this);
}
void SizeofContainerCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      expr(unless(isInTemplateInstantiation()),
           expr(sizeOfExpr(has(ignoringParenImpCasts(
                    expr(hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
                        matchesName("^(::std::|::string)"),
                        unless(matchesName("^::std::(bitset|array)$")),
                        hasMethod(cxxMethodDecl(hasName("size"), isPublic(),
                                                isConst())))))))))))
               .bind("sizeof"),
           // Ignore ARRAYSIZE(<array of containers>) pattern.
           unless(hasAncestor(binaryOperator(
               anyOf(hasOperatorName("/"), hasOperatorName("%")),
               hasLHS(ignoringParenCasts(sizeOfExpr(expr()))),
               hasRHS(ignoringParenCasts(equalsBoundNode("sizeof"))))))),
      this);
}