]> granicus.if.org Git - clang/commitdiff
Add ability to layout the vtable pointer in trivial cases. I noticed
authorMike Stump <mrs@apple.com>
Thu, 30 Jul 2009 00:22:38 +0000 (00:22 +0000)
committerMike Stump <mrs@apple.com>
Thu, 30 Jul 2009 00:22:38 +0000 (00:22 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77556 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
lib/AST/RecordLayoutBuilder.h
lib/CodeGen/CodeGenTypes.cpp
test/CodeGenCXX/virt.cpp [new file with mode: 0644]

index e3581d88d24623e0dbd48a69745e14bfe17f373b..a60a72b74fa4a2f29226c6030a8008ad1098e6c4 100644 (file)
@@ -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();
index e7d49b55a8e859b14760c2d8bbf64301716aef8a..41c002d61dca3fc6624952738a66bc9a7af02952 100644 (file)
@@ -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);
   
index f88ed048fd361045d4f1723bd1af9032451bff13..c20e90e8ce6c677ecfb0fc5fb955e1903eec5db2 100644 (file)
@@ -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 (file)
index 0000000..a07d8e0
--- /dev/null
@@ -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");