aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp26
-rw-r--r--lib/AST/RecordLayoutBuilder.h1
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--test/CodeGenCXX/virt.cpp8
4 files changed, 29 insertions, 8 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index e3581d88d2..a60a72b74f 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/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<CXXRecordDecl>(D));
+ if (Ctx.getLangOptions().CPlusPlus) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(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/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h
index e7d49b55a8..41c002d61d 100644
--- a/lib/AST/RecordLayoutBuilder.h
+++ b/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/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index f88ed048fd..c20e90e8ce 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/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<CXXRecordDecl>(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/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp
new file mode 100644
index 0000000000..a07d8e011f
--- /dev/null
+++ b/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");