From: Anders Carlsson Date: Fri, 25 Sep 2009 00:02:51 +0000 (+0000) Subject: More work on empty classes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6026504302763f74102592602b392cecd5ced3ae;p=clang More work on empty classes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82736 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index dec6402d36..38c3e37352 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -252,6 +252,18 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, return true; } +bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, + uint64_t Offset) const { + if (const RecordType *RT = dyn_cast(FD->getType())) { + if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) + return canPlaceRecordAtOffset(RD, Offset); + } + + // FIXME: Arrays. + + return true; +} + void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset) { if (RD->isEmpty()) @@ -485,6 +497,17 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { // Round up the current record size to the field's alignment boundary. FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + + if (!IsUnion) { + while (true) { + // Check if we can place the field at this offset. + if (canPlaceFieldAtOffset(D, FieldOffset)) + break; + + // We can't try again. + FieldOffset += FieldAlign; + } + } } // Place this field at the current location. diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 43563c6729..0f83661cd9 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -103,6 +103,10 @@ class ASTRecordLayoutBuilder { /// (direct or indirect) of the same type having the same offset. bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset) const; + /// canPlaceFieldAtOffset - Return whether a field can be placed at the given + /// offset. + bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const; + /// UpdateEmptyClassOffsets - Called after a record (either a base class /// or a field) has been placed at the given offset. Will update the /// EmptyClassOffsets map if the class is empty or has any empty bases or diff --git a/test/SemaCXX/empty-class-layout.cpp b/test/SemaCXX/empty-class-layout.cpp index ebbeb38fc9..625e3ee903 100644 --- a/test/SemaCXX/empty-class-layout.cpp +++ b/test/SemaCXX/empty-class-layout.cpp @@ -17,3 +17,10 @@ struct F : E { }; struct G : E, F { }; SA(3, sizeof(G) == 2); + +struct H { H(); }; + +struct I : H { + H h; +}; +SA(4, sizeof(I) == 2);