I hope to match all for-loop with vector declaring in it's body (might extend to while-loop and do-while-loop later):
#include <vector>
int main() {
for (int i = 0; i < 10; i++) {
std::vector<int> foo;
}
return 0;
}
The AST I got from this program is
`-FunctionDecl 0x55c1d33c8bc8 <main.cpp:3:1, line:9:1> line:3:5 main 'int ()'
`-CompoundStmt 0x55c1d3402a48 <col:12, line:9:1>
|-ForStmt 0x55c1d34029e0 <line:4:3, line:6:3>
| |-DeclStmt 0x55c1d33c8d40 <line:4:8, col:17>
| | `-VarDecl 0x55c1d33c8cb8 <col:8, col:16> col:12 used i 'int' cinit
| | `-IntegerLiteral 0x55c1d33c8d20 <col:16> 'int' 0
| |-<<<NULL>>>
| |-BinaryOperator 0x55c1d33c8db0 <col:19, col:23> 'bool' '<'
| | |-ImplicitCastExpr 0x55c1d33c8d98 <col:19> 'int' <LValueToRValue>
| | | `-DeclRefExpr 0x55c1d33c8d58 <col:19> 'int' lvalue Var 0x55c1d33c8cb8 'i' 'int'
| | `-IntegerLiteral 0x55c1d33c8d78 <col:23> 'int' 10
| |-UnaryOperator 0x55c1d33c8df0 <col:27, col:28> 'int' postfix '++'
| | `-DeclRefExpr 0x55c1d33c8dd0 <col:27> 'int' lvalue Var 0x55c1d33c8cb8 'i' 'int'
| `-CompoundStmt 0x55c1d34029c8 <col:32, line:6:3>
| `-DeclStmt 0x55c1d34029b0 <line:5:5, col:25>
| `-VarDecl 0x55c1d33cd388 <col:5, col:22> col:22 foo 'std::vector<int>' callinit destroyed
| `-CXXConstructExpr 0x55c1d3402988 <col:22> 'std::vector<int>' 'void () noexcept'
`-ReturnStmt 0x55c1d3402a38 <line:8:3, col:10>
`-IntegerLiteral 0x55c1d3402a18 <col:10> 'int' 0
Now how do I write a matcher (in clang-tidy customized check) to match such pattern?
I read the document for customizing clang-tidy checks and Matching the Clang AST, but they don't seem to provide enough information on how I should actually combine each APIs.
update: with @Scott McPeak's answer, I can match the for loop with clang-query in terminal but I have trouble transplanting this matcher into my clang-tidy check:
void LowPerfLoopCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
forStmt(hasDescendant(varDecl(hasType(hasDeclaration(cxxRecordDecl(
matchesName("^::std::vector$")))))
.bind("vector-in-for"))),
this);
}
When building clang-tidy, it says call of overloaded 'hasType()' is ambiguous
:
llvm-project/clang-tools-extra/clang-tidy/misc/LowPerfLoopCheck.cpp: In member function ‘virtual void clang::tidy::misc::LowPerfLoopCheck::registerMatchers(clang::ast_matchers::MatchFinder*)’:
/home/wentao/Desktop/llvm-project/clang-tools-extra/clang-tidy/misc/LowPerfLoopCheck.cpp:19:44: error: call of overloaded ‘hasType(clang::ast_matchers::internal::PolymorphicMatcher<clang::ast_matchers::internal::HasDeclarationMatcher, void(clang::ast_matchers::internal::TypeList<clang::CallExpr, clang::CXXConstructExpr, clang::CXXNewExpr, clang::DeclRefExpr, clang::EnumType, clang::ElaboratedType, clang::InjectedClassNameType, clang::LabelStmt, clang::AddrLabelExpr, clang::MemberExpr, clang::QualType, clang::RecordType, clang::TagType, clang::TemplateSpecializationType, clang::TemplateTypeParmType, clang::TypedefType, clang::UnresolvedUsingType, clang::ObjCIvarRefExpr>), clang::ast_matchers::internal::Matcher<clang::Decl> >)’ is ambiguous
19 | forStmt(hasDescendant(varDecl(hasType(hasDeclaration(cxxRecordDecl(
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 | matchesName("^::std::vector$")))))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Why does the same code works for clang-query but not for clang-tidy checks?