void MemsetZeroLengthCheck::registerMatchers( ast_matchers::MatchFinder *Finder) { // Look for memset(x, y, 0) as those is most likely an argument swap. // TODO: Also handle other standard functions that suffer from the same // problem, e.g. memchr. Finder->addMatcher(callExpr(callee(functionDecl(hasName("::memset"))), argumentCountIs(3), unless(isInTemplateInstantiation())) .bind("decl"), this); }
void AvoidBindCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus14) // Need C++14 for generic lambdas. return; Finder->addMatcher( callExpr( callee(namedDecl(hasName("::std::bind"))), hasArgument(0, declRefExpr(to(functionDecl().bind("f"))).bind("ref"))) .bind("bind"), this); }
TEST_F(StructuralEquivalenceRecordTest, RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) { auto t = makeTuDecls( R"( struct X { struct { int a; }; struct { int b; }; }; )", R"( struct X { // The order is reversed. struct { int b; }; struct { int a; }; }; )", Lang_C); auto *TU = get<0>(t); auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( TU, indirectFieldDecl(hasName("a"))); auto *FA = cast<FieldDecl>(A->chain().front()); RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); auto *TU1 = get<1>(t); auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match( TU1, indirectFieldDecl(hasName("a"))); auto *FA1 = cast<FieldDecl>(A1->chain().front()); RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl(); RecordDecl *X = FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X"))); RecordDecl *X1 = FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X"))); ASSERT_NE(X, X1); EXPECT_FALSE(testStructuralMatch(X, X1)); ASSERT_NE(RA, RA1); EXPECT_TRUE(testStructuralMatch(RA, RA)); EXPECT_TRUE(testStructuralMatch(RA1, RA1)); EXPECT_FALSE(testStructuralMatch(RA1, RA)); }
Layout* Layout::addName(Name name, int expectedSlot) { assert(!hasName(name)); Layout* layout = children_.get(name); if (!layout) { Stack<Layout*> self(this); layout = gc.create<Layout>(self, name); } assert(expectedSlot == -1 || expectedSlot == layout->slotIndex()); return layout; }
/** Initializes attributes. * * @throw NodeException if not given a name. */ Branch::Branch(const Tag &tag) : Node(tag), Nameable(tag) { // Follow follow = true; // Name if (!hasName()) { NodeException e(getTag()); e << "[Branch] Must have a name."; throw e; } }
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 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( memberCallExpr( on(expr().bind("left")), callee(memberExpr().bind("reset_member")), callee(methodDecl(hasName("reset"), ofClass(recordDecl(hasName("::std::unique_ptr"), decl().bind("left_class"))))), has(memberCallExpr( on(expr().bind("right")), callee(memberExpr().bind("release_member")), callee(methodDecl( hasName("release"), ofClass(recordDecl(hasName("::std::unique_ptr"), decl().bind("right_class")))))))) .bind("reset_call"), this); }
/// If `Node` is a call to the inverse of `Scale`, return that inverse's /// argument, otherwise None. static llvm::Optional<std::string> rewriteInverseTimeCall(const MatchFinder::MatchResult &Result, DurationScale Scale, const Expr &Node) { llvm::StringRef InverseFunction = getTimeInverseForScale(Scale); if (const auto *MaybeCallArg = selectFirst<const Expr>( "e", match(callExpr(callee(functionDecl(hasName(InverseFunction))), hasArgument(0, expr().bind("e"))), Node, *Result.Context))) { return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str(); } return llvm::None; }
void SkyObject::setLongName( const QString &longname ) { delete LongName; if ( longname.isEmpty() ) { if ( hasName() ) LongName = new QString(translatedName()); else if ( hasName2() ) LongName = new QString(*Name2); else LongName = 0; } else { LongName = new QString(longname); } }
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 UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus11) return; // FIXME: Bunch of functionality that could be easily added: // + add handling of `push_front` for std::forward_list, std::list // and std::deque. // + add handling of `push` for std::stack, std::queue, std::priority_queue // + add handling of `insert` for stl associative container, but be careful // because this requires special treatment (it could cause performance // regression) // + match for emplace calls that should be replaced with insertion // + match for make_pair calls. auto callPushBack = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_back"))), on(hasType(cxxRecordDecl(hasAnyName("std::vector", "llvm::SmallVector", "std::list", "std::deque"))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of // passed pointer because smart pointer won't be constructed // (and destructed) as in push_back case. auto isCtorOfSmartPtr = hasDeclaration(cxxConstructorDecl( ofClass(hasAnyName("std::shared_ptr", "std::unique_ptr", "std::auto_ptr", "std::weak_ptr")))); // Bitfields binds only to consts and emplace_back take it by universal ref. auto bitFieldAsArgument = hasAnyArgument(ignoringParenImpCasts( memberExpr(hasDeclaration(fieldDecl(matchers::isBitfield()))))); // We could have leak of resource. auto newExprAsArgument = hasAnyArgument(ignoringParenImpCasts(cxxNewExpr())); auto constructingDerived = hasParent(implicitCastExpr(hasCastKind(CastKind::CK_DerivedToBase))); auto hasInitList = has(ignoringParenImpCasts(initListExpr())); auto soughtConstructExpr = cxxConstructExpr( unless(anyOf(isCtorOfSmartPtr, hasInitList, bitFieldAsArgument, newExprAsArgument, constructingDerived, has(materializeTemporaryExpr(hasInitList))))) .bind("ctor"); auto hasConstructExpr = has(ignoringParenImpCasts(soughtConstructExpr)); auto ctorAsArgument = materializeTemporaryExpr( anyOf(hasConstructExpr, has(cxxFunctionalCastExpr(hasConstructExpr)))); Finder->addMatcher( cxxMemberCallExpr(callPushBack, has(ctorAsArgument)).bind("call"), this); }
void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType( hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom( hasName("std::exception")))))))))), has(expr(unless(cxxUnresolvedConstructExpr()))), eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))) .bind("bad_throw"), this); }
void StarObject::setNames( QString name, QString name2 ) { QString lname; setName( name ); setName2( name2 ); if ( hasName() ) { lname = name; if ( hasName2() ) lname += " (" + gname() + ')'; } else if ( hasName2() ) lname = gname(); setLongName(lname); }
void Expression::apply(const std::string& name, const float& value) { if (!hasName(name)) { return; } float var_value = getValue(name); termList_.erase(std::remove_if(termList_.begin(), termList_.end(), [name](const std::unique_ptr<Term>& term){ return term->hasName(name); }), termList_.end()); if (var_value != 0.0f) { add(Constant(var_value * 1.0f * value)); } }
/** Initializes the @e link and @e name attributes. */ Target::Target(const Tag &tag) : Attachment(tag) { tag.get("link", link, true, false); // Check name if (!hasName()) setName(link); // Check type if (getType() != "color") { NodeException e(getTag()); e << "[Target] Type must be color."; throw e; } }
void Identification::onCreate(uint64_t id){ Identifier* identifier = _engine.manager.getComponent<Identifier>(id); // If name, add to name name if (identifier->name != "" && !hasName(identifier->name)){ _names[identifier->name] = id; identifier->validName = true; } // If layer, add to layer map if (identifier->layer != ""){ assert(_layers[identifier->layer].find(id) == _layers[identifier->layer].end()); _layers[identifier->layer].insert(id); } }
void Expression::simplify(const std::string& name) { float name_value = 0.0f; if (!hasName(name)) { return; } name_value += getValue(name); termList_.erase(std::remove_if(termList_.begin(), termList_.end(), [name](const std::unique_ptr<Term>& term){ return term->hasName(name); }), termList_.end()); if(name_value != 0.0f) { add(Variable(name_value, name)); } }
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 ExplicitMakePairCheck::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; // Look for std::make_pair with explicit template args. Ignore calls in // templates. Finder->addMatcher( callExpr(unless(isInTemplateInstantiation()), callee(expr(ignoringParenImpCasts( declRefExpr(hasExplicitTemplateArgs(), to(functionDecl(hasName("::std::make_pair")))) .bind("declref"))))).bind("call"), this); }
void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; auto MoveCallMatcher = callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1), unless(isInTemplateInstantiation())) .bind("call-move"); Finder->addMatcher(MoveCallMatcher, this); auto ConstParamMatcher = forEachArgumentWithParam( MoveCallMatcher, parmVarDecl(hasType(references(isConstQualified())))); Finder->addMatcher(callExpr(ConstParamMatcher).bind("receiving-expr"), this); Finder->addMatcher(cxxConstructExpr(ConstParamMatcher).bind("receiving-expr"), this); }
void ProperlySeededRandomGeneratorCheck::registerMatchers(MatchFinder *Finder) { auto RandomGeneratorEngineDecl = cxxRecordDecl(hasAnyName( "::std::linear_congruential_engine", "::std::mersenne_twister_engine", "::std::subtract_with_carry_engine", "::std::discard_block_engine", "::std::independent_bits_engine", "::std::shuffle_order_engine")); auto RandomGeneratorEngineTypeMatcher = hasType(hasUnqualifiedDesugaredType( recordType(hasDeclaration(RandomGeneratorEngineDecl)))); // std::mt19937 engine; // engine.seed(); // ^ // engine.seed(1); // ^ // const int x = 1; // engine.seed(x); // ^ Finder->addMatcher( cxxMemberCallExpr( has(memberExpr(has(declRefExpr(RandomGeneratorEngineTypeMatcher)), member(hasName("seed")), unless(hasDescendant(cxxThisExpr()))))) .bind("seed"), this); // std::mt19937 engine; // ^ // std::mt19937 engine(1); // ^ // const int x = 1; // std::mt19937 engine(x); // ^ Finder->addMatcher( cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor"), this); // srand(); // ^ // const int x = 1; // srand(x); // ^ Finder->addMatcher( callExpr(callee(functionDecl(hasAnyName("::srand", "::std::srand")))) .bind("srand"), this); }
void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher(arraySubscriptExpr(hasBase(ignoringImpCasts(hasType( constantArrayType().bind("type")))), hasIndex(expr().bind("index"))) .bind("expr"), this); Finder->addMatcher( cxxOperatorCallExpr( hasOverloadedOperatorName("[]"), hasArgument( 0, hasType(cxxRecordDecl(hasName("::std::array")).bind("type"))), hasArgument(1, expr().bind("index"))) .bind("expr"), this); }
std::wstring VKRecord::getName() const { if (! hasName()) { return VKRecord::DEFAULT_VALUE_NAME; } uint32_t nameLength = getWord(NAME_LENGTH_OFFSET); if (nameLength > MAX_NAME_LENGTH) { throw RegistryParseException("Value name length exceeds maximum length."); } if (hasAsciiName()) { // TODO: This is a little hacky but it should work fine // for ASCII strings. std::vector<uint8_t> name = getData(NAME_OFFSET_OFFSET, nameLength); return std::wstring(name.begin(), name.end()); } return getUTF16String(NAME_OFFSET_OFFSET, nameLength); }
std::string avro2sql_table_name(boost::shared_ptr<avro::ValidSchema> schema, avro::GenericDatum& datum) { auto r = schema->root(); assert(r->type() == avro::AVRO_RECORD); if (r->hasName()) { std::string name = r->name(); //since we use convention tablename.key / table_name.value (until we know what bottledwater does...) // return namesapace as table name std::size_t found = name.find_first_of("."); if (found != std::string::npos) { std::string ns = name.substr(0, found); return ns; } return r->name(); } assert(false); return "unknown_table_name"; }
void InefficientStringConcatenationCheck::registerMatchers( MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; const auto BasicStringType = hasType(qualType(hasUnqualifiedDesugaredType(recordType( hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"))))))); const auto BasicStringPlusOperator = cxxOperatorCallExpr( hasOverloadedOperatorName("+"), hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType)))); const auto PlusOperator = cxxOperatorCallExpr( hasOverloadedOperatorName("+"), hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))), hasDescendant(BasicStringPlusOperator)) .bind("plusOperator"); const auto AssignOperator = cxxOperatorCallExpr( hasOverloadedOperatorName("="), hasArgument(0, declRefExpr(BasicStringType, hasDeclaration(decl().bind("lhsStrT"))) .bind("lhsStr")), hasArgument(1, stmt(hasDescendant(declRefExpr( hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))), hasDescendant(BasicStringPlusOperator)); if (StrictMode) { Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)), this); } else { Finder->addMatcher( cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator), hasAncestor(stmt(anyOf(cxxForRangeStmt(), whileStmt(), forStmt())))), this); } }
TEST_F(StructuralEquivalenceRecordTest, Match) { auto Code = R"( struct A{ }; struct B{ }; struct foo: A, virtual B { void x(); int a; }; )"; auto t = makeNamedDecls(Code, Code, Lang_CXX); EXPECT_TRUE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) { auto t = makeTuDecls( R"( struct A { struct { struct A *next; } entry0; struct { struct A *next; } entry1; }; )", "", Lang_C); auto *TU = get<0>(t); auto *Entry0 = FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0"))); auto *Entry1 = FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1"))); auto *R0 = getRecordDecl(Entry0); auto *R1 = getRecordDecl(Entry1); ASSERT_NE(R0, R1); EXPECT_TRUE(testStructuralMatch(R0, R0)); EXPECT_TRUE(testStructuralMatch(R1, R1)); EXPECT_FALSE(testStructuralMatch(R0, R1)); }
void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus11) return; // FIXME: Bunch of functionality that could be easily added: // + add handling of `push_front` for std::forward_list, std::list // and std::deque. // + add handling of `push` for std::stack, std::queue, std::priority_queue // + add handling of `insert` for stl associative container, but be careful // because this requires special treatment (it could cause performance // regression) // + match for emplace calls that should be replaced with insertion // + match for make_pair calls. auto callPushBack = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_back"))), on(hasType(cxxRecordDecl(hasAnyName(SmallVector<StringRef, 5>( ContainersWithPushBack.begin(), ContainersWithPushBack.end())))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of // passed pointer because smart pointer won't be constructed // (and destructed) as in push_back case. auto isCtorOfSmartPtr = hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName( SmallVector<StringRef, 5>(SmartPointers.begin(), SmartPointers.end()))))); // Bitfields binds only to consts and emplace_back take it by universal ref. auto bitFieldAsArgument = hasAnyArgument( ignoringImplicit(memberExpr(hasDeclaration(fieldDecl(isBitField()))))); // Initializer list can't be passed to universal reference. auto initializerListAsArgument = hasAnyArgument( ignoringImplicit(cxxConstructExpr(isListInitialization()))); // We could have leak of resource. auto newExprAsArgument = hasAnyArgument(ignoringImplicit(cxxNewExpr())); // We would call another constructor. auto constructingDerived = hasParent(implicitCastExpr(hasCastKind(CastKind::CK_DerivedToBase))); // emplace_back can't access private constructor. auto isPrivateCtor = hasDeclaration(cxxConstructorDecl(isPrivate())); auto hasInitList = has(ignoringImplicit(initListExpr())); // FIXME: Discard 0/NULL (as nullptr), static inline const data members, // overloaded functions and template names. auto soughtConstructExpr = cxxConstructExpr( unless(anyOf(isCtorOfSmartPtr, hasInitList, bitFieldAsArgument, initializerListAsArgument, newExprAsArgument, constructingDerived, isPrivateCtor))) .bind("ctor"); auto hasConstructExpr = has(ignoringImplicit(soughtConstructExpr)); auto ctorAsArgument = materializeTemporaryExpr( anyOf(hasConstructExpr, has(cxxFunctionalCastExpr(hasConstructExpr)))); Finder->addMatcher(cxxMemberCallExpr(callPushBack, has(ctorAsArgument), unless(isInTemplateInstantiation())) .bind("call"), this); }
const std::string& DataTypeInformation::getName() const { assert::that(hasName()); return _name; }
#include "ASTUtility.h" //StatementMatcher callExprMatcher = callExpr().bind("callexpr"); StatementMatcher mallocMatcher = callExpr(callee(functionDecl(hasName("malloc")).bind("m"))).bind("mallocCall"); StatementMatcher freeMatcher = callExpr(callee(functionDecl(hasName("free")).bind("f"))).bind("freeCall"); StatementMatcher reallocMatcher = callExpr(callee(functionDecl(hasName("realloc")).bind("r"))).bind("reallocCall"); //memcpy arrayType non-builtin = pointer or user-defined StatementMatcher memcpyAryMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cpyParm"))))))) ).bind("memcpyCall"); StatementMatcher memcpyPtrMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(pointerType( pointee(unless(builtinType()))).bind("cpyParmPtr"))))))) ).bind("memcpyCall"); StatementMatcher memcmpAryMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cmpParm"))))))) ).bind("memcmpCall"); StatementMatcher memcmpPtrMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr(