void StringLiteralWithEmbeddedNulCheck::registerMatchers(MatchFinder *Finder) { // Match a string that contains embedded NUL character. Extra-checks are // applied in |check| to find incorectly escaped characters. Finder->addMatcher(stringLiteral(containsNul()).bind("strlit"), this); // The remaining checks only apply to C++. if (!getLangOpts().CPlusPlus) return; const auto StrLitWithNul = ignoringParenImpCasts(stringLiteral(containsNul()).bind("truncated")); // Match string constructor. const auto StringConstructorExpr = expr(anyOf( cxxConstructExpr(argumentCountIs(1), hasDeclaration(cxxMethodDecl(hasName("basic_string")))), // If present, the second argument is the alloc object which must not // be present explicitly. cxxConstructExpr(argumentCountIs(2), hasDeclaration(cxxMethodDecl(hasName("basic_string"))), hasArgument(1, cxxDefaultArgExpr())))); // Detect passing a suspicious string literal to a string constructor. // example: std::string str = "abc\0def"; Finder->addMatcher( cxxConstructExpr(StringConstructorExpr, hasArgument(0, StrLitWithNul)), this); // Detect passing a suspicious string literal through an overloaded operator. Finder->addMatcher(cxxOperatorCallExpr(hasAnyArgument(StrLitWithNul)), this); }
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 EndCall = callExpr( callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))), hasArgument( 1, anyOf(cxxConstructExpr(has(ignoringImplicit( cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) .bind("end")))), anything()))) .bind("alg"); const auto DeclInStd = type(hasUnqualifiedDesugaredType( tagType(hasDeclaration(decl(isInStdNamespace()))))); Finder->addMatcher( cxxMemberCallExpr( on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), hasArgument(0, has(ignoringImplicit( anyOf(EndCall, has(ignoringImplicit(EndCall)))))), unless(isInTemplateInstantiation())) .bind("erase"), this); }
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 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 = cxxConstructExpr( 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( cxxMemberCallExpr(on(hasType(namedDecl(stlShrinkableContainer()))), callee(cxxMethodDecl(hasName("swap"))), has(memberExpr(hasDescendant(CopyCtorCall))), hasArgument(0, SwapParam.bind("ContainerToShrink")), unless(isInTemplateInstantiation())) .bind("CopyAndSwapTrick"), this); }
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); }
/// \brief Creates a matcher that finds the \c std::auto_ptr copy-ctor and /// assign-operator expressions. /// /// \c AutoPtrOwnershipTransferId is assigned to the argument of the expression, /// this is the part that has to be wrapped by \c std::move(). /// /// \code /// std::auto_ptr<int> i, j; /// i = j; /// ~~~~^ /// \endcode StatementMatcher makeTransferOwnershipExprMatcher() { return anyOf( cxxOperatorCallExpr(allOf(hasOverloadedOperatorName("="), callee(cxxMethodDecl(ofClass(AutoPtrDecl))), hasArgument(1, MovableArgumentMatcher))), cxxConstructExpr(allOf(hasType(AutoPtrType), argumentCountIs(1), hasArgument(0, MovableArgumentMatcher)))); }
void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) { auto PrivateSpecialFn = cxxMethodDecl( isPrivate(), anyOf(cxxConstructorDecl(anyOf(isDefaultConstructor(), isCopyConstructor(), isMoveConstructor())), cxxMethodDecl( anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())), cxxDestructorDecl())); Finder->addMatcher( cxxMethodDecl( PrivateSpecialFn, unless(anyOf(hasBody(stmt()), isDefaulted(), isDeleted(), ast_matchers::isTemplateInstantiation(), // Ensure that all methods except private special member // functions are defined. hasParent(cxxRecordDecl(hasMethod(unless( anyOf(PrivateSpecialFn, hasBody(stmt()), isPure(), isDefaulted(), isDeleted())))))))) .bind(SpecialFunction), this); Finder->addMatcher( cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic), this); }
void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) { // If we use ``[[nodiscard]]`` attribute, we require at least C++17. Use a // macro or ``__attribute__`` with pre c++17 compilers by using // ReplacementString option. if ((NoDiscardMacro == "[[nodiscard]]" && !getLangOpts().CPlusPlus17) || !getLangOpts().CPlusPlus) return; auto FunctionObj = cxxRecordDecl(hasAnyName("::std::function", "::boost::function")); // Find all non-void const methods which have not already been marked to // warn on unused result. Finder->addMatcher( cxxMethodDecl( allOf(isConst(), isDefinitionOrInline(), unless(anyOf( returns(voidType()), isNoReturn(), isOverloadedOperator(), isVariadic(), hasTemplateReturnType(), hasClassMutableFields(), isConversionOperator(), hasAttr(clang::attr::WarnUnusedResult), hasType(isInstantiationDependentType()), hasAnyParameter(anyOf( parmVarDecl(anyOf(hasType(FunctionObj), hasType(references(FunctionObj)))), hasType(isNonConstReferenceOrPointer()), hasParameterPack())))))) .bind("no_discard"), this); }
TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) { auto t = makeDecls<CXXMethodDecl>( "struct X { public: void foo(); };", "struct X { private: void foo(); };", Lang_CXX, cxxMethodDecl(hasName("foo"))); EXPECT_FALSE(testStructuralMatch(t)); }
TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) { auto t = makeDecls<CXXMethodDecl>( "struct X { void foo(); };", "struct X { virtual void foo(); };", Lang_CXX, cxxMethodDecl(hasName("foo"))); EXPECT_FALSE(testStructuralMatch(t)); }
void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()), varDecl(hasStaticStorageDuration()))), unless(isInTemplateInstantiation())) .bind("memberExpression"), this); }
void OverloadedUnaryAndCheck::registerMatchers( ast_matchers::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; // Match unary methods that overload operator&. Finder->addMatcher( cxxMethodDecl(parameterCountIs(0), hasOverloadedOperatorName("&")) .bind("overload"), this); // Also match freestanding unary operator& overloads. Be careful not to match // binary methods. Finder->addMatcher(functionDecl(unless(cxxMethodDecl()), parameterCountIs(1), hasOverloadedOperatorName("&")) .bind("overload"), this); }
void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( cxxRecordDecl( eachOf( has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")), has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())) .bind("copy-ctor")), has(cxxMethodDecl(isCopyAssignmentOperator(), unless(isImplicit())) .bind("copy-assign")), has(cxxConstructorDecl(isMoveConstructor(), unless(isImplicit())) .bind("move-ctor")), has(cxxMethodDecl(isMoveAssignmentOperator(), unless(isImplicit())) .bind("move-assign")))) .bind("class-def"), 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 VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( cxxMethodDecl( unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl(), isStatic(), isOverloadedOperator()))) .bind("method"), this); }
void NoexceptMoveConstructorCheck::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) return; Finder->addMatcher( cxxMethodDecl(anyOf(cxxConstructorDecl(), hasOverloadedOperatorName("=")), unless(isImplicit()), unless(isDeleted())) .bind("decl"), this); }
void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( cxxMemberCallExpr( callee(memberExpr(hasDescendant(implicitCastExpr( hasImplicitDestinationType(pointsTo( type(anything()).bind("castToType"))), hasSourceExpression(cxxThisExpr(hasType( type(anything()).bind("thisType"))))))) .bind("member")), callee(cxxMethodDecl(isVirtual()))), this); }
void ContainerSizeEmptyCheck::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 ValidContainer = cxxRecordDecl(isSameOrDerivedFrom( namedDecl( has(cxxMethodDecl( isConst(), parameterCountIs(0), isPublic(), hasName("size"), returns(qualType(isInteger(), unless(booleanType())))) .bind("size")), has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(), hasName("empty"), returns(booleanType())) .bind("empty"))) .bind("container"))); const auto WrongUse = anyOf( hasParent(binaryOperator( matchers::isComparisonOperator(), hasEitherOperand(ignoringImpCasts(anyOf( integerLiteral(equals(1)), integerLiteral(equals(0)))))) .bind("SizeBinaryOp")), hasParent(implicitCastExpr( hasImplicitDestinationType(booleanType()), anyOf( hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")), anything()))), hasParent(explicitCastExpr(hasDestinationType(booleanType())))); Finder->addMatcher( cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer), hasType(pointsTo(ValidContainer)), hasType(references(ValidContainer)))) .bind("STLObject")), callee(cxxMethodDecl(hasName("size"))), WrongUse) .bind("SizeCallExpr"), this); }
void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus || !getLangOpts().CXXExceptions) return; Finder->addMatcher( functionDecl(anyOf(isNoThrow(), cxxDestructorDecl(), cxxConstructorDecl(isMoveConstructor()), cxxMethodDecl(isMoveAssignmentOperator()), hasName("main"), hasName("swap"), isEnabled(FunctionsThatShouldNotThrow)), throws(unless(isIgnored(IgnoredExceptions)))) .bind("thrower"), this); }
void UniqueptrResetReleaseCheck::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) return; Finder->addMatcher( cxxMemberCallExpr( on(expr().bind("left")), callee(memberExpr().bind("reset_member")), callee( cxxMethodDecl(hasName("reset"), ofClass(cxxRecordDecl(hasName("::std::unique_ptr"), decl().bind("left_class"))))), has(ignoringParenImpCasts(cxxMemberCallExpr( on(expr().bind("right")), callee(memberExpr().bind("release_member")), callee(cxxMethodDecl( hasName("release"), ofClass(cxxRecordDecl(hasName("::std::unique_ptr"), decl().bind("right_class"))))))))) .bind("reset_call"), this); }
void ReplaceAutoPtrCheck::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; auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isFromStdNamespace()); auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl)); // std::auto_ptr<int> a; // ^~~~~~~~~~~~~ // // typedef std::auto_ptr<int> int_ptr_t; // ^~~~~~~~~~~~~ // // std::auto_ptr<int> fn(std::auto_ptr<int>); // ^~~~~~~~~~~~~ ^~~~~~~~~~~~~ Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType, // Skip elaboratedType() as the named // type will match soon thereafter. unless(elaboratedType())))) .bind(AutoPtrTokenId), this); // using std::auto_ptr; // ^~~~~~~~~~~~~~~~~~~ Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(allOf( hasName("auto_ptr"), isFromStdNamespace())))) .bind(AutoPtrTokenId), this); // Find ownership transfers via copy construction and assignment. // AutoPtrOwnershipTransferId is bound to the the part that has to be wrapped // into std::move(). // std::auto_ptr<int> i, j; // i = j; // ~~~~^ auto MovableArgumentMatcher = expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId); Finder->addMatcher( cxxOperatorCallExpr(hasOverloadedOperatorName("="), callee(cxxMethodDecl(ofClass(AutoPtrDecl))), hasArgument(1, MovableArgumentMatcher)), this); Finder->addMatcher(cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1), hasArgument(0, MovableArgumentMatcher)), this); }
void UnconventionalAssignOperatorCheck::registerMatchers( ast_matchers::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 HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType( pointee(unless(isConstQualified()), anyOf(autoType(), hasDeclaration(equalsBoundNode("class"))))))); const auto IsSelf = qualType( anyOf(hasDeclaration(equalsBoundNode("class")), referenceType(pointee(hasDeclaration(equalsBoundNode("class")))))); const auto IsAssign = cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())), hasName("operator="), ofClass(recordDecl().bind("class"))) .bind("method"); const auto IsSelfAssign = cxxMethodDecl(IsAssign, hasParameter(0, parmVarDecl(hasType(IsSelf)))) .bind("method"); Finder->addMatcher( cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"), this); const auto BadSelf = referenceType( anyOf(lValueReferenceType(pointee(unless(isConstQualified()))), rValueReferenceType(pointee(isConstQualified())))); Finder->addMatcher( cxxMethodDecl(IsSelfAssign, hasParameter(0, parmVarDecl(hasType(BadSelf)))) .bind("ArgumentType"), this); Finder->addMatcher( cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"), this); const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts( anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())), cxxOperatorCallExpr(argumentCountIs(1), callee(unresolvedLookupExpr()), hasArgument(0, cxxThisExpr()))))))); const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType); Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign)) .bind("returnStmt"), this); }
void SlicingCheck::registerMatchers(MatchFinder *Finder) { // When we see: // class B : public A { ... }; // A a; // B b; // a = b; // The assignment is OK if: // - the assignment operator is defined as taking a B as second parameter, // or // - B does not define any additional members (either variables or // overrides) wrt A. // // The same holds for copy ctor calls. This also captures stuff like: // void f(A a); // f(b); // Helpers. const auto OfBaseClass = ofClass(cxxRecordDecl().bind("BaseDecl")); const auto IsDerivedFromBaseDecl = cxxRecordDecl(isDerivedFrom(equalsBoundNode("BaseDecl"))) .bind("DerivedDecl"); const auto HasTypeDerivedFromBaseDecl = anyOf(hasType(IsDerivedFromBaseDecl), hasType(references(IsDerivedFromBaseDecl))); const auto IsWithinDerivedCtor = hasParent(cxxConstructorDecl(ofClass(equalsBoundNode("DerivedDecl")))); // Assignement slicing: "a = b;" and "a = std::move(b);" variants. const auto SlicesObjectInAssignment = callExpr(callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator()), OfBaseClass)), hasArgument(1, HasTypeDerivedFromBaseDecl)); // Construction slicing: "A a{b};" and "f(b);" variants. Note that in case of // slicing the letter will create a temporary and therefore call a ctor. const auto SlicesObjectInCtor = cxxConstructExpr( hasDeclaration(cxxConstructorDecl( anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)), hasArgument(0, HasTypeDerivedFromBaseDecl), // We need to disable matching on the call to the base copy/move // constructor in DerivedDecl's constructors. unless(IsWithinDerivedCtor)); Finder->addMatcher( expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"), this); }
void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( cxxOperatorCallExpr( anyOf(hasOverloadedOperatorName("="), hasOverloadedOperatorName("+=")), callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl( hasName("::std::basic_string"), hasTemplateArgument(0, refersToType(qualType().bind("type"))))))), hasArgument(1, ignoringImpCasts(expr(hasType(isInteger()), unless(hasType(isAnyCharacter()))) .bind("expr"))), unless(isInTemplateInstantiation())), 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); }
void AvoidConstParamsInDecls::registerMatchers(MatchFinder *Finder) { const auto ConstParamDecl = parmVarDecl(hasType(qualType(isConstQualified()))).bind("param"); Finder->addMatcher( functionDecl(unless(isDefinition()), // Lambdas are always their own definition, but they // generate a non-definition FunctionDecl too. Ignore those. // Class template instantiations have a non-definition // CXXMethodDecl for methods that aren't used in this // translation unit. Ignore those, as the template will have // already been checked. unless(cxxMethodDecl(ofClass(cxxRecordDecl(anyOf( isLambda(), ast_matchers::isTemplateInstantiation()))))), has(typeLoc(forEach(ConstParamDecl)))) .bind("func"), this); }
void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) { auto IsSusbstituted = qualType(anyOf( substTemplateTypeParmType(), hasDescendant(substTemplateTypeParmType()))); auto UniquePtrWithDefaultDelete = classTemplateSpecializationDecl( hasName("std::unique_ptr"), hasTemplateArgument(1, refersToType(qualType(hasDeclaration(cxxRecordDecl( hasName("std::default_delete"))))))); Finder->addMatcher( cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr( on(expr(hasType(UniquePtrWithDefaultDelete), unless(hasType(IsSusbstituted))) .bind("uptr")), callee(cxxMethodDecl(hasName("release"))))))) .bind("delete"), 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); }
void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; // Match all operator new and operator delete overloads (including the array // forms). Do not match implicit operators, placement operators, or // deleted/private operators. // // Technically, trivially-defined operator delete seems like a reasonable // thing to also skip. e.g., void operator delete(void *) {} // However, I think it's more reasonable to warn in this case as the user // should really be writing that as a deleted function. Finder->addMatcher( functionDecl(unless(anyOf(isImplicit(), isPlacementOverload(), isDeleted(), cxxMethodDecl(isPrivate()))), anyOf(hasOverloadedOperatorName("new"), hasOverloadedOperatorName("new[]"), hasOverloadedOperatorName("delete"), hasOverloadedOperatorName("delete[]"))) .bind("func"), this); }
void UseOverrideCheck::registerMatchers(MatchFinder *Finder) { // Only register the matcher for C++11. if (getLangOpts().CPlusPlus11) Finder->addMatcher(cxxMethodDecl(isOverride()).bind("method"), this); }