forked from OSchip/llvm-project
[MS] Mangle return adjusting thunks with the public access specifier
MSVC does this, so we should too. Fixes PR40138 llvm-svn: 350071
This commit is contained in:
parent
56c5343e5a
commit
3ab5a9cd1c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
Loading…
Reference in New Issue