From 9af604c260f93a93a44c5a34362b1a0ba6236cad Mon Sep 17 00:00:00 2001
From: David Majnemer <david.majnemer@gmail.com>
Date: Fri, 12 Jun 2015 17:55:44 +0000
Subject: [PATCH] [MS ABI] Lock-in the derived memptr rep. for base-to-derived
 conversions

We would get this right in the case where an explicit cast was formed
but not when we were performing an implicit conversion.

This fixes PR23828.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@239625 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaExprCXX.cpp                          |  8 ++++----
 test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 11 +++++++++++
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ef72097e935..6c839f356fd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -3290,10 +3290,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
 
     // We may not have been able to figure out what this member pointer resolved
     // to up until this exact point.  Attempt to lock-in it's inheritance model.
-    QualType FromType = From->getType();
-    if (FromType->isMemberPointerType())
-      if (Context.getTargetInfo().getCXXABI().isMicrosoft())
-        RequireCompleteType(From->getExprLoc(), FromType, 0);
+    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+      RequireCompleteType(From->getExprLoc(), From->getType(), 0);
+      RequireCompleteType(From->getExprLoc(), ToType, 0);
+    }
 
     From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
              .get();
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index c12ceae131a..cf9da81ea28 100644
--- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -678,6 +678,17 @@ static_assert(sizeof(int A::*) == 12, "");
 // CHECK-LABEL: define void @"\01?test@pr20007_pragma2@@YAXXZ"
 }
 
+namespace pr23823 {
+struct Base { void Method(); };
+struct Child : Base {};
+void use(void (Child::*const &)());
+void f() { use(&Child::Method); }
+#pragma pointers_to_members(full_generality, virtual_inheritance)
+static_assert(sizeof(int Base::*) == 4, "");
+static_assert(sizeof(int Child::*) == 4, "");
+#pragma pointers_to_members(best_case)
+}
+
 namespace pr19987 {
 template <typename T>
 struct S {
-- 
GitLab