]> granicus.if.org Git - clang/commitdiff
[MS ABI] nullptr data member ptrs are mangled differently for classes vs fns
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 2 Jul 2015 09:43:11 +0000 (09:43 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 2 Jul 2015 09:43:11 +0000 (09:43 +0000)
It turns out that nullptr pointers to data members act differently in
function templates vs class templates.  Class templates use a variable
width representation proportional to the number of fields needed to
materialize it.  Function templates always use a single '0' template
parameter.  However, using '0' all the time is problematic if the class
uses single or multiple inheritance.  In those cases, use -1.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241251 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/MicrosoftMangle.cpp
test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
test/CodeGenCXX/mangle-ms-templates-memptrs.cpp

index c50db60abe5a055252cd2b96ef522a8405f24513..48a8fa541a69a3e272e9bc64852a94eeb9d62574 100644 (file)
@@ -1215,11 +1215,23 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
         return;
       }
       if (MPT->isMemberDataPointer()) {
-        mangleMemberDataPointer(RD, nullptr);
-        return;
+        if (isa<ClassTemplateDecl>(TD)) {
+          mangleMemberDataPointer(RD, nullptr);
+          return;
+        }
+        // nullptr data pointers are always represented with a single field
+        // which is initialized with either 0 or -1.  Why -1?  Well, we need to
+        // distinguish the case where the data member is at offset zero in the
+        // record.
+        // However, we are free to use 0 *if* we would use multiple fields for
+        // non-nullptr member pointers.
+        if (!RD->nullFieldOffsetIsZero()) {
+          mangleIntegerLiteral(llvm::APSInt::get(-1), /*IsBoolean=*/false);
+          return;
+        }
       }
     }
-    Out << "$0A@";
+    mangleIntegerLiteral(llvm::APSInt::getUnsigned(0), /*IsBoolean=*/false);
     break;
   }
   case TemplateArgument::Expression:
index e2cbe15dfa9ff9a4aeaab26db2977eebcf25e1e8..b01d6099d8f766e5dd801173c055228b65ed0889 100644 (file)
@@ -3,22 +3,37 @@
 template <typename T, int (T::*)() = nullptr>
 struct J {};
 
+template <typename T, int T::* = nullptr>
+struct K {};
+
 struct __single_inheritance M;
 J<M> m;
 // CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A"
 
+K<M> m2;
+// CHECK-DAG: @"\01?m2@@3U?$K@UM@@$0?0@@A"
+
 struct __multiple_inheritance N;
 J<N> n;
 // CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A"
 
+K<N> n2;
+// CHECK-DAG: @"\01?n2@@3U?$K@UN@@$0?0@@A"
+
 struct __virtual_inheritance O;
 J<O> o;
 // CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A"
 
+K<O> o2;
+// CHECK-DAG: @"\01?o2@@3U?$K@UO@@$FA@?0@@A"
+
 struct P;
 J<P> p;
 // CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A"
 
+K<P> p2;
+// CHECK-DAG: @"\01?p2@@3U?$K@UP@@$GA@A@?0@@A"
+
 #pragma pointers_to_members(full_generality, virtual_inheritance)
 
 struct S {
index 42237f5b7d4a418bd94164bb15928ef9032b743d..e710abe97e985f91e99448faec3272a5409d29fe 100644 (file)
@@ -69,8 +69,8 @@ void ReadFields() {
 // them right in class templates.
 // CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
 // CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FA@?0@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$GA@A@?0@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UV@@$0A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UU@@$0A@@@YAHAAUU@@@Z"
 
 // Non-polymorphic null data memptr vs first field memptr.  MSVC mangles these
 // the same.