bolshakov-a created this revision.
bolshakov-a added reviewers: erichkeane, rnk.
Herald added a project: All.
bolshakov-a requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Several issues have been discovered and (hopefully) fixed here:

- Reference NTTPs should be mangled in the same manner as pointer ones.

- Pointer fields of class type NTTPs should be treated in the same

manner as reference ones.

- Pointer-to-member fields of class type NTTPs should be treated

differently compared to pointer-to-member NTTPs. Tests on
pointer-to-member-function NTTP class fields added.

Reference NTTP mangling was done back in 2013
in e8fdc06e0dab2e7b98339425dbe369e27e2092a3, and Microsoft might change
mangling algorithm since then. But class type NTTPs are introduced only
in C++20, and the test was written in b637148ecb62b900872b34eedd78b923bb43c378 
<https://reviews.llvm.org/rGb637148ecb62b900872b34eedd78b923bb43c378>.
It is strange if the MS ABI had been realy changed, because Microsoft
claims that they maintain ABI stability since VS 2015. I've tested both
on v142 and v143 MSVC toolsets, and they show the same behavior
on the test cases which are changed in this PR. But
pointer-to-member-function NTTP class field mangling has been actually
changed, because it was erroneous in v142, leading to name collisions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146386

Files:
  clang/lib/AST/MicrosoftMangle.cpp
  clang/test/CodeGenCXX/mangle-class-nttp.cpp
  clang/test/CodeGenCXX/mangle-ms-templates.cpp

Index: clang/test/CodeGenCXX/mangle-ms-templates.cpp
===================================================================
--- clang/test/CodeGenCXX/mangle-ms-templates.cpp
+++ clang/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -272,7 +272,7 @@
 };
 extern const record inst;
 void recref(type1<inst>) {}
-// CHECK: "?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
+// CHECK: "?recref@@YAXU?$type1@$1?inst@@3Urecord@@B@@@Z"
 
 struct _GUID {};
 struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
@@ -286,7 +286,7 @@
 void fun(UUIDType1<uuid> a) {}
 // CHECK: "?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
 void fun(UUIDType2<uuid> b) {}
-// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
 
 template <typename T> struct TypeWithFriendDefinition {
   friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition<T>) {}
Index: clang/test/CodeGenCXX/mangle-class-nttp.cpp
===================================================================
--- clang/test/CodeGenCXX/mangle-class-nttp.cpp
+++ clang/test/CodeGenCXX/mangle-class-nttp.cpp
@@ -15,7 +15,7 @@
 
 int n = 0;
 // CHECK: define weak_odr void @_Z1fIXtl1BadL_Z1nEEEEvv(
-// MSABI: define {{.*}} @"??$f@$2UB@@PEBH1?n@@3HAH0A@@@@YAXXZ"
+// MSABI: define {{.*}} @"??$f@$2UB@@PEBHE?n@@3HAH0A@@@@YAXXZ"
 template void f<B{&n}>();
 // CHECK: define weak_odr void @_Z1fIXtl1BLPKi0ELi1EEEEvv(
 // MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A@H00@@@YAXXZ"
@@ -86,13 +86,13 @@
 struct D { const int Derived::*p; int k; };
 template<D> void f() {}
 // CHECK: define weak_odr void @_Z1fIXtl1DLM7DerivedKi0ELi1EEEEvv
-// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0?0H00@@@YAXXZ"
+// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH00@@@YAXXZ"
 template void f<D{nullptr, 1}>();
 // CHECK: define weak_odr void @_Z1fIXtl1DEEEvv
-// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0?0H0A@@@@YAXXZ"
+// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH0A@@@@YAXXZ"
 template void f<D{nullptr}>();
 // CHECK: define weak_odr void @_Z1fIXtl1DadL_ZN7Derived1zEEEEEvv
-// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0BA@H0A@@@@YAXXZ"
+// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H82@z@@H0A@@@@YAXXZ"
 template void f<D{&Derived::z}>();
 #ifndef _WIN32
 // CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN1A1aEEEEEEvv
@@ -112,7 +112,45 @@
 template void f<D{(int Derived::*)&MoreDerived::z}>();
 #endif
 
-// FIXME: Pointers to member functions.
+struct DerivedVirtually : virtual A, Nested { int z; };
+struct D2 { const int DerivedVirtually::*p; int k; };
+template<D2> void f() {}
+// CHECK: define weak_odr void @_Z1fIXtl2D2LM16DerivedVirtuallyKi0ELi1EEEEvv
+// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H00@@@YAXXZ"
+template void f<D2{nullptr, 1}>();
+// CHECK: define weak_odr void @_Z1fIXtl2D2EEEvv
+// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H0A@@@@YAXXZ"
+template void f<D2{nullptr}>();
+// CHECK: define weak_odr void @_Z1fIXtl2D2adL_ZN16DerivedVirtually1zEEEEEvv
+// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFBA@A@H0A@@@@YAXXZ"
+template void f<D2{&DerivedVirtually::z}>();
+
+// Pointers to member functions.
+// Test struct templates instead of function templates so as to cover
+// the separate code which handles nullptr in their pointer-to-member arguments.
+struct Derived2 : A, Nested { void f(); virtual void g(); };
+struct D3 { void (Derived2::*p)(); };
+template <D3> struct S1 { static void fn() {} };
+// CHECK: define weak_odr void @_ZN2S1IXtl2D3adL_ZN8Derived21fEvEEEE2fnEv
+// MSABI: define {{.*}} @"?fn@?$S1@$2UD3@@P8Derived2@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ"
+template void S1<D3{&Derived2::f}>::fn();
+// CHECK: define weak_odr void @_ZN2S1IXtl2D3adL_ZN8Derived21gEvEEEE2fnEv
+// MSABI: define {{.*}} @"?fn@?$S1@$2UD3@@P8Derived2@@EAAXXZE??_92@$BA@AA@@@SAXXZ"
+template void S1<D3{&Derived2::g}>::fn();
+// CHECK: define weak_odr void @_ZN2S1IXtl2D3EEE2fnEv
+// MSABI: define {{.*}} @"?fn@?$S1@$2UD3@@P8Derived2@@EAAXXZHA@@@@SAXXZ"
+template void S1<D3{nullptr}>::fn();
+
+struct NoInheritance { void f(); };
+struct D4 { void (NoInheritance::*p)(); };
+template <D4> struct S2 { static void fn() {} };
+// CHECK: define weak_odr void @_ZN2S2IXtl2D4adL_ZN13NoInheritance1fEvEEEE2fnEv
+// MSABI: define {{.*}} @"?fn@?$S2@$2UD4@@P8NoInheritance@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ"
+template void S2<D4{&NoInheritance::f}>::fn();
+// CHECK: define weak_odr void @_ZN2S2IXtl2D4EEE2fnEv
+// MSABI: define {{.*}} @"?fn@?$S2@$2UD4@@P8NoInheritance@@EAAXXZN@@@SAXXZ"
+template void S2<D4{nullptr}>::fn();
+
 
 union E {
   int n;
@@ -204,8 +242,6 @@
 template void f<G{-8, -32}>();
 
 // Empty and nearly-empty unions.
-// Some of the MSVC manglings here are our invention, because MSVC rejects, but
-// seem likely to be right.
 union H1 {};
 union H2 { int : 1, : 2, : 3; };
 union H3 { int : 1, a, : 2, b, : 3; };
Index: clang/lib/AST/MicrosoftMangle.cpp
===================================================================
--- clang/lib/AST/MicrosoftMangle.cpp
+++ clang/lib/AST/MicrosoftMangle.cpp
@@ -368,9 +368,13 @@
   void mangleVariableEncoding(const VarDecl *VD);
   void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD,
                                StringRef Prefix = "$");
+  void mangleMemberDataPointerInClassNTTP(const CXXRecordDecl *,
+                                          const ValueDecl *);
   void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
                                    const CXXMethodDecl *MD,
                                    StringRef Prefix = "$");
+  void mangleMemberFunctionPointerInClassNTTP(const CXXRecordDecl *RD,
+                                              const CXXMethodDecl *MD);
   void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
                                 const MethodVFTableLocation &ML);
   void mangleNumber(int64_t Number);
@@ -711,6 +715,27 @@
     mangleNumber(VBTableOffset);
 }
 
+void MicrosoftCXXNameMangler::mangleMemberDataPointerInClassNTTP(
+    const CXXRecordDecl *RD, const ValueDecl *VD) {
+  MSInheritanceModel IM = RD->getMSInheritanceModel();
+  // <nttp-class-member-data-pointer> ::= <member-data-pointer>
+  //                                  ::= N
+  //                                  ::= 8 <mangled-name> <unqualified-name>
+
+  if (IM != MSInheritanceModel::Single && IM != MSInheritanceModel::Multiple)
+    return mangleMemberDataPointer(RD, VD, "");
+
+  if (!VD) {
+    Out << 'N';
+    return;
+  }
+
+  Out << '8';
+  mangleName(RD);
+  mangleUnqualifiedName(VD);
+  Out << '@';
+}
+
 void
 MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
                                                      const CXXMethodDecl *MD,
@@ -775,6 +800,34 @@
     mangleNumber(VBTableOffset);
 }
 
+void MicrosoftCXXNameMangler::mangleMemberFunctionPointerInClassNTTP(
+    const CXXRecordDecl *RD, const CXXMethodDecl *MD) {
+  // <nttp-class-member-function-pointer> ::= <member-function-pointer>
+  //                           ::= N
+  //                           ::= E? <virtual-mem-ptr-thunk>
+  //                           ::= E? <mangled-name> <type-encoding>
+
+  if (!MD) {
+    if (RD->getMSInheritanceModel() != MSInheritanceModel::Single)
+      return mangleMemberFunctionPointer(RD, MD, "");
+
+    Out << 'N';
+    return;
+  }
+
+  Out << "E?";
+  if (MD->isVirtual()) {
+    MicrosoftVTableContext *VTContext =
+        cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
+    MethodVFTableLocation ML =
+        VTContext->getMethodVFTableLocation(GlobalDecl(MD));
+    mangleVirtualMemPtrThunk(MD, ML);
+  } else {
+    mangleName(MD);
+    mangleFunctionEncoding(MD, /*ShouldMangle=*/true);
+  }
+}
+
 void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
     const CXXMethodDecl *MD, const MethodVFTableLocation &ML) {
   // Get the vftable offset.
@@ -1569,7 +1622,6 @@
   //                  ::= 8 <class> <unqualified-name> @
   //                  ::= A <type> <non-negative integer>  # float
   //                  ::= B <type> <non-negative integer>  # double
-  //                  ::= E <mangled-name>             # reference to D
   //                  # pointer to member, by component value
   //                  ::= F <number> <number>
   //                  ::= G <number> <number> <number>
@@ -1614,7 +1666,7 @@
       mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
                              TPO->getValue());
     } else {
-      mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
+      mangle(ND, "$1?");
     }
     break;
   }
@@ -1743,7 +1795,7 @@
         // FIXME: This can only happen as an extension. Invent a mangling.
         break;
       } else if (auto *VD = Base.dyn_cast<const ValueDecl*>()) {
-        Out << (T->isReferenceType() ? "E" : "1");
+        Out << "E";
         mangle(VD);
       } else {
         break;
@@ -1804,9 +1856,10 @@
         T->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
     const ValueDecl *D = V.getMemberPointerDecl();
     if (T->isMemberDataPointerType())
-      mangleMemberDataPointer(RD, D, "");
+      mangleMemberDataPointerInClassNTTP(RD, D);
     else
-      mangleMemberFunctionPointer(RD, cast_or_null<CXXMethodDecl>(D), "");
+      mangleMemberFunctionPointerInClassNTTP(RD,
+                                             cast_or_null<CXXMethodDecl>(D));
     return;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D146386:... Andrey Ali Khan Bolshakov via Phabricator via cfe-commits

Reply via email to