使用 AST 匹配器匹配可变模板参数
Matching variadic template arguments using an AST Matcher
我有以下示例代码。
template<class T, class... Args>
T add(T first, Args... rest) {
return first + add(rest...);
}
int add(int a, int b) {
return a + b;
}
当我 运行 通过 clang-check -ast-dump
时,我得到以下树。
FunctionDecl 0x4df0b08 <tmp.cpp:2:1, line:4:1> line:2:3 add 'T (T, Args...)'
|-ParmVarDecl 0x4df0928 <col:7, col:9> col:9 referenced first 'T'
|-ParmVarDecl 0x4df09f8 <col:16, col:24> col:24 referenced rest 'Args...' pack
`-CompoundStmt 0x4df0dd0 <col:30, line:4:1>
`-ReturnStmt 0x4df0dc0 <line:3:5, col:31>
`-BinaryOperator 0x4df0da0 <col:12, col:31> '<dependent type>' '+'
|-DeclRefExpr 0x4df0cd0 <col:12> 'T' lvalue ParmVar 0x4df0928 'first' 'T'
`-CallExpr 0x4df0d78 <col:20, col:31> '<dependent type>'
|-UnresolvedLookupExpr 0x4df0cf0 <col:20> '<overloaded function type>' lvalue (ADL) = 'add' 0x4df0ba8
`-PackExpansionExpr 0x4df0d58 <col:24, col:28> '<dependent type>' lvalue
`-DeclRefExpr 0x4df0d38 <col:24> 'Args' lvalue ParmVar 0x4df09f8 'rest' 'Args...'
FunctionDecl 0x4df0f60 <tmp.cpp:6:1, line:8:1> line:6:5 add 'int (int, int)'
|-ParmVarDecl 0x4df0e00 <col:9, col:13> col:13 used a 'int'
|-ParmVarDecl 0x4df0e80 <col:16, col:20> col:20 used b 'int'
`-CompoundStmt 0x4df10b0 <col:23, line:8:1>
`-ReturnStmt 0x4df10a0 <line:7:5, col:16>
`-BinaryOperator 0x4df1080 <col:12, col:16> 'int' '+'
|-DeclRefExpr 0x4df1010 <col:12> 'int' lvalue ParmVar 0x4df0e00 'a' 'int'
`-DeclRefExpr 0x4df1030 <col:16> 'int' lvalue ParmVar 0x4df0e80 'b' 'int'
我想为第一种情况编写一个匹配器,其中函数的一个参数是可变的。来自 AST Matcher Reference, I have found that there is a isVariadic 匹配器,尽管如文档所述,
Example matches f, but not g or h. The function i will not match, even when
compiled in C mode.
void f(...);
void g(int);
template <typename... Ts> void h(Ts...);
void i();
有什么方法可以匹配可变参数函数声明,并将可变参数声明进一步绑定到某个节点?我想做类似 functionDecl(has(parmVarDecl(hasType(packExpansionType().bind("parameter_type")))))
的事情,但似乎这是不可能的,因为没有 packExpansionType
匹配器。我在这里遗漏了什么吗?
为了将来参考,我找到了解决这个问题的方法。实际上可以在检查中定义自定义匹配器。
namespace {
const AstTypeMatcher<PackExpansionType> packExpansionType;
const internal::VariadicDynCastAllOfMatcher<Stmt, PackExpansionExpr> packExpansionExpr;
}
// You can also use the macros from ASTMatchersMacros.h
...
我有以下示例代码。
template<class T, class... Args>
T add(T first, Args... rest) {
return first + add(rest...);
}
int add(int a, int b) {
return a + b;
}
当我 运行 通过 clang-check -ast-dump
时,我得到以下树。
FunctionDecl 0x4df0b08 <tmp.cpp:2:1, line:4:1> line:2:3 add 'T (T, Args...)'
|-ParmVarDecl 0x4df0928 <col:7, col:9> col:9 referenced first 'T'
|-ParmVarDecl 0x4df09f8 <col:16, col:24> col:24 referenced rest 'Args...' pack
`-CompoundStmt 0x4df0dd0 <col:30, line:4:1>
`-ReturnStmt 0x4df0dc0 <line:3:5, col:31>
`-BinaryOperator 0x4df0da0 <col:12, col:31> '<dependent type>' '+'
|-DeclRefExpr 0x4df0cd0 <col:12> 'T' lvalue ParmVar 0x4df0928 'first' 'T'
`-CallExpr 0x4df0d78 <col:20, col:31> '<dependent type>'
|-UnresolvedLookupExpr 0x4df0cf0 <col:20> '<overloaded function type>' lvalue (ADL) = 'add' 0x4df0ba8
`-PackExpansionExpr 0x4df0d58 <col:24, col:28> '<dependent type>' lvalue
`-DeclRefExpr 0x4df0d38 <col:24> 'Args' lvalue ParmVar 0x4df09f8 'rest' 'Args...'
FunctionDecl 0x4df0f60 <tmp.cpp:6:1, line:8:1> line:6:5 add 'int (int, int)'
|-ParmVarDecl 0x4df0e00 <col:9, col:13> col:13 used a 'int'
|-ParmVarDecl 0x4df0e80 <col:16, col:20> col:20 used b 'int'
`-CompoundStmt 0x4df10b0 <col:23, line:8:1>
`-ReturnStmt 0x4df10a0 <line:7:5, col:16>
`-BinaryOperator 0x4df1080 <col:12, col:16> 'int' '+'
|-DeclRefExpr 0x4df1010 <col:12> 'int' lvalue ParmVar 0x4df0e00 'a' 'int'
`-DeclRefExpr 0x4df1030 <col:16> 'int' lvalue ParmVar 0x4df0e80 'b' 'int'
我想为第一种情况编写一个匹配器,其中函数的一个参数是可变的。来自 AST Matcher Reference, I have found that there is a isVariadic 匹配器,尽管如文档所述,
Example matches f, but not g or h. The function i will not match, even when
compiled in C mode.
void f(...);
void g(int);
template <typename... Ts> void h(Ts...);
void i();
有什么方法可以匹配可变参数函数声明,并将可变参数声明进一步绑定到某个节点?我想做类似 functionDecl(has(parmVarDecl(hasType(packExpansionType().bind("parameter_type")))))
的事情,但似乎这是不可能的,因为没有 packExpansionType
匹配器。我在这里遗漏了什么吗?
为了将来参考,我找到了解决这个问题的方法。实际上可以在检查中定义自定义匹配器。
namespace {
const AstTypeMatcher<PackExpansionType> packExpansionType;
const internal::VariadicDynCastAllOfMatcher<Stmt, PackExpansionExpr> packExpansionExpr;
}
// You can also use the macros from ASTMatchersMacros.h
...