void MisplacedOperatorInStrlenInAllocCheck::registerMatchers( MatchFinder *Finder) { const auto StrLenFunc = functionDecl(anyOf( hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"), hasName("::std::strnlen"), hasName("::strnlen_s"), hasName("::std::strnlen_s"), hasName("::wcslen"), hasName("::std::wcslen"), hasName("::wcsnlen"), hasName("::std::wcsnlen"), hasName("::wcsnlen_s"), hasName("std::wcsnlen_s"))); const auto BadUse = callExpr(callee(StrLenFunc), hasAnyArgument(ignoringImpCasts( binaryOperator( hasOperatorName("+"), hasRHS(ignoringParenImpCasts(integerLiteral(equals(1))))) .bind("BinOp")))) .bind("StrLen"); const auto BadArg = anyOf( allOf(unless(binaryOperator( hasOperatorName("+"), hasLHS(BadUse), hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))), hasDescendant(BadUse)), BadUse); const auto Alloc0Func = functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"), hasName("::alloca"), hasName("std::alloca"))); const auto Alloc1Func = functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"), hasName("::realloc"), hasName("std::realloc"))); const auto Alloc0FuncPtr = varDecl(hasType(isConstQualified()), hasInitializer(ignoringParenImpCasts( declRefExpr(hasDeclaration(Alloc0Func))))); const auto Alloc1FuncPtr = varDecl(hasType(isConstQualified()), hasInitializer(ignoringParenImpCasts( declRefExpr(hasDeclaration(Alloc1Func))))); Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), hasArgument(0, BadArg)) .bind("Alloc"), this); Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), hasArgument(1, BadArg)) .bind("Alloc"), this); Finder->addMatcher( cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this); }
void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { const auto IsGlobal = allOf(hasGlobalStorage(), hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())), // Class scope. unless(isConstexpr())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(IsGlobal, unless(isDefinition())).bind("referencee"))); Finder->addMatcher( varDecl(IsGlobal, isDefinition(), hasInitializer(expr(hasDescendant(ReferencesUndefinedGlobalVar)))) .bind("var"), this); }
void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) { // Add parameters to Parameters. Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind("Parm"), this); // C++ constructor. Finder->addMatcher(cxxConstructorDecl().bind("Ctor"), this); // Track unused parameters, there is Wunused-parameter about unused // parameters. Finder->addMatcher(declRefExpr().bind("Ref"), this); // Analyse parameter usage in function. Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--"))), binaryOperator(), callExpr(), returnStmt(), cxxConstructExpr())) .bind("Mark"), this); Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this); }
void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) { const auto Calc = expr(anyOf(binaryOperator( anyOf(hasOperatorName("+"), hasOperatorName("-"), hasOperatorName("*"), hasOperatorName("<<"))), unaryOperator(hasOperatorName("~"))), hasType(isInteger())) .bind("Calc"); const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); const auto ImplicitCast = implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast"); Finder->addMatcher(varDecl(hasInitializer(Cast)), this); Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this); Finder->addMatcher(callExpr(hasAnyArgument(Cast)), this); Finder->addMatcher(binaryOperator(hasOperatorName("="), hasRHS(Cast)), this); Finder->addMatcher( binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(Cast)), this); }
StatementMatcher LoopMatcher = forStmt( // Node hasLoopInit( // Traversal declStmt( // Node hasSingleDecl( // Traversal varDecl( // Node hasInitializer( // Traversal integerLiteral( // Node equals( // Narrowing 0)))))))).bind("forLoop")
#include "ASTUtility.h" // int *x = NULL or int *x = 0 DeclarationMatcher nullPointerMatcher = varDecl(hasType(pointerType()), hasInitializer(implicitCastExpr().bind("cast"))).bind("var"); // x == NULL or x == 0 StatementMatcher biOpMatcher1 = binaryOperator(hasRHS(implicitCastExpr().bind("castR1")), hasOperatorName("==")).bind("bo1"); // x != NULL or x != 0 StatementMatcher biOpMatcher2 = binaryOperator(hasRHS(implicitCastExpr().bind("castR2")), hasOperatorName("!=")).bind("bo2"); // x != NULL or x != 0 StatementMatcher biOpMatcher3 = binaryOperator(hasRHS(implicitCastExpr().bind("castR3")), hasOperatorName("=")).bind("bo3"); class NullPointerPrinter : public MatchFinder::MatchCallback { public: virtual void run(const MatchFinder::MatchResult &Result) { //get the node clang::ASTContext *Context = Result.Context; const clang::ImplicitCastExpr *cast = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("cast"); const clang::ImplicitCastExpr *castR1 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR1"); const clang::ImplicitCastExpr *castR2 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR2"); const clang::ImplicitCastExpr *castR3 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR3"); const clang::BinaryOperator *bo1 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo1"); const clang::BinaryOperator *bo2 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo2"); const clang::BinaryOperator *bo3 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo3");
StatementMatcher LoopMatcher = forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl( hasInitializer(integerLiteral(equals(0)))))))).bind("forLoop"); class LoopPrinter : public MatchFinder::MatchCallback { public : virtual void run(const MatchFinder::MatchResult &Result) { if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop")) FS->dump(); } };
namespace ProgrammingLanguage { //match naked new DeclarationMatcher nakedNewMatcherPL = varDecl(hasInitializer(newExpr())).bind("var"); }