From da810d9f6c8fd1b93c3e6775ebae59b487157cd8 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 27 Feb 2014 01:14:31 +0000 Subject: [PATCH] [MS ABI] Error instead of generating bad vftables for certain virtual hierarchies (PR18967) 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 | 37 +++++++++++++++++++ .../microsoft-abi-virtual-inheritance.cpp | 7 +++- ...bi-vtables-virtual-inheritance-pr18967.cpp | 27 ++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-pr18967.cpp diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index e0e30a122a..8efd9c03d4 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -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(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); diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 80efdd0490..0f53f73919 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -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 index 0000000000..cc4d9f7928 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-pr18967.cpp @@ -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(); +} -- 2.40.0