From 3ab5a9cd1c826b627d6bcc775df824f637dd9e17 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 26 Dec 2018 20:07:52 +0000 Subject: [PATCH] [MS] Mangle return adjusting thunks with the public access specifier MSVC does this, so we should too. Fixes PR40138 llvm-svn: 350071 --- clang/lib/AST/MicrosoftMangle.cpp | 18 +++++++++----- .../test/CodeGenCXX/mangle-ms-thunks-covariant.cpp | 29 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index caa3af59..92e9679 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2939,14 +2939,14 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D, // ::= // ::= // -static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, +static void mangleThunkThisAdjustment(AccessSpecifier AS, const ThisAdjustment &Adjustment, MicrosoftCXXNameMangler &Mangler, raw_ostream &Out) { if (!Adjustment.Virtual.isEmpty()) { Out << '$'; char AccessSpec; - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -2974,7 +2974,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, Mangler.mangleNumber(-static_cast(Adjustment.NonVirtual)); } } else if (Adjustment.NonVirtual != 0) { - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -2988,7 +2988,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, } Mangler.mangleNumber(-static_cast(Adjustment.NonVirtual)); } else { - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -3019,7 +3019,13 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << '?'; Mangler.mangleName(MD); - mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO); + + // Usually the thunk uses the access specifier of the new method, but if this + // is a covariant return thunk, then MSVC always uses the public access + // specifier, and we do the same. + AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public; + mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO); + if (!Thunk.Return.isEmpty()) assert(Thunk.Method != nullptr && "Thunk info should hold the overridee decl"); @@ -3040,7 +3046,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk( MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type); Mangler.getStream() << "??_E"; Mangler.mangleName(DD->getParent()); - mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO); + mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO); Mangler.mangleFunctionType(DD->getType()->castAs(), DD); } diff --git a/clang/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp b/clang/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp new file mode 100644 index 0000000..47b1a38 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fno-rtti-data -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK + +namespace t1 { +struct A { +public: + virtual ~A(); + virtual A *f(); +}; +struct B { +public: + virtual ~B(); + +private: + virtual B *f(); +}; +struct C : A, B { + virtual ~C(); + +protected: + virtual C *f(); +}; +C c; +} +// Main external C::f impl: +// CHECK-DAG: "?f@C@t1@@MEAAPEAU12@XZ" +// New slot in C's vftable for B, returns C* directly: +// CHECK-DAG: "?f@C@t1@@O7EAAPEAU12@XZ" +// Return-adjusting thunk in C's vftable for B: +// CHECK-DAG: "?f@C@t1@@W7EAAPEAUB@2@XZ" -- 2.7.4