[cfe-commits] r76348 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp lib/AST/RecordLayoutBuilder.h test/SemaCXX/class-layout.cpp
Anders Carlsson
andersca at mac.com
Sat Jul 18 17:18:48 PDT 2009
Author: andersca
Date: Sat Jul 18 19:18:47 2009
New Revision: 76348
URL: http://llvm.org/viewvc/llvm-project?rev=76348&view=rev
Log:
Handle layout of non-virtual base classes.
Added:
cfe/trunk/test/SemaCXX/class-layout.cpp
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/lib/AST/RecordLayoutBuilder.h
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=76348&r1=76347&r2=76348&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Jul 18 19:18:47 2009
@@ -11,6 +11,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
@@ -20,9 +21,48 @@
using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
- : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
+ : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
IsUnion(false) {}
+void
+ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
+ assert(!RD->isPolymorphic() &&
+ "FIXME: We don't support polymorphic classes yet!");
+
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ if (!i->isVirtual()) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAsRecordType()->getDecl());
+ LayoutNonVirtualBase(Base);
+ }
+ }
+}
+
+void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
+ const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
+ assert(BaseInfo.getDataSize() > 0 &&
+ "FIXME: Handle empty classes.");
+
+ // FIXME: Should get the non-virtual alignment of the base.
+ unsigned BaseAlign = BaseInfo.getAlignment();
+
+ // FIXME: Should get the non-virtual size of the base.
+ uint64_t BaseSize = BaseInfo.getDataSize();
+
+ // Round up the current record size to the base's alignment boundary.
+ Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
+
+ // Reserve space for this base.
+ Size += BaseSize;
+
+ // Remember the next available offset.
+ NextOffset = Size;
+
+ // Remember max struct/class alignment.
+ UpdateAlignment(BaseAlign);
+}
+
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
IsUnion = D->isUnion();
@@ -31,7 +71,11 @@
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getAlignment());
-
+
+ // If this is a C++ class, lay out the nonvirtual bases.
+ if (Ctx.getLangOptions().CPlusPlus)
+ LayoutNonVirtualBases(cast<CXXRecordDecl>(D));
+
LayoutFields(D);
// Finally, round the size of the total struct up to the alignment of the
@@ -191,8 +235,20 @@
Builder.Layout(D);
- return new ASTRecordLayout(Builder.Size, Builder.Alignment,
- Builder.NextOffset,
+ bool IsPODForThePurposeOfLayout;
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // In C, all record types are POD.
+ IsPODForThePurposeOfLayout = true;
+ } else {
+ // FIXME: This is not always correct. See the part about bitfields at
+ // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
+ IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
+ }
+
+ uint64_t DataSize =
+ IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
+
+ return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
Builder.FieldOffsets.data(),
Builder.FieldOffsets.size());
}
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=76348&r1=76347&r2=76348&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Sat Jul 18 19:18:47 2009
@@ -15,6 +15,7 @@
namespace clang {
class ASTContext;
class ASTRecordLayout;
+ class CXXRecordDecl;
class FieldDecl;
class ObjCImplementationDecl;
class ObjCInterfaceDecl;
@@ -34,12 +35,16 @@
ASTRecordLayoutBuilder(ASTContext &Ctx);
void Layout(const RecordDecl *D);
+ void Layout(const CXXRecordDecl *D);
void Layout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
void LayoutFields(const RecordDecl *D);
void LayoutField(const FieldDecl *D);
+ void LayoutNonVirtualBases(const CXXRecordDecl *RD);
+ void LayoutNonVirtualBase(const CXXRecordDecl *RD);
+
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
void FinishLayout();
Added: cfe/trunk/test/SemaCXX/class-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class-layout.cpp?rev=76348&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/class-layout.cpp (added)
+++ cfe/trunk/test/SemaCXX/class-layout.cpp Sat Jul 18 19:18:47 2009
@@ -0,0 +1,31 @@
+// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify
+
+#define SA(n, p) int a##n[(p) ? 1 : -1]
+
+struct A {
+ int a;
+ char b;
+};
+
+SA(0, sizeof(A) == 8);
+
+struct B : A {
+ char c;
+};
+
+SA(1, sizeof(B) == 12);
+
+struct C {
+// Make fields private so C won't be a POD type.
+private:
+ int a;
+ char b;
+};
+
+SA(2, sizeof(C) == 8);
+
+struct D : C {
+ char c;
+};
+
+SA(3, sizeof(D) == 8);
More information about the cfe-commits
mailing list