diff options
author | Reid Kleckner <rnk@google.com> | 2018-12-26 20:07:52 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-12-26 20:07:52 +0000 |
commit | 3ab5a9cd1c826b627d6bcc775df824f637dd9e17 (patch) | |
tree | 59fe307150248229891d860782766f4f68a64eda | |
parent | 56c5343e5a9fe03533251a623006c3d5c79db547 (diff) | |
download | bcm5719-llvm-3ab5a9cd1c826b627d6bcc775df824f637dd9e17.tar.gz bcm5719-llvm-3ab5a9cd1c826b627d6bcc775df824f637dd9e17.zip |
[MS] Mangle return adjusting thunks with the public access specifier
MSVC does this, so we should too.
Fixes PR40138
llvm-svn: 350071
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 18 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp | 29 |
2 files changed, 41 insertions, 6 deletions
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index caa3af598db..92e9679e49a 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2939,14 +2939,14 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D, // <vtordisp-shift> ::= <offset-to-vtordisp> // <vtordispex-shift> ::= <offset-to-vbptr> <vbase-offset-offset> // <offset-to-vtordisp> -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<uint32_t>(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<uint32_t>(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<FunctionProtoType>(), 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 00000000000..47b1a38ffe1 --- /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" |