]> granicus.if.org Git - clang/commitdiff
[MS ABI] Error instead of generating bad vftables for certain virtual hierarchies...
authorHans Wennborg <hans@hanshq.net>
Thu, 27 Feb 2014 01:14:31 +0000 (01:14 +0000)
committerHans Wennborg <hans@hanshq.net>
Thu, 27 Feb 2014 01:14:31 +0000 (01:14 +0000)
Erroring out until we fix the bug means we don't have to keep chasing down
this same miscompile in a bunch of different places.

Differential Revision: http://llvm-reviews.chandlerc.com/D2890

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

lib/AST/VTableBuilder.cpp
test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-pr18967.cpp [new file with mode: 0644]

index e0e30a122a880c193b12847e8428a85296f48a6a..8efd9c03d4cccda12bb66175bdedbf0a4547ad6d 100644 (file)
@@ -2560,10 +2560,47 @@ private:
                   const CXXRecordDecl *LastVBase,
                   BasesSetVectorTy &VisitedBases);
 
+  void CheckBadVirtualInheritanceHierarchy() {
+    // We fail at this-adjustment for virtual methods inherited from
+    // non-virtual bases that overrides a method in a virtual base.
+    if (Context.getLangOpts().DumpVTableLayouts)
+      return;
+    for (CXXRecordDecl::base_class_const_iterator BI =
+        MostDerivedClass->bases_begin(), BE = MostDerivedClass->bases_end();
+        BI != BE; ++BI) {
+      const CXXRecordDecl *Base = BI->getType()->getAsCXXRecordDecl();
+      if (BI->isVirtual())
+        continue;
+      for (CXXRecordDecl::method_iterator I = Base->method_begin(),
+          E = Base->method_end(); I != E; ++I) {
+        const CXXMethodDecl *Method = *I;
+        if (!Method->isVirtual())
+          continue;
+        if (isa<CXXDestructorDecl>(Method))
+          continue;
+        OverriddenMethodsSetTy OverriddenMethods;
+        ComputeAllOverriddenMethods(Method, OverriddenMethods);
+        for (OverriddenMethodsSetTy::const_iterator I =
+            OverriddenMethods.begin(),
+            E = OverriddenMethods.end(); I != E; ++I) {
+          const CXXMethodDecl *Overridden = *I;
+          if (Base->isVirtuallyDerivedFrom(Overridden->getParent())) {
+            ErrorUnsupported("classes with non-virtual base "
+                "classes that override methods in virtual bases",
+                BI->getLocStart());
+            return;
+          }
+        }
+      }
+    }
+  }
+
   void LayoutVFTable() {
     // FIXME: add support for RTTI when we have proper LLVM support for symbols
     // pointing to the middle of a section.
 
+    CheckBadVirtualInheritanceHierarchy();
+
     BasesSetVectorTy VisitedBases;
     AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, 0,
                VisitedBases);
index 80efdd04908de4303f4c58ce1905bbfa188e0f50..0f53f73919e3936aa4397d2fdde377b2159e732a 100644 (file)
@@ -217,7 +217,12 @@ void call_complete_dtor() {
   // CHECK: ret
 }
 
-struct C : B {
+struct X : virtual VBase {
+  int x;
+};
+
+
+struct C : X {
   C();
   // has an implicit vdtor.
 };
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-pr18967.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-pr18967.cpp
new file mode 100644 (file)
index 0000000..cc4d9f7
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: not %clang_cc1 -triple i686-pc-win32 -emit-llvm -fno-rtti %s 2>&1 | FileCheck %s
+
+// CHECK: error: v-table layout for classes with non-virtual base classes that override methods in virtual bases is not supported yet
+
+struct A {
+  virtual int foo() { return a; }
+  int a;
+};
+struct B : virtual A {
+  B() : b(1) {}
+  virtual int bar() { return b; }
+  int b;
+};
+struct C : virtual A {
+  C() : c(2) {}
+  virtual int foo() { return c; }
+  int c;
+};
+struct D : B, C {
+  D() : d(3) {}
+  virtual int bar() { return d; }
+  int d;
+};
+int main() {
+  D d;
+  return d.foo();
+}