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); }
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); }
TEST(CXXConstructExpr, SourceRange) { RangeVerifier<CXXConstructExpr> Verifier; Verifier.expectRange(3, 14, 3, 19); EXPECT_TRUE(Verifier.match( "struct A { A(int, int); };\n" "void f(A a);\n" "void g() { f({0, 0}); }", constructExpr(), Lang_CXX11)); }
TEST(ObjCMessageExpr, CXXConstructExprRange) { RangeVerifier<CXXConstructExpr> Verifier; Verifier.expectRange(5, 25, 5, 27); EXPECT_TRUE(Verifier.match( "struct A { int a; };\n" "@interface B {}\n" "+ (void) f1: (A)arg;\n" "@end\n" "void f2() { A a; [B f1: (a)]; }\n", constructExpr(), Lang_OBJCXX)); }
void MoveConstructorInitCheck::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) { Finder->addMatcher( constructorDecl(unless(isImplicit()), allOf( isMoveConstructor(), hasAnyConstructorInitializer( ctorInitializer(withInitializer(constructExpr(hasDeclaration( constructorDecl(isCopyConstructor()).bind("ctor") )))).bind("init") ) )), this); } }