From: David Majnemer Date: Mon, 5 Aug 2013 22:43:06 +0000 (+0000) Subject: [ms-cxxabi] Properly mangle member pointers X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c0e64f3d293bc1c448a84d285f115bc946b91b07;p=clang [ms-cxxabi] Properly mangle member pointers There were three things missing from the original implementation: - We would omit the 'E' qualifier for members int 64-bit mode. - We would not exmaine the qualifiers in 'IsMember' mode. - We didn't generate the correct backref to the base class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187753 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index fb3f87ad13..8d7b76db5e 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -329,7 +329,11 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { mangleQualifiers(Ty.getQualifiers(), false); } else { mangleType(Ty, TL.getSourceRange(), QMM_Drop); - mangleQualifiers(Ty.getLocalQualifiers(), false); + mangleQualifiers(Ty.getLocalQualifiers(), Ty->isMemberPointerType()); + // Member pointers are suffixed with a back reference to the member + // pointer's class name. + if (const MemberPointerType *MPT = Ty->getAs()) + mangleName(MPT->getClass()->getAsCXXRecordDecl()); } } @@ -978,6 +982,7 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, // ::= 5 # not really based bool HasConst = Quals.hasConst(), HasVolatile = Quals.hasVolatile(); + if (!IsMember) { if (HasConst && HasVolatile) { Out << 'D'; @@ -989,6 +994,9 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, Out << 'A'; } } else { + if (PointersAre64Bit) + Out << 'E'; + if (HasConst && HasVolatile) { Out << 'T'; } else if (HasVolatile) { diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 3f80e54f43..1002d5ddc9 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -13,8 +13,8 @@ // CHECK: @"\01?h2@@3QBHB" // CHECK: @"\01?i@@3PAY0BE@HA" // CHECK: @"\01?j@@3P6GHCE@ZA" -// CHECK: @"\01?k@@3PTfoo@@DA" -// CHECK: @"\01?l@@3P8foo@@AEHH@ZA" +// CHECK: @"\01?k@@3PTfoo@@DQ1@" +// CHECK: @"\01?l@@3P8foo@@AEHH@ZQ1@" // CHECK: @"\01?color1@@3PANA" // CHECK: @"\01?color2@@3QBNB" // CHECK: @"\01?color3@@3QAY02$$CBNA" diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 4771fd4a5a..ae41f3c391 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -50,22 +50,22 @@ int Multiple ::*m_d_memptr; int Virtual ::*v_d_memptr; int NonZeroVBPtr::*n_d_memptr; int Unspecified::*u_d_memptr; -// CHECK: @"\01?s_d_memptr@@3PQSingle@@HA" = global i32 -1, align 4 -// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HA" = global i32 0, align 4 -// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HA" = global i32 -1, align 4 -// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HA" = global { i32, i32 } +// CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = global i32 -1, align 4 +// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4 +// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4 +// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 } // CHECK: { i32 0, i32 -1 }, align 4 -// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HA" = global { i32, i32 } +// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 } // CHECK: { i32 0, i32 -1 }, align 4 -// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HA" = global { i32, i32, i32 } +// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 } // CHECK: { i32 0, i32 0, i32 -1 }, align 4 void (Single ::*s_f_memptr)(); void (Multiple::*m_f_memptr)(); void (Virtual ::*v_f_memptr)(); -// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZA" = global i8* null, align 4 -// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZA" = global { i8*, i32 } zeroinitializer, align 4 -// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZA" = global { i8*, i32, i32 } zeroinitializer, align 4 +// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4 +// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4 +// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4 // We can define Unspecified after locking in the inheritance model. struct Unspecified : Multiple, Virtual { @@ -79,13 +79,13 @@ void (Single ::*s_f_mp)() = &Single::foo; void (Multiple ::*m_f_mp)() = &B2::foo; void (Virtual ::*v_f_mp)() = &Virtual::foo; void (Unspecified::*u_f_mp)() = &Unspecified::foo; -// CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZA" = +// CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" = // CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4 -// CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZA" = +// CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" = // CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4 -// CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZA" = +// CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" = // CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4 -// CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZA" = +// CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" = // CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 4 } @@ -102,16 +102,16 @@ struct B { int b; }; struct C : B, A { int c; }; void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo; -// CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZA" = +// CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" = // CHECK: global i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4 // Try a reinterpret_cast followed by a memptr conversion. void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo; -// CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZA" = +// CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" = // CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4 void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0; -// CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZA" = +// CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" = // CHECK: global { i8*, i32 } zeroinitializer, align 4 struct D : C { @@ -122,11 +122,11 @@ struct D : C { // Try a cast that changes the inheritance model. Null for D is 0, but null for // C is -1. We need the cast to long in order to hit the non-APValue path. int C::*ptr4 = (int C::*) (int D::*) (long D::*) 0; -// CHECK: @"\01?ptr4@CastParam@@3PQC@1@HA" = global i32 -1, align 4 +// CHECK: @"\01?ptr4@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4 // MSVC rejects this but we accept it. int C::*ptr5 = (int C::*) (long D::*) 0; -// CHECK: @"\01?ptr5@CastParam@@3PQC@1@HA" = global i32 -1, align 4 +// CHECK: @"\01?ptr5@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4 } struct UnspecWithVBPtr;