From 3dc7eb94403c9de3c5ec2cc0ffd9c4b7f57ba5fb Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 30 Jul 2009 00:22:38 +0000 Subject: [PATCH] Add ability to layout the vtable pointer in trivial cases. I noticed that we would silently do bad things with virtual bases in the layout code, so, we just turn them off. When people do better things with them, we can turn them back on. llvm-svn: 77556 --- clang/lib/AST/RecordLayoutBuilder.cpp | 26 ++++++++++++++++++++------ clang/lib/AST/RecordLayoutBuilder.h | 1 + clang/lib/CodeGen/CodeGenTypes.cpp | 2 -- clang/test/CodeGenCXX/virt.cpp | 8 ++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 clang/test/CodeGenCXX/virt.cpp diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index e3581d8..a60a72b 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -24,11 +24,19 @@ ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {} +void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { + if (RD->isPolymorphic()) + { + assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet"); + int AS = 0; + UpdateAlignment(Ctx.Target.getPointerAlign(AS)); + Size += Ctx.Target.getPointerWidth(AS); + NextOffset = Size; + } +} + 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()) { @@ -74,14 +82,20 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { UpdateAlignment(AA->getAlignment()); // If this is a C++ class, lay out the nonvirtual bases. - if (Ctx.getLangOptions().CPlusPlus) - LayoutNonVirtualBases(cast(D)); + if (Ctx.getLangOptions().CPlusPlus) { + const CXXRecordDecl *RD = cast(D); + LayoutVtable(RD); + LayoutNonVirtualBases(RD); + + assert (RD->getNumVBases() == 0 + && "FIXME: We don't support virtual bases yet!"); + } LayoutFields(D); NonVirtualSize = Size; NonVirtualAlignment = Alignment; - + // Finally, round the size of the total struct up to the alignment of the // struct itself. FinishLayout(); diff --git a/clang/lib/AST/RecordLayoutBuilder.h b/clang/lib/AST/RecordLayoutBuilder.h index e7d49b5..41c002d 100644 --- a/clang/lib/AST/RecordLayoutBuilder.h +++ b/clang/lib/AST/RecordLayoutBuilder.h @@ -48,6 +48,7 @@ class ASTRecordLayoutBuilder { void LayoutFields(const RecordDecl *D); void LayoutField(const FieldDecl *D); + void LayoutVtable(const CXXRecordDecl *RD); void LayoutNonVirtualBases(const CXXRecordDecl *RD); void LayoutNonVirtualBase(const CXXRecordDecl *RD); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index f88ed04..c20e90e 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -381,8 +381,6 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) { // FIXME. This may have to move to a better place. if (const CXXRecordDecl *RD = dyn_cast(TD)) { - 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()) { diff --git a/clang/test/CodeGenCXX/virt.cpp b/clang/test/CodeGenCXX/virt.cpp new file mode 100644 index 0000000..a07d8e0 --- /dev/null +++ b/clang/test/CodeGenCXX/virt.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -emit-llvm -o - -std=c++0x + +class A { +public: + virtual void foo(); +}; + +static_assert (sizeof (A) == (sizeof(void *)), "vtable pointer layout"); -- 2.7.4