Skip to content

Commit ada983c

Browse files
committed
Improved the check for a layout on a record.
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent c3048ae commit ada983c

File tree

1 file changed

+67
-23
lines changed

1 file changed

+67
-23
lines changed

src/CppParser/Parser.cpp

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,67 @@ Class* Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record)
820820

821821
static int I = 0;
822822

823+
static bool IsRecordValid(const clang::RecordDecl* RC,
824+
std::vector<const clang::RecordDecl*>& Visited)
825+
{
826+
using namespace clang;
827+
828+
if (std::find(Visited.begin(), Visited.end(), RC) != Visited.end())
829+
return true;
830+
831+
Visited.push_back(RC);
832+
if (RC->isInvalidDecl())
833+
return false;
834+
for (auto Field : RC->fields())
835+
{
836+
auto Type = Field->getType()->getUnqualifiedDesugaredType();
837+
const auto* RD = const_cast<CXXRecordDecl*>(Type->getAsCXXRecordDecl());
838+
if (!RD)
839+
RD = Type->getPointeeCXXRecordDecl();
840+
if (RD && !IsRecordValid(RD, Visited))
841+
return false;
842+
}
843+
return true;
844+
}
845+
846+
static bool IsRecordValid(const clang::RecordDecl* RC)
847+
{
848+
std::vector<const clang::RecordDecl*> Visited;
849+
return IsRecordValid(RC, Visited);
850+
}
851+
852+
static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::QualType& Ty) {
853+
using namespace clang;
854+
855+
if (auto RT = Ty->getAs<clang::RecordType>())
856+
return dyn_cast<clang::CXXRecordDecl>(RT->getDecl());
857+
else if (auto TST = Ty->getAs<clang::TemplateSpecializationType>())
858+
return dyn_cast<clang::CXXRecordDecl>(
859+
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl());
860+
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
861+
return Injected->getDecl();
862+
863+
assert("Could not get base CXX record from type");
864+
return nullptr;
865+
}
866+
867+
static bool HasLayout(const clang::RecordDecl* Record)
868+
{
869+
if (Record->isDependentType() || !Record->getDefinition() ||
870+
!IsRecordValid(Record))
871+
return false;
872+
873+
if (auto CXXRecord = llvm::dyn_cast<clang::CXXRecordDecl>(Record))
874+
for (auto Base : CXXRecord->bases())
875+
{
876+
auto CXXBase = GetCXXRecordDeclFromBaseType(Base.getType());
877+
if (!CXXBase || !HasLayout(CXXBase))
878+
return false;
879+
}
880+
881+
return true;
882+
}
883+
823884
void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
824885
{
825886
using namespace clang;
@@ -846,7 +907,7 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
846907
RC->isDependent = Record->isDependentType();
847908
RC->isExternCContext = Record->isExternCContext();
848909

849-
bool hasLayout = !Record->isDependentType() && !Record->isInvalidDecl();
910+
bool hasLayout = HasLayout(Record);
850911

851912
if (hasLayout)
852913
{
@@ -926,21 +987,6 @@ void Parser::WalkRecord(const clang::RecordDecl* Record, Class* RC)
926987
}
927988
}
928989

929-
static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::Type* Ty) {
930-
using namespace clang;
931-
932-
if (auto RT = Ty->getAs<clang::RecordType>())
933-
return dyn_cast<clang::CXXRecordDecl>(RT->getDecl());
934-
else if (auto TST = Ty->getAs<clang::TemplateSpecializationType>())
935-
return dyn_cast<clang::CXXRecordDecl>(
936-
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl());
937-
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
938-
return Injected->getDecl();
939-
940-
assert("Could not get base CXX record from type");
941-
return nullptr;
942-
}
943-
944990
void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
945991
{
946992
using namespace clang;
@@ -961,7 +1007,7 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
9611007
RC->hasNonTrivialCopyConstructor = Record->hasNonTrivialCopyConstructor();
9621008
RC->hasNonTrivialDestructor = Record->hasNonTrivialDestructor();
9631009

964-
bool hasLayout = !Record->isDependentType() && !Record->isInvalidDecl() &&
1010+
bool hasLayout = HasLayout(Record) &&
9651011
Record->getDeclName() != c->getSema().VAListTagName;
9661012

9671013
// Get the record layout information.
@@ -976,18 +1022,16 @@ void Parser::WalkRecordCXX(const clang::CXXRecordDecl* Record, Class* RC)
9761022
}
9771023

9781024
// Iterate through the record bases.
979-
for (auto it = Record->bases_begin(); it != Record->bases_end(); ++it)
1025+
for (auto BS : Record->bases())
9801026
{
981-
auto& BS = *it;
982-
9831027
BaseClassSpecifier* Base = new BaseClassSpecifier();
9841028
Base->access = ConvertToAccess(BS.getAccessSpecifier());
9851029
Base->isVirtual = BS.isVirtual();
9861030

9871031
auto BSTL = BS.getTypeSourceInfo()->getTypeLoc();
9881032
Base->type = WalkType(BS.getType(), &BSTL);
9891033

990-
auto BaseDecl = GetCXXRecordDeclFromBaseType(BS.getType().getTypePtr());
1034+
auto BaseDecl = GetCXXRecordDeclFromBaseType(BS.getType());
9911035
if (BaseDecl && Layout)
9921036
{
9931037
auto Offset = BS.isVirtual() ? Layout->getVBaseClassOffset(BaseDecl)
@@ -2784,7 +2828,7 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
27842828
return false;
27852829

27862830
if (auto RT = FinalType->getAs<clang::RecordType>())
2787-
return RT->getDecl()->getDefinition() != 0;
2831+
return HasLayout(RT->getDecl());
27882832

27892833
// Lock in the MS inheritance model if we have a member pointer to a class,
27902834
// else we get an assertion error inside Clang's codegen machinery.
@@ -2985,7 +3029,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
29853029

29863030
const CXXMethodDecl* MD;
29873031
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
2988-
!CanCheckCodeGenInfo(c->getSema(), MD->getThisType(c->getASTContext()).getTypePtr()))
3032+
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext())))
29893033
return;
29903034

29913035
if (!CanCheckCodeGenInfo(c->getSema(), FD->getReturnType().getTypePtr()))

0 commit comments

Comments
 (0)