如何在 Clang 中获取模板化类的实例化 CXXRecordDecl?

How do you obtain the instantiated CXXRecordDecl of a templated class in Clang?

本文关键字:实例化 CXXRecordDecl Clang 获取      更新时间:2023-10-16

例如,我有一个类:

template<typename T>
class Foo {
public:
T getBar();
private:
T bar_;
};

它实例化为:

using FooBarT = Foo<Bar>;

如何获取具有已解析字段和方法Foo<bar>CXXRecordDecl


我试过了:

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知道。

我想要具有实例化类型的CXXRecordDecl用于FieldDecl bar_

仅供参考,您想要的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'

这对我有用:

  1. 演员ClassTemplateSpecializationDeclDeclContext
  2. 使用DeclContext::decls()遍历存储的声明,
  3. dyn_cast迭代Decls 到FieldDeclgetType()- 这将是成员变量的实例化类型。
  4. dyn_cast为成员功能CXXMethodDecl并继续类似 - 我没有 得自己尝试一下。

所有这些都是通过逐步学习和研究ASTDumper如何工作的。