void InaccurateEraseCheck::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 auto CheckForEndCall = hasArgument(
      1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts(
                   cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
                       .bind("InaccEndCall")))),
               anything()));

  Finder->addMatcher(
      cxxMemberCallExpr(
          on(hasType(namedDecl(matchesName("^::std::")))),
          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
          hasArgument(0, has(ignoringParenImpCasts(
                             callExpr(callee(functionDecl(matchesName(
                                          "^::std::(remove(_if)?|unique)$"))),
                                      CheckForEndCall)
                                 .bind("InaccAlgCall")))),
          unless(isInTemplateInstantiation()))
          .bind("InaccErase"),
      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);
}
MakeSharedCheck::SmartPtrTypeMatcher
MakeSharedCheck::getSmartPointerTypeMatcher() const {
  return qualType(hasDeclaration(classTemplateSpecializationDecl(
      matchesName("::std::shared_ptr"), templateArgumentCountIs(1),
      hasTemplateArgument(
          0, templateArgument(refersToType(qualType().bind(PointerType)))))));
}
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);
}
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
  // this check should only be applied to ObjC sources.
  if (!getLangOpts().ObjC) return;

  Finder->addMatcher(objcPropertyDecl(
                         // the property name should be in Lower Camel Case like
                         // 'lowerCamelCase'
                         unless(matchesName(validPropertyNameRegex(true))))
                         .bind("property"),
                     this);
}
void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) {
  // This check should only be applied to Objective-C sources.
  if (!getLangOpts().ObjC)
    return;

  // Enforce Objective-C function naming conventions on all functions except:
  // • Functions defined in system headers.
  // • C++ member functions.
  // • Namespaced functions.
  // • Implicitly defined functions.
  // • The main function.
  Finder->addMatcher(
      functionDecl(
          unless(anyOf(isExpansionInSystemHeader(), cxxMethodDecl(),
                       hasAncestor(namespaceDecl()), isMain(), isImplicit(),
                       matchesName(validFunctionNameRegex(true)),
                       allOf(isStaticStorageClass(),
                             matchesName(validFunctionNameRegex(false))))))
          .bind("function"),
      this);
}
示例#7
0
bool JitConfigValues::MethodSet::contains(const char*       methodName,
                                          const char*       className,
                                          CORINFO_SIG_INFO* sigInfo) const
{
    int numArgs = sigInfo != nullptr ? sigInfo->numArgs : -1;

    // Try to match any the entries in the list.
    for (MethodName* name = m_names; name != nullptr; name = name->m_next)
    {
        // If m_numArgs is valid, check for a mismatch
        if (name->m_numArgs != -1 && name->m_numArgs != numArgs)
        {
            continue;
        }

        // If m_methodNameStart is valid, check for a mismatch
        if (name->m_methodNameStart != -1)
        {
            const char* expectedMethodName = &m_list[name->m_methodNameStart];
            if (!matchesName(expectedMethodName, name->m_methodNameLen, methodName))
            {
                // C++ embeds the class name into the method name; deal with that here.
                const char* colon = strchr(methodName, ':');
                if (colon != nullptr && colon[1] == ':' &&
                    matchesName(expectedMethodName, name->m_methodNameLen, methodName))
                {
                    int classLen = (int)(colon - methodName);
                    if (name->m_classNameStart == -1 ||
                        (classLen == name->m_classNameLen &&
                         strncmp(&m_list[name->m_classNameStart], methodName, classLen) == 0))
                    {
                        return true;
                    }
                }
                continue;
            }
        }

        // If m_classNameStart is valid, check for a mismatch
        if (className == nullptr || name->m_classNameStart == -1 ||
            matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, className))
        {
            return true;
        }

        // Check for suffix wildcard like System.*
        if (name->m_classNameLen > 0 && m_list[name->m_classNameStart + name->m_classNameLen - 1] == '*' &&
            strncmp(&m_list[name->m_classNameStart], className, name->m_classNameLen - 1) == 0)
        {
            return true;
        }

#ifdef _DEBUG
        // Maybe className doesn't include the namespace. Try to match that
        const char* nsSep = strrchr(className, '.');
        if (nsSep != nullptr && nsSep != className)
        {
            const char* onlyClass = nsSep[-1] == '.' ? nsSep : &nsSep[1];
            if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, onlyClass))
            {
                return true;
            }
        }
#endif
    }

    return false;
}