例如,我有一个课程:
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
可以访问。
我想要具有CXXRecordDecl
实例化类型的FieldDecl bar_
答案 0 :(得分:1)
这对我有用:
ClassTemplateSpecializationDecl
投射到DeclContext
,DeclContext::decls()
遍历存储的声明,dyn_cast
将Decl
迭代到FieldDecl
和getType()
-这将是成员变量的实例化类型。dyn_cast
至CXXMethodDecl
的成员函数,并以类似的方式继续-我还没有
必须自己尝试一下。所有这些我都是通过逐步学习并研究ASTDumper
的工作方式来学习的。
答案 1 :(得分:1)
仅供参考,您想要的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'