如何在 Clang 中获取模板化 class 的实例化 CXXRecordDecl?
How do you obtain the instantiated CXXRecordDecl of a templated class in Clang?
比如我有一个class:
template<typename T>
class Foo {
public:
T getBar();
private:
T bar_;
};
实例化为:
using FooBarT = Foo<Bar>;
如何获取 CXXRecordDecl
以及 Foo<bar>
的已解析字段和方法?
我试过了:
const auto *typeAliasDecl = llvm::dyn_cast<clang::TypeAliasDecl>(decl);
typeAliasDecl->getUnderlyingType()->getAsCXXRecordDecl()->dump();
我得到的输出是:
ClassTemplateSpecializationDecl 0x0000000 class Foo
`-TemplateArgument type 'Bar'
但是,我也希望 CXXRecordDecl
具有字段和方法,以便我可以遍历它们。我也试过:
for (const auto *contextDecl: typeAliasDecl->getUnderlyingType()->getUnqualifiedDesugaredType()->getAsCXXRecordDecl()->getDeclContext()->decls()) {
const auto *classTemplateDecl = llvm::dyn_cast<clang::ClassTemplateDecl>(contextDecl);
classTemplateDecl->dump();
}
输出:
ClassTemplateDecl Foo
|-TemplateTypeParmDecl 0x0000000 referenced typename depth 0 index 0 T
|-CXXRecordDecl class Foo definition
| ...
| |-FieldDecl 0x0000000 referenced bar_ 'T'
|-ClassTemplateSpecializationDecl 0x0000000 class Foo
`-TemplateArgument type 'Bar'
如您所见,CXXRecordDecl class Foo definition
可以访问 FieldDecl
,但不知道 bar_
的类型实例化,而 ClassTemplateSpecializationDecl
知道。
我想要实例化类型为 FieldDecl bar_
的 CXXRecordDecl
这对我有用:
- 将
ClassTemplateSpecializationDecl
转换为 DeclContext
,
- 使用
DeclContext::decls()
、 迭代存储的声明
dyn_cast
迭代 Decl
s 到 FieldDecl
和 getType()
- 这将是成员变量的实例化类型。
dyn_cast
到 CXXMethodDecl
用于成员函数并以类似方式继续 - 我还没有
必须亲自尝试一下。
所有这些都是我通过逐步研究 ASTDumper
的工作原理而学到的。
仅供参考,您想要的 CXXRecordDecl 只是 AST 中的 ClassTemplateSpecializationDecl,因为 ClassTemplateSpecializationDecl 是 CXXRecordDecl 的子类。你真正想要的不是你已经拥有的CXXRecordDecl,而是那个CXXRecordDecl中的FieldDecl。
您在ClassTemplateSpecializationDecl 下没有FieldDecl 的原因是您的模板实例化代码没有使用bar_。尝试以下来源:
template<typename T>
class Foo {
public:
T getBar() { return bar_; };
private:
T bar_;
};
using FooBarT = Foo<int>;
void func() {
FooBarT().getBar();
}
然后 FieldDecl 将在 ClassTemplateSpecializationDecl 下:
| `-ClassTemplateSpecializationDecl 0x1fe7f2a9d80 <line:2:1, line:9:1> line:3:7 class Foo definition
...
| |-FieldDecl 0x1fe7f2aa3c8 <line:8:2, col:4> col:4 referenced bar_ 'int':'int'
比如我有一个class:
template<typename T>
class Foo {
public:
T getBar();
private:
T bar_;
};
实例化为:
using FooBarT = Foo<Bar>;
如何获取 CXXRecordDecl
以及 Foo<bar>
的已解析字段和方法?
我试过了:
const auto *typeAliasDecl = llvm::dyn_cast<clang::TypeAliasDecl>(decl);
typeAliasDecl->getUnderlyingType()->getAsCXXRecordDecl()->dump();
我得到的输出是:
ClassTemplateSpecializationDecl 0x0000000 class Foo
`-TemplateArgument type 'Bar'
但是,我也希望 CXXRecordDecl
具有字段和方法,以便我可以遍历它们。我也试过:
for (const auto *contextDecl: typeAliasDecl->getUnderlyingType()->getUnqualifiedDesugaredType()->getAsCXXRecordDecl()->getDeclContext()->decls()) {
const auto *classTemplateDecl = llvm::dyn_cast<clang::ClassTemplateDecl>(contextDecl);
classTemplateDecl->dump();
}
输出:
ClassTemplateDecl Foo
|-TemplateTypeParmDecl 0x0000000 referenced typename depth 0 index 0 T
|-CXXRecordDecl class Foo definition
| ...
| |-FieldDecl 0x0000000 referenced bar_ 'T'
|-ClassTemplateSpecializationDecl 0x0000000 class Foo
`-TemplateArgument type 'Bar'
如您所见,CXXRecordDecl class Foo definition
可以访问 FieldDecl
,但不知道 bar_
的类型实例化,而 ClassTemplateSpecializationDecl
知道。
我想要实例化类型为 FieldDecl bar_
CXXRecordDecl
这对我有用:
- 将
ClassTemplateSpecializationDecl
转换为DeclContext
, - 使用
DeclContext::decls()
、 迭代存储的声明
dyn_cast
迭代Decl
s 到FieldDecl
和getType()
- 这将是成员变量的实例化类型。dyn_cast
到CXXMethodDecl
用于成员函数并以类似方式继续 - 我还没有 必须亲自尝试一下。
所有这些都是我通过逐步研究 ASTDumper
的工作原理而学到的。
仅供参考,您想要的 CXXRecordDecl 只是 AST 中的 ClassTemplateSpecializationDecl,因为 ClassTemplateSpecializationDecl 是 CXXRecordDecl 的子类。你真正想要的不是你已经拥有的CXXRecordDecl,而是那个CXXRecordDecl中的FieldDecl。
您在ClassTemplateSpecializationDecl 下没有FieldDecl 的原因是您的模板实例化代码没有使用bar_。尝试以下来源:
template<typename T>
class Foo {
public:
T getBar() { return bar_; };
private:
T bar_;
};
using FooBarT = Foo<int>;
void func() {
FooBarT().getBar();
}
然后 FieldDecl 将在 ClassTemplateSpecializationDecl 下:
| `-ClassTemplateSpecializationDecl 0x1fe7f2a9d80 <line:2:1, line:9:1> line:3:7 class Foo definition
...
| |-FieldDecl 0x1fe7f2aa3c8 <line:8:2, col:4> col:4 referenced bar_ 'int':'int'