Browse Source

Improved the check for a layout on a record.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/987/head
Dimitar Dobrev 8 years ago
parent
commit
ada983c40d
  1. 90
      src/CppParser/Parser.cpp

90
src/CppParser/Parser.cpp

@ -820,6 +820,67 @@ Class* Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record) @@ -820,6 +820,67 @@ Class* Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record)
static int I = 0;
static bool IsRecordValid(const clang::RecordDecl* RC,
std::vector<const clang::RecordDecl*>& Visited)
{
using namespace clang;
if (std::find(Visited.begin(), Visited.end(), RC) != Visited.end())
return true;
Visited.push_back(RC);
if (RC->isInvalidDecl())
return false;
for (auto Field : RC->fields())
{
auto Type = Field->getType()->getUnqualifiedDesugaredType();
const auto* RD = const_cast<CXXRecordDecl*>(Type->getAsCXXRecordDecl());
if (!RD)
RD = Type->getPointeeCXXRecordDecl();
if (RD && !IsRecordValid(RD, Visited))
return false;
}
return true;
}
static bool IsRecordValid(const clang::RecordDecl* RC)
{
std::vector<const clang::RecordDecl*> Visited;
return IsRecordValid(RC, Visited);
}
static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::QualType& Ty) {
using namespace clang;
if (auto RT = Ty->getAs<clang::RecordType>())
return dyn_cast<clang::CXXRecordDecl>(RT->getDecl());
else if (auto TST = Ty->getAs<clang::TemplateSpecializationType>())
return dyn_cast<clang::CXXRecordDecl>(
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl());
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
return Injected->getDecl();
assert("Could not get base CXX record from type");
return nullptr;
}
static bool HasLayout(const clang::RecordDecl* Record)
{
if (Record->isDependentType() || !Record->getDefinition() ||
!IsRecordValid(Record))
return false;
if (auto CXXRecord = llvm::dyn_cast<clang::CXXRecordDecl>(Record))
for (auto Base : CXXRecord->bases())
{
auto CXXBase = GetCXXRecordDeclFromBaseType(Base.getType());
if (!CXXBase || !HasLayout(CXXBase))
return false;
}
return true;
}
void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
{
using namespace clang;
@ -846,7 +907,7 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC) @@ -846,7 +907,7 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
RC->isDependent = Record->isDependentType();
RC->isExternCContext = Record->isExternCContext();
bool hasLayout = !Record->isDependentType() && !Record->isInvalidDecl();
bool hasLayout = HasLayout(Record);
if (hasLayout)
{
@ -926,21 +987,6 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC) @@ -926,21 +987,6 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
}
}
static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::Type* Ty) {
using namespace clang;
if (auto RT = Ty->getAs<clang::RecordType>())
return dyn_cast<clang::CXXRecordDecl>(RT->getDecl());
else if (auto TST = Ty->getAs<clang::TemplateSpecializationType>())
return dyn_cast<clang::CXXRecordDecl>(
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl());
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
return Injected->getDecl();
assert("Could not get base CXX record from type");
return nullptr;
}
void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
{
using namespace clang;
@ -961,7 +1007,7 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC) @@ -961,7 +1007,7 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
RC->hasNonTrivialCopyConstructor = Record->hasNonTrivialCopyConstructor();
RC->hasNonTrivialDestructor = Record->hasNonTrivialDestructor();
bool hasLayout = !Record->isDependentType() && !Record->isInvalidDecl() &&
bool hasLayout = HasLayout(Record) &&
Record->getDeclName() != c->getSema().VAListTagName;
// Get the record layout information.
@ -976,10 +1022,8 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC) @@ -976,10 +1022,8 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
}
// Iterate through the record bases.
for (auto it = Record->bases_begin(); it != Record->bases_end(); ++it)
for (auto BS : Record->bases())
{
auto& BS = *it;
BaseClassSpecifier* Base = new BaseClassSpecifier();
Base->access = ConvertToAccess(BS.getAccessSpecifier());
Base->isVirtual = BS.isVirtual();
@ -987,7 +1031,7 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC) @@ -987,7 +1031,7 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
auto BSTL = BS.getTypeSourceInfo()->getTypeLoc();
Base->type = WalkType(BS.getType(), &BSTL);
auto BaseDecl = GetCXXRecordDeclFromBaseType(BS.getType().getTypePtr());
auto BaseDecl = GetCXXRecordDeclFromBaseType(BS.getType());
if (BaseDecl && Layout)
{
auto Offset = BS.isVirtual() ? Layout->getVBaseClassOffset(BaseDecl)
@ -2784,7 +2828,7 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty) @@ -2784,7 +2828,7 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
return false;
if (auto RT = FinalType->getAs<clang::RecordType>())
return RT->getDecl()->getDefinition() != 0;
return HasLayout(RT->getDecl());
// Lock in the MS inheritance model if we have a member pointer to a class,
// else we get an assertion error inside Clang's codegen machinery.
@ -2985,7 +3029,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F, @@ -2985,7 +3029,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
const CXXMethodDecl* MD;
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
!CanCheckCodeGenInfo(c->getSema(), MD->getThisType(c->getASTContext()).getTypePtr()))
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext())))
return;
if (!CanCheckCodeGenInfo(c->getSema(), FD->getReturnType().getTypePtr()))

Loading…
Cancel
Save