MakeSharedCheck::SmartPtrTypeMatcher MakeSharedCheck::getSmartPointerTypeMatcher() const { return qualType(hasDeclaration(classTemplateSpecializationDecl( matchesName("::std::shared_ptr"), templateArgumentCountIs(1), hasTemplateArgument( 0, templateArgument(refersToType(qualType().bind(PointerType))))))); }
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 UseToStringCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( callExpr( hasDeclaration(functionDecl( returns(hasDeclaration(classTemplateSpecializationDecl( hasName("std::basic_string"), hasTemplateArgument(0, templateArgument().bind("char_type"))))), hasName("boost::lexical_cast"), hasParameter(0, hasType(qualType(has(substTemplateTypeParmType( isStrictlyInteger()))))))), argumentCountIs(1), unless(isInTemplateInstantiation())) .bind("to_string"), 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 UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; // For the arithmetic calls, we match only the uses of the templated operators // where the template parameter is not a built-in type. This means the // instantiation makes use of an available user defined conversion to // `int64_t`. // // The implementation of these templates will be updated to fail SFINAE for // non-integral types. We match them to suggest an explicit cast. // Match expressions like `a *= b` and `a /= b` where `a` has type // `absl::Duration` and `b` is not of a built-in type. Finder->addMatcher( cxxOperatorCallExpr( argumentCountIs(2), hasArgument( 0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))), hasArgument(1, expr().bind("arg")), callee(functionDecl( hasParent(functionTemplateDecl()), unless(hasTemplateArgument(0, refersToType(builtinType()))), hasAnyName("operator*=", "operator/=")))), this); // Match expressions like `a.operator*=(b)` and `a.operator/=(b)` where `a` // has type `absl::Duration` and `b` is not of a built-in type. Finder->addMatcher( cxxMemberCallExpr( callee(cxxMethodDecl( ofClass(cxxRecordDecl(hasName("::absl::Duration"))), hasParent(functionTemplateDecl()), unless(hasTemplateArgument(0, refersToType(builtinType()))), hasAnyName("operator*=", "operator/="))), argumentCountIs(1), hasArgument(0, expr().bind("arg"))), this); // Match expressions like `a * b`, `a / b`, `operator*(a, b)`, and // `operator/(a, b)` where `a` has type `absl::Duration` and `b` is not of a // built-in type. Finder->addMatcher( callExpr(callee(functionDecl( hasParent(functionTemplateDecl()), unless(hasTemplateArgument(0, refersToType(builtinType()))), hasAnyName("::absl::operator*", "::absl::operator/"))), argumentCountIs(2), hasArgument(0, expr(hasType( cxxRecordDecl(hasName("::absl::Duration"))))), hasArgument(1, expr().bind("arg"))), this); // Match expressions like `a * b` and `operator*(a, b)` where `a` is not of a // built-in type and `b` has type `absl::Duration`. Finder->addMatcher( callExpr(callee(functionDecl( hasParent(functionTemplateDecl()), unless(hasTemplateArgument(0, refersToType(builtinType()))), hasName("::absl::operator*"))), argumentCountIs(2), hasArgument(0, expr().bind("arg")), hasArgument(1, expr(hasType(cxxRecordDecl( hasName("::absl::Duration")))))), this); // For the factory functions, we match only the non-templated overloads that // take an `int64_t` parameter. Within these calls, we care about implicit // casts through a user defined conversion to `int64_t`. // // The factory functions will be updated to be templated and SFINAE on whether // the template parameter is an integral type. This complements the already // existing templated overloads that only accept floating point types. // Match calls like: // `absl::Nanoseconds(x)` // `absl::Microseconds(x)` // `absl::Milliseconds(x)` // `absl::Seconds(x)` // `absl::Minutes(x)` // `absl::Hours(x)` // where `x` is not of a built-in type. Finder->addMatcher( implicitCastExpr( anyOf(hasCastKind(CK_UserDefinedConversion), has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))), hasParent(callExpr( callee(functionDecl(DurationFactoryFunction(), unless(hasParent(functionTemplateDecl())))), hasArgument(0, expr().bind("arg"))))), this); }