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); }
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; }