Clang AST:从 CXXRecordDecl 访问成员函数模板
Clang AST: access member function templates from CXXRecordDecl
假设我有一个像这样的假人 class:
class Stack
{
public:
template<typename T>
void push(T val)
{ (void)val; }
template<typename T>
T pop()
{ return 0; }
bool empty() const
{ return true; }
};
其 AST 转储如下所示:
...
|-CXXRecordDecl 0x5610df147d60 <col:1, col:7> col:7 implicit class Stack
|-AccessSpecDecl 0x5610df147df0 <line:3:1, col:7> col:1 public
|-FunctionTemplateDecl 0x5610df1480e0 <line:4:3, line:6:16> line:5:8 push
| |-TemplateTypeParmDecl 0x5610df147e18 <line:4:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148040 <line:5:3, line:6:16> line:5:8 push 'void (T)'
| |-ParmVarDecl 0x5610df147f00 <col:13, col:15> col:15 referenced val 'T'
| `-CompoundStmt 0x5610df1484f0 <line:6:3, col:16>
| `-CStyleCastExpr 0x5610df1484c8 <col:5, col:11> 'void' <ToVoid>
| `-DeclRefExpr 0x5610df148498 <col:11> 'T' lvalue ParmVar 0x5610df147f00 'val' 'T'
|-FunctionTemplateDecl 0x5610df148300 <line:8:3, line:10:15> line:9:5 pop
| |-TemplateTypeParmDecl 0x5610df148140 <line:8:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148260 <line:9:3, line:10:15> line:9:5 pop 'T ()'
| `-CompoundStmt 0x5610df148538 <line:10:3, col:15>
| `-ReturnStmt 0x5610df148528 <col:5, col:12>
| `-IntegerLiteral 0x5610df148508 <col:12> 'int' 0
`-CXXMethodDecl 0x5610df1483e0 <line:12:3, line:13:18> line:12:8 empty 'bool () const'
`-CompoundStmt 0x5610df148570 <line:13:3, col:18>
`-ReturnStmt 0x5610df148560 <col:5, col:12>
`-CXXBoolLiteralExpr 0x5610df148550 <col:12> 'bool' true
如果可以访问 Stack
的 CXXRecordDecl
节点,我如何访问 push
和 pop
的 FunctionTemplateDecl
对象? CXXRecorDecl::methods
只有 returns empty
的方法声明,我没有看到任何其他可能有用的函数。我是否必须分别匹配函数模板声明,然后再将它们与 class 声明相关联?
我相信我现在已经弄明白了,如果这对其他人有用,我会回答我自己的问题:
这样做的方法是首先将给定的 CXXRecordDecl
转换为 DeclContext
,遍历包含的声明并尝试将它们转换为 FunctionTemplateDecl
,伪代码:
clang::CXXRecordDecl const *record = // ...
for (auto const *inner : static_cast<clang::DeclContext>(record)->decls()) {
auto const *member_function_template = llvm::dyn_cast<clang::FunctionTemplateDecl>(inner);
if (!member_function_template)
continue;
// do something useful
}
假设我有一个像这样的假人 class:
class Stack
{
public:
template<typename T>
void push(T val)
{ (void)val; }
template<typename T>
T pop()
{ return 0; }
bool empty() const
{ return true; }
};
其 AST 转储如下所示:
...
|-CXXRecordDecl 0x5610df147d60 <col:1, col:7> col:7 implicit class Stack
|-AccessSpecDecl 0x5610df147df0 <line:3:1, col:7> col:1 public
|-FunctionTemplateDecl 0x5610df1480e0 <line:4:3, line:6:16> line:5:8 push
| |-TemplateTypeParmDecl 0x5610df147e18 <line:4:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148040 <line:5:3, line:6:16> line:5:8 push 'void (T)'
| |-ParmVarDecl 0x5610df147f00 <col:13, col:15> col:15 referenced val 'T'
| `-CompoundStmt 0x5610df1484f0 <line:6:3, col:16>
| `-CStyleCastExpr 0x5610df1484c8 <col:5, col:11> 'void' <ToVoid>
| `-DeclRefExpr 0x5610df148498 <col:11> 'T' lvalue ParmVar 0x5610df147f00 'val' 'T'
|-FunctionTemplateDecl 0x5610df148300 <line:8:3, line:10:15> line:9:5 pop
| |-TemplateTypeParmDecl 0x5610df148140 <line:8:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148260 <line:9:3, line:10:15> line:9:5 pop 'T ()'
| `-CompoundStmt 0x5610df148538 <line:10:3, col:15>
| `-ReturnStmt 0x5610df148528 <col:5, col:12>
| `-IntegerLiteral 0x5610df148508 <col:12> 'int' 0
`-CXXMethodDecl 0x5610df1483e0 <line:12:3, line:13:18> line:12:8 empty 'bool () const'
`-CompoundStmt 0x5610df148570 <line:13:3, col:18>
`-ReturnStmt 0x5610df148560 <col:5, col:12>
`-CXXBoolLiteralExpr 0x5610df148550 <col:12> 'bool' true
如果可以访问 Stack
的 CXXRecordDecl
节点,我如何访问 push
和 pop
的 FunctionTemplateDecl
对象? CXXRecorDecl::methods
只有 returns empty
的方法声明,我没有看到任何其他可能有用的函数。我是否必须分别匹配函数模板声明,然后再将它们与 class 声明相关联?
我相信我现在已经弄明白了,如果这对其他人有用,我会回答我自己的问题:
这样做的方法是首先将给定的 CXXRecordDecl
转换为 DeclContext
,遍历包含的声明并尝试将它们转换为 FunctionTemplateDecl
,伪代码:
clang::CXXRecordDecl const *record = // ...
for (auto const *inner : static_cast<clang::DeclContext>(record)->decls()) {
auto const *member_function_template = llvm::dyn_cast<clang::FunctionTemplateDecl>(inner);
if (!member_function_template)
continue;
// do something useful
}