Commit f27cdbda authored by ussrhero's avatar ussrhero

get field from base classes for clang type builder

parent 506c4c31
......@@ -227,6 +227,8 @@ void TypeInfoClangStruct::getFields()
void TypeInfoClangStruct::getRecursiveFields( clang::RecordDecl* recordDecl, MEMOFFSET_32 startOffset)
{
getFieldFromBaseClasses(recordDecl, startOffset);
const ASTRecordLayout &typeLayout = recordDecl->getASTContext().getASTRecordLayout(recordDecl);
for(clang::RecordDecl::decl_iterator declit = recordDecl->decls_begin(); declit != recordDecl->decls_end(); declit++)
......@@ -268,6 +270,24 @@ void TypeInfoClangStruct::getRecursiveFields( clang::RecordDecl* recordDecl, MEM
///////////////////////////////////////////////////////////////////////////////
void TypeInfoClangStruct::getFieldFromBaseClasses(clang::RecordDecl* recordDecl, MEMOFFSET_32 startOffset)
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
if (!classDecl)
return;
for (auto baseIt : classDecl->bases())
{
auto baseDecl = baseIt.getType()->getAsCXXRecordDecl();
auto baseOffset = recordDecl->getASTContext().getASTRecordLayout(m_decl).getBaseClassOffset( baseIt.getType()->getAsCXXRecordDecl() ).getQuantity();
getRecursiveFields(baseDecl, startOffset + baseOffset);
}
}
///////////////////////////////////////////////////////////////////////////////
size_t TypeInfoClangStruct::getSize()
{
const ASTRecordLayout &typeLayout = m_decl->getASTContext().getASTRecordLayout(m_decl);
......@@ -276,6 +296,95 @@ size_t TypeInfoClangStruct::getSize()
///////////////////////////////////////////////////////////////////////////////
size_t TypeInfoClangStruct::getBaseClassesCount()
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(m_decl);
if (!classDecl)
return 0;
return std::distance(classDecl->bases_begin(), classDecl->bases_end());
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoClangStruct::getBaseClass(const std::wstring& className)
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(m_decl);
if (!classDecl)
throw TypeException(L"Type has no base class");
for (auto baseIt : classDecl->bases())
{
if (baseIt.getType()->getAsCXXRecordDecl()->getNameAsString() == wstrToStr(className))
return getTypeForClangType(m_astSession, baseIt.getType());
}
std::wstringstream sstr;
sstr << getName() << " has no this base class : " << className;
throw TypeException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoClangStruct::getBaseClass(size_t index)
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(m_decl);
if (!classDecl)
throw TypeException(L"Type has no base class");
if (index >= getBaseClassesCount())
throw IndexException(index);
return getTypeForClangType(m_astSession, std::next(classDecl->bases_begin(), index)->getType());
}
///////////////////////////////////////////////////////////////////////////////
MEMOFFSET_REL TypeInfoClangStruct::getBaseClassOffset(const std::wstring &className)
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(m_decl);
if (!classDecl)
throw TypeException(L"Type has no base class");
for (auto baseIt : classDecl->bases())
{
if (baseIt.getType()->getAsCXXRecordDecl()->getNameAsString() == wstrToStr(className))
{
return m_decl->getASTContext().getASTRecordLayout(m_decl).getBaseClassOffset(
baseIt.getType()->getAsCXXRecordDecl()
).getQuantity();
}
}
std::wstringstream sstr;
sstr << getName() << " has no this base class : " << className;
throw TypeException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
MEMOFFSET_REL TypeInfoClangStruct::getBaseClassOffset(size_t index)
{
const CXXRecordDecl *classDecl = llvm::dyn_cast<clang::CXXRecordDecl>(m_decl);
if (!classDecl)
throw TypeException(L"Type has no base class");
if (index >= getBaseClassesCount())
throw IndexException(index);
return m_decl->getASTContext().getASTRecordLayout(m_decl).getBaseClassOffset(
std::next(classDecl->bases_begin(), index)->getType()->getAsCXXRecordDecl()
).getQuantity();
}
///////////////////////////////////////////////////////////////////////////////
std::wstring TypeInfoClangStructNoDef::str()
{
return std::wstring(L"forward declaration class/struct : ") + m_name;
......
......@@ -85,13 +85,25 @@ protected:
return printStructType(selfPtr);
}
virtual size_t getBaseClassesCount();
virtual TypeInfoPtr getBaseClass(const std::wstring& className);
virtual TypeInfoPtr getBaseClass(size_t index);
virtual MEMOFFSET_REL getBaseClassOffset(const std::wstring &name);
virtual MEMOFFSET_REL getBaseClassOffset(size_t index);
virtual size_t getSize();
protected:
virtual void getFields();
void getRecursiveFields( clang::RecordDecl* recordDecl, MEMOFFSET_32 startOffset);
void getRecursiveFields(clang::RecordDecl* recordDecl, MEMOFFSET_32 startOffset);
void getFieldFromBaseClasses(clang::RecordDecl* recordDecl, MEMOFFSET_32 startOffset);
ClangASTSessionPtr m_astSession;
......
......@@ -495,6 +495,10 @@ TEST_F(ClangTest, MultipleInheritance)
ASSERT_NO_THROW(typeInfo = typeProvider->getTypeByName(L"TestClass"));
EXPECT_EQ(3, typeInfo->getElementCount());
EXPECT_EQ(2, typeInfo->getBaseClassesCount());
EXPECT_EQ(1, typeInfo->getBaseClass(0)->getElementCount());
EXPECT_FALSE(typeInfo->getBaseClassOffset(0) == typeInfo->getBaseClassOffset(1));
EXPECT_EQ(L"field1", typeInfo->getBaseClass(0)->getElementName(0));
EXPECT_EQ(L"field2", typeInfo->getBaseClass(L"Base2")->getElementName(0));
EXPECT_FALSE(typeInfo->getBaseClassOffset(0) == typeInfo->getBaseClassOffset(L"Base2"));
std::wstring str;
EXPECT_NO_THROW(str = typeInfo->str());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment