clangparser: add support for parents

TODO: Check the assumption that a "base" always has a Type that can be cast to
RecordType.
TODO: Check the assumption that a "base" always has a Decl that can be cast to
CXXRecordDecl.

Add basic support for class parents. Focus purely on bases for now and ignore
vbases.

Test Plan:
- Tested with a simple example. Base containing a long and a class containing a
  float. Both fields appear in the final flattened code.
This commit is contained in:
Jake Hillion 2023-12-22 18:10:23 +00:00
parent beb404e41c
commit 460799bf74
2 changed files with 33 additions and 1 deletions

View File

@ -17,8 +17,10 @@
#include <clang/AST/ASTContext.h>
#include <clang/AST/Decl.h>
#include <clang/AST/DeclCXX.h>
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/QualTypeNames.h>
#include <clang/AST/RecordLayout.h>
#include <clang/AST/Type.h>
#include <clang/Basic/DiagnosticSema.h>
#include <clang/Sema/Sema.h>
@ -196,7 +198,7 @@ Type& ClangTypeParser::enumerateClass(const clang::RecordType& ty) {
ty, kind, std::move(name), std::move(fqName), size, virtuality);
enumerateClassTemplateParams(ty, c.templateParams);
// enumerateClassParents(type, c.parents);
enumerateClassParents(ty, c.parents);
enumerateClassMembers(ty, c.members);
// enumerateClassFunctions(type, c.functions);
@ -275,6 +277,34 @@ std::optional<TemplateParam> ClangTypeParser::enumerateTemplateTemplateParam(
}
}
void ClangTypeParser::enumerateClassParents(const clang::RecordType& ty,
std::vector<Parent>& parents) {
assert(parents.empty());
auto* decl = ty.getDecl();
auto* cxxDecl = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
if (cxxDecl == nullptr)
return;
const auto& layout = decl->getASTContext().getASTRecordLayout(decl);
for (const auto& base : cxxDecl->bases()) {
auto baseType = base.getType();
const auto* baseRecordType = llvm::dyn_cast<clang::RecordType>(&*baseType);
if (baseRecordType == nullptr)
continue;
auto* baseDecl = baseRecordType->getDecl();
auto* baseCxxDecl = llvm::dyn_cast<clang::CXXRecordDecl>(baseDecl);
if (baseCxxDecl == nullptr)
continue;
auto offset = layout.getBaseClassOffset(baseCxxDecl).getQuantity();
auto& ptype = enumerateType(*baseType);
Parent p{ptype, static_cast<uint64_t>(offset)};
parents.push_back(p);
}
}
void ClangTypeParser::enumerateClassMembers(const clang::RecordType& ty,
std::vector<Member>& members) {
assert(members.empty());

View File

@ -50,6 +50,7 @@ class Array;
class Class;
class Enum;
class Member;
struct Parent;
class Primitive;
class Reference;
class Type;
@ -114,6 +115,7 @@ class ClangTypeParser {
std::optional<TemplateParam> enumerateTemplateTemplateParam(
const clang::TemplateName&);
void enumerateClassParents(const clang::RecordType&, std::vector<Parent>&);
void enumerateClassMembers(const clang::RecordType&, std::vector<Member>&);
ContainerInfo* getContainerInfo(const std::string& fqName) const;