More __unknown_anytype work.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129269 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 92f1c63..e8b6f56 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -99,7 +99,8 @@
   return GetBogusMemberPointer(CGM, QualType(MPT, 0));
 }
 
-llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+                                            QualType unknownType) {
   return GetBogusMemberPointer(CGM,
                          CGM.getContext().getMemberPointerType(MD->getType(),
                                          MD->getParent()->getTypeForDecl()));
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index de4df3d..a34ca9b 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -119,7 +119,12 @@
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
   /// Create a member pointer for the given method.
-  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+  ///
+  /// \param unknownType - if non-null, use this type as the operand
+  ///   to CodeGenModule::getAddrOfUnknownAnyDecl instead of
+  ///   fetching the method's address in the normal way
+  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
+                                            QualType unknownType = QualType());
 
   /// Create a member pointer for the given field.
   virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index a35f81c..496c3fc 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1792,6 +1792,35 @@
   return MakeAddrLValue(phi, expr->getType());
 }
 
+static LValue emitUnknownAnyLValue(CodeGenFunction &CGF,
+                                   const Expr *operand,
+                                   QualType resolvedType) {
+  const ValueDecl *decl;
+  if (const DeclRefExpr *ref = dyn_cast<DeclRefExpr>(operand)) {
+    decl = ref->getDecl();
+  } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(operand)) {
+    decl = mem->getMemberDecl();
+
+    // Emit (and ignore) the base.
+    if (mem->isArrow())
+      CGF.EmitScalarExpr(mem->getBase());
+    else
+      CGF.EmitLValue(mem->getBase());
+  } else {
+    llvm_unreachable("unexpected operand of unknown-any resolution!");
+    decl = 0;
+  }
+  llvm::Value *addr = CGF.CGM.getAddrOfUnknownAnyDecl(decl, resolvedType);
+
+  QualType type = resolvedType;
+  if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
+    addr = CGF.Builder.CreateLoad(addr, "ref.value");
+    type = ref->getPointeeType();
+  }
+
+  return CGF.MakeAddrLValue(addr, type);
+}
+
 /// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
 /// If the cast is a dynamic_cast, we can have the usual lvalue result,
 /// otherwise if a cast is needed by the code generator in an lvalue context,
@@ -1930,11 +1959,12 @@
                                            ConvertType(ToType));
     return MakeAddrLValue(V, E->getType());
   }
-  case CK_ResolveUnknownAnyType: {
-    const DeclRefExpr *declRef = cast<DeclRefExpr>(E->getSubExpr());
-    llvm::Constant *addr = CGM.getAddrOfUnknownAnyDecl(declRef->getDecl(),
-                                                       E->getType());
-    return MakeAddrLValue(addr, E->getType());
+  case CK_ResolveUnknownAnyType:
+    return emitUnknownAnyLValue(*this, E->getSubExpr(), E->getType());
+  case CK_ResolveUnknownAnyTypeToReference: {
+    // l-value vs. r-value reference type shouldn't matter here.
+    QualType type = getContext().getLValueReferenceType(E->getType());
+    return emitUnknownAnyLValue(*this, E->getSubExpr(), type);
   }
   }
   
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 75e3a78..5d22fc3 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -311,6 +311,7 @@
     break;
 
   case CK_ResolveUnknownAnyType:
+  case CK_ResolveUnknownAnyTypeToReference:
     EmitAggLoadOfLValue(E);
     break;
       
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index a3d3f43..ef71e89 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -167,10 +167,12 @@
 // extensions allowing explicit constructor function call.
 RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
                                               ReturnValueSlot ReturnValue) {
-  if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens())) 
+  const Expr *callee = CE->getCallee()->IgnoreParens();
+
+  if (isa<BinaryOperator>(callee))
     return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
-      
-  const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
+
+  const MemberExpr *ME = cast<MemberExpr>(callee);
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
 
   CGDebugInfo *DI = getDebugInfo();
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 822a999..b04ff0a 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -553,6 +553,7 @@
     case CK_ToVoid:
     case CK_Dynamic:
     case CK_ResolveUnknownAnyType:
+    case CK_ResolveUnknownAnyTypeToReference:
       return 0;
 
     // These might need to be supported for constexpr.
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 65aa46f..f2ab0a2 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1128,6 +1128,19 @@
   }
 
   case CK_ResolveUnknownAnyType:
+    // Special case: resolving a member pointer constant.
+    if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(E)) {
+      DeclRefExpr *declRef = cast<DeclRefExpr>(uo->getSubExpr());
+      const CXXMethodDecl *method = cast<CXXMethodDecl>(declRef->getDecl());
+
+      const MemberPointerType *mpt = CE->getType()->castAs<MemberPointerType>();
+      QualType resolvedType = mpt->getPointeeType();
+
+      return CGF.CGM.getCXXABI().EmitMemberPointer(method, resolvedType);
+    }
+    // fallthrough
+
+  case CK_ResolveUnknownAnyTypeToReference:
     return EmitLoadOfLValue(CE);
       
   case CK_LValueToRValue:
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 53163ed..6c864ca 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -78,7 +78,8 @@
 
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
-  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
+                                    QualType unknownType);
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                         CharUnits offset);
 
@@ -502,7 +503,8 @@
   return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
 }
 
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+                                                 QualType unknownType) {
   assert(MD->isInstance() && "Member function must not be static!");
   MD = MD->getCanonicalDecl();
 
@@ -537,20 +539,27 @@
       MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
     }
   } else {
-    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-    const llvm::Type *Ty;
-    // Check whether the function has a computable LLVM signature.
-    if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
-      // The function has a computable LLVM signature; use the correct type.
-      Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+    llvm::Constant *addr;
+    if (!unknownType.isNull()) {
+      addr = CGM.getAddrOfUnknownAnyDecl(MD, unknownType);
     } else {
-      // Use an arbitrary non-function type to tell GetAddrOfFunction that the
-      // function type is incomplete.
-      Ty = ptrdiff_t;
+      QualType fnType = MD->getType();
+      const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
+      const llvm::Type *Ty;
+      // Check whether the function has a computable LLVM signature.
+      if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+        // The function has a computable LLVM signature; use the correct type.
+        Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
+                                   FPT->isVariadic());
+      } else {
+        // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+        // function type is incomplete.
+        Ty = ptrdiff_t;
+      }
+      addr = CGM.GetAddrOfFunction(MD, Ty);
     }
 
-    llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
-    MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+    MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
     MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
   }