如何无需递归遍历基类获取CXXRecordDecl的显式及继承隐式字段
Clang获取类所有显式+继承字段的简化方案
方案1:直接调用ASTContext封装好的getAllVisibleFields接口
这个是最省事的方案,Clang内部已经实现了继承链遍历、访问权限校验、虚继承去重的所有逻辑,一行调用就能拿到所有可访问的字段,包含自身显式定义和父类继承的字段。
示例代码:
#include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "llvm/ADT/SmallVector.h" // 假设你已经拿到了目标类的CXXRecordDecl指针 RD llvm::SmallVector<const clang::FieldDecl *> AllVisibleFields; RD->getASTContext().getAllVisibleFields(RD, AllVisibleFields);
遍历AllVisibleFields即可拿到所有符合要求的字段。
方案2:用forallBases工具函数自定义遍历逻辑
如果你需要更细粒度的控制(比如要收集不可访问的父类私有字段、过滤特定类型的字段等),可以用CXXRecordDecl自带的forallBases方法替代手写递归遍历,配合内置的isAccessibleFrom接口做权限判断,不用自己实现C++继承访问规则。
示例代码:
#include "clang/AST/DeclCXX.h" #include "llvm/ADT/SmallVector.h" llvm::SmallVector<const clang::FieldDecl *> AllFields; // 先收集当前类自身的显式字段 for (const auto *FD : RD->fields()) { AllFields.push_back(FD); } // 遍历所有基类(自动处理虚基类去重,不会重复遍历) RD->forallBases([&](const clang::CXXRecordDecl *Base) { for (const auto *FD : Base->fields()) { // 可选:加上权限判断,仅收集当前类可访问的字段 if (FD->isAccessibleFrom(RD)) { AllFields.push_back(FD); } } return true; // 返回true继续遍历下一个基类,返回false可提前终止遍历 });
额外说明
- 不需要可见性校验的场景下,直接去掉
isAccessibleFrom判断即可拿到所有父类字段,包括私有不可访问的成员 - 如果要收集成员函数而非字段,可以换用
ASTContext::getAllVisibleMethods接口,逻辑完全一致
内容的提问来源于stack exchange,提问作者llambdaa
相关产品推荐
相关产品推荐

