Make yet another placeholder type, this one marking that an expression is a bound
member function, i.e. something of the form 'x.f' where 'f' is a non-static
member function.  Diagnose this in the general case.  Some of the new diagnostics
are probably worse than the old ones, but we now get this right much more
universally, and there's certainly room for improvement in the diagnostics.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130239 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 648011b..ed54f0f 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -160,10 +160,6 @@
   // FIXME: should we check this in a more fine-grained manner?
   bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
 
-  if (Ex.get()->isBoundMemberFunction(Context))
-    Diag(Ex.get()->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-      << Ex.get()->getSourceRange();
-
   ExprValueKind VK = VK_RValue;
   if (TypeDependent)
     VK = Expr::getValueKindForType(DestType);
@@ -305,6 +301,11 @@
 /// Diagnose a failed cast.
 static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
                             SourceRange opRange, Expr *src, QualType destType) {
+  if (src->getType() == S.Context.BoundMemberTy) {
+    (void) S.CheckPlaceholderExpr(src); // will always fail
+    return;
+  }
+
   if (msg == diag::err_bad_cxx_cast_generic &&
       tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
     return;
@@ -1540,12 +1541,6 @@
                          Expr *CastExpr, CastKind &Kind, 
                          CXXCastPath &BasePath,
                          bool FunctionalStyle) {
-  if (CastExpr->isBoundMemberFunction(Context)) {
-    Diag(CastExpr->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-        << CastExpr->getSourceRange();
-    return ExprError();
-  }
-
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -1557,6 +1552,9 @@
       return ExprError();
     CastExpr = CastExprRes.take();
 
+    if (CastExpr->getType() == Context.BoundMemberTy)
+      return CheckPlaceholderExpr(CastExpr); // will always fail
+
     if (CastExpr->getType() == Context.OverloadTy) {
       ExprResult SingleFunctionExpr = 
         ResolveAndFixSingleFunctionTemplateSpecialization(
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c90c513..212f584 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3934,12 +3934,20 @@
   }
 
   if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    ExprValueKind valueKind;
+    QualType type;
+    if (MemberFn->isInstance()) {
+      valueKind = VK_RValue;
+      type = Context.BoundMemberTy;
+    } else {
+      valueKind = VK_LValue;
+      type = MemberFn->getType();
+    }
+
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  MemberFn, FoundDecl, MemberNameInfo,
-                                 MemberFn->getType(),
-                                 MemberFn->isInstance() ? VK_RValue : VK_LValue,
-                                 OK_Ordinary));
+                                 type, valueKind, OK_Ordinary));
   }
   assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
 
@@ -4051,6 +4059,8 @@
         << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
         << FixItHint::CreateReplacement(OpLoc, ".");
       IsArrow = false;
+    } else if (BaseType == Context.BoundMemberTy) {
+      goto fail;
     } else {
       Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
         << BaseType << BaseExpr.get()->getSourceRange();
@@ -4424,6 +4434,16 @@
       }
     } else if ((Fun = BaseType->getAs<FunctionType>())) {
       TryCall = true;
+    } else if (BaseType == Context.BoundMemberTy) {
+      // Look for the bound-member type.  If it's still overloaded,
+      // give up, although we probably should have fallen into the
+      // OverloadExpr case above if we actually have an overloaded
+      // bound member.
+      QualType fnType = Expr::findBoundMemberType(BaseExpr.get());
+      if (!fnType.isNull()) {
+        TryCall = true;
+        Fun = fnType->castAs<FunctionType>();
+      }
     }
 
     if (TryCall) {
@@ -4858,91 +4878,33 @@
       Fn = result.take();
     }
 
-    Expr *NakedFn = Fn->IgnoreParens();
-
-    // Determine whether this is a call to an unresolved member function.
-    if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
-      // If lookup was unresolved but not dependent (i.e. didn't find
-      // an unresolved using declaration), it has to be an overloaded
-      // function set, which means it must contain either multiple
-      // declarations (all methods or method templates) or a single
-      // method template.
-      assert((MemE->getNumDecls() > 1) ||
-             isa<FunctionTemplateDecl>(
-                                 (*MemE->decls_begin())->getUnderlyingDecl()));
-      (void)MemE;
-
+    if (Fn->getType() == Context.BoundMemberTy) {
       return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                        RParenLoc);
     }
+  }
 
-    // Determine whether this is a call to a member function.
-    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
-      NamedDecl *MemDecl = MemExpr->getMemberDecl();
-      if (isa<CXXMethodDecl>(MemDecl))
+  // Check for overloaded calls.  This can happen even in C due to extensions.
+  if (Fn->getType() == Context.OverloadTy) {
+    OverloadExpr::FindResult find = OverloadExpr::find(Fn);
+
+    // We aren't supposed to apply this logic if there's an '&' involved.
+    if (!find.IsAddressOfOperand) {
+      OverloadExpr *ovl = find.Expression;
+      if (isa<UnresolvedLookupExpr>(ovl)) {
+        UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+        return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+                                       RParenLoc, ExecConfig);
+      } else {
         return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                          RParenLoc);
-    }
-
-    // Determine whether this is a call to a pointer-to-member function.
-    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
-      if (BO->getOpcode() == BO_PtrMemD ||
-          BO->getOpcode() == BO_PtrMemI) {
-        if (const FunctionProtoType *FPT
-                                = BO->getType()->getAs<FunctionProtoType>()) {
-          QualType ResultTy = FPT->getCallResultType(Context);
-          ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
-
-          // Check that the object type isn't more qualified than the
-          // member function we're calling.
-          Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals());
-          Qualifiers ObjectQuals 
-            = BO->getOpcode() == BO_PtrMemD
-                ? BO->getLHS()->getType().getQualifiers()
-                : BO->getLHS()->getType()->getAs<PointerType>()
-                                            ->getPointeeType().getQualifiers();
-
-          Qualifiers Difference = ObjectQuals - FuncQuals;
-          Difference.removeObjCGCAttr();
-          Difference.removeAddressSpace();
-          if (Difference) {
-            std::string QualsString = Difference.getAsString();
-            Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
-              << BO->getType().getUnqualifiedType()
-              << QualsString
-              << (QualsString.find(' ') == std::string::npos? 1 : 2);
-          }
-              
-          CXXMemberCallExpr *TheCall
-            = new (Context) CXXMemberCallExpr(Context, Fn, Args,
-                                              NumArgs, ResultTy, VK,
-                                              RParenLoc);
-
-          if (CheckCallReturnType(FPT->getResultType(),
-                                  BO->getRHS()->getSourceRange().getBegin(),
-                                  TheCall, 0))
-            return ExprError();
-
-          if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
-                                      RParenLoc))
-            return ExprError();
-
-          return MaybeBindToTemporary(TheCall);
-        }
       }
     }
   }
 
   // If we're directly calling a function, get the appropriate declaration.
-  // Also, in C++, keep track of whether we should perform argument-dependent
-  // lookup and whether there were any explicitly-specified template arguments.
 
   Expr *NakedFn = Fn->IgnoreParens();
-  if (isa<UnresolvedLookupExpr>(NakedFn)) {
-    UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
-    return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
-                                   RParenLoc, ExecConfig);
-  }
 
   NamedDecl *NDecl = 0;
   if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
@@ -4951,6 +4913,8 @@
   
   if (isa<DeclRefExpr>(NakedFn))
     NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+  else if (isa<MemberExpr>(NakedFn))
+    NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
 
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
                                ExecConfig);
@@ -8282,6 +8246,11 @@
     return S.Context.OverloadTy;
   if (OrigOp->getType() == S.Context.UnknownAnyTy)
     return S.Context.UnknownAnyTy;
+  if (OrigOp->getType() == S.Context.BoundMemberTy) {
+    S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+      << OrigOp->getSourceRange();
+    return QualType();
+  }
 
   assert(!OrigOp->getType()->isPlaceholderType());
 
@@ -10301,13 +10270,11 @@
   if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
     DiagnoseEqualityWithExtraParens(parenE);
 
-  if (!E->isTypeDependent()) {
-    if (E->isBoundMemberFunction(Context)) {
-      Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-        << E->getSourceRange();
-      return ExprError();
-    }
+  ExprResult result = CheckPlaceholderExpr(E);
+  if (result.isInvalid()) return ExprError();
+  E = result.take();
 
+  if (!E->isTypeDependent()) {
     if (getLangOptions().CPlusPlus)
       return CheckCXXBooleanCondition(E); // C++ 6.4p4
 
@@ -10728,6 +10695,13 @@
                                                              QualType(),
                                                    diag::err_ovl_unresolvable);
 
+  // Bound member functions.
+  if (type == Context.BoundMemberTy) {
+    Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+      << E->getSourceRange();
+    return ExprError();
+  }    
+
   // Expressions of unknown type.
   if (type == Context.UnknownAnyTy)
     return diagnoseUnknownAnyExpr(*this, E);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index edfa4a5..f8ad763 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2857,13 +2857,6 @@
   //   second operand.
   // The cv qualifiers are the union of those in the pointer and the left side,
   // in accordance with 5.5p5 and 5.2.5.
-  // FIXME: This returns a dereferenced member function pointer as a normal
-  // function type. However, the only operation valid on such functions is
-  // calling them. There's also a GCC extension to get a function pointer to the
-  // thing, which is another complication, because this type - unlike the type
-  // that is the result of this expression - takes the class as the first
-  // argument.
-  // We probably need a "MemberFunctionClosureType" or something like that.
   QualType Result = MemPtr->getPointeeType();
   Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
 
@@ -2900,12 +2893,14 @@
   //   operand is a pointer to a member function is a prvalue. The
   //   result of an ->* expression is an lvalue if its second operand
   //   is a pointer to data member and a prvalue otherwise.
-  if (Result->isFunctionType())
+  if (Result->isFunctionType()) {
     VK = VK_RValue;
-  else if (isIndirect)
+    return Context.BoundMemberTy;
+  } else if (isIndirect) {
     VK = VK_LValue;
-  else
+  } else {
     VK = lex.get()->getValueKind();
+  }
 
   return Result;
 }
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 06c097c..6e6bf22 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3623,8 +3623,8 @@
     return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
 
   if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
-    return  Diag(From->getSourceRange().getBegin(),
-                 diag::err_typecheck_bool_condition)
+    return Diag(From->getSourceRange().getBegin(),
+                diag::err_typecheck_bool_condition)
                   << From->getType() << From->getSourceRange();
   return ExprError();
 }
@@ -7202,7 +7202,7 @@
     if (!TargetFunctionType->isFunctionType()) {        
       if (OvlExpr->hasExplicitTemplateArgs()) {
         DeclAccessPair dap;
-        if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+        if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
                                             OvlExpr, false, &dap) ) {
 
           if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
@@ -7502,32 +7502,29 @@
 /// template, where that template-id refers to a single template whose template
 /// arguments are either provided by the template-id or have defaults,
 /// as described in C++0x [temp.arg.explicit]p3.
-FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, 
-                                                                bool Complain,
-                                                  DeclAccessPair* FoundResult) {
+FunctionDecl *
+Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, 
+                                                  bool Complain,
+                                                  DeclAccessPair *FoundResult) {
   // C++ [over.over]p1:
   //   [...] [Note: any redundant set of parentheses surrounding the
   //   overloaded function name is ignored (5.1). ]
   // C++ [over.over]p1:
   //   [...] The overloaded function name can be preceded by the &
   //   operator.
-  if (From->getType() != Context.OverloadTy)
-    return 0;
-
-  OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
 
   // If we didn't actually find any template-ids, we're done.
-  if (!OvlExpr->hasExplicitTemplateArgs())
+  if (!ovl->hasExplicitTemplateArgs())
     return 0;
 
   TemplateArgumentListInfo ExplicitTemplateArgs;
-  OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+  ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
 
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
   FunctionDecl *Matched = 0;
-  for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
-         E = OvlExpr->decls_end(); I != E; ++I) {
+  for (UnresolvedSetIterator I = ovl->decls_begin(),
+         E = ovl->decls_end(); I != E; ++I) {
     // C++0x [temp.arg.explicit]p3:
     //   [...] In contexts where deduction is done and fails, or in contexts
     //   where deduction is not done, if a template argument list is
@@ -7544,7 +7541,7 @@
     //   function template specialization, which is added to the set of
     //   overloaded functions considered.
     FunctionDecl *Specialization = 0;
-    TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+    TemplateDeductionInfo Info(Context, ovl->getNameLoc());
     if (TemplateDeductionResult Result
           = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
                                     Specialization, Info)) {
@@ -7553,21 +7550,20 @@
       continue;
     }
 
+    assert(Specialization && "no specialization and no error?");
+
     // Multiple matches; we can't resolve to a single declaration.
     if (Matched) {
-      if (FoundResult) 
-          *FoundResult = DeclAccessPair();
-      
       if (Complain) {
-        Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
-          << OvlExpr->getName();
-        NoteAllOverloadCandidates(OvlExpr);
+        Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
+          << ovl->getName();
+        NoteAllOverloadCandidates(ovl);
       }
       return 0;
-    }   
+    }
     
-    if ((Matched = Specialization) && FoundResult) 
-      *FoundResult = I.getPair();    
+    Matched = Specialization;
+    if (FoundResult) *FoundResult = I.getPair();    
   }
 
   return Matched;
@@ -7581,39 +7577,65 @@
 // template specialization
 // Last three arguments should only be supplied if Complain = true
 ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
-             Expr *SrcExpr, bool DoFunctionPointerConverion, bool Complain,
+             Expr *SrcExpr, bool doFunctionPointerConverion, bool complain,
                                   const SourceRange& OpRangeForComplaining, 
                                            QualType DestTypeForComplaining, 
-                                            unsigned DiagIDForComplaining ) {
+                                            unsigned DiagIDForComplaining) {
+  assert(SrcExpr->getType() == Context.OverloadTy);
 
-    assert(SrcExpr->getType() == Context.OverloadTy);
+  OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr);
 
-    DeclAccessPair Found;
-    ExprResult SingleFunctionExpression;
-    if (FunctionDecl* Fn = ResolveSingleFunctionTemplateSpecialization(
-      SrcExpr, false, // false -> Complain 
-      &Found)) {
-        if (!DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
-          // mark the expression as resolved to Fn
-          SingleFunctionExpression = Owned(FixOverloadedFunctionReference(SrcExpr, 
-            Found, Fn));
-          if (DoFunctionPointerConverion)
-            SingleFunctionExpression =
-              DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
-        }      
-    }
-    if (!SingleFunctionExpression.isUsable()) {
-      if (Complain) {
-        OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
-        Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
-          << oe->getName() << DestTypeForComplaining << OpRangeForComplaining 
-          << oe->getQualifierLoc().getSourceRange();
-        NoteAllOverloadCandidates(SrcExpr);
-      }      
+  DeclAccessPair found;
+  ExprResult SingleFunctionExpression;
+  if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+                           ovl.Expression, /*complain*/ false, &found)) {
+    if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin()))
+      return ExprError();
+
+    // It is only correct to resolve to an instance method if we're
+    // resolving a form that's permitted to be a pointer to member.
+    // Otherwise we'll end up making a bound member expression, which
+    // is illegal in all the contexts we resolve like this.
+    if (!ovl.HasFormOfMemberPointer &&
+        isa<CXXMethodDecl>(fn) &&
+        cast<CXXMethodDecl>(fn)->isInstance()) {
+      if (complain) {
+        Diag(ovl.Expression->getExprLoc(),
+             diag::err_invalid_use_of_bound_member_func)
+          << ovl.Expression->getSourceRange();
+        // TODO: I believe we only end up here if there's a mix of
+        // static and non-static candidates (otherwise the expression
+        // would have 'bound member' type, not 'overload' type).
+        // Ideally we would note which candidate was chosen and why
+        // the static candidates were rejected.
+      }
+      
       return ExprError();
     }
 
-    return SingleFunctionExpression;
+    // Fix the expresion to refer to 'fn'.
+    SingleFunctionExpression =
+      Owned(FixOverloadedFunctionReference(SrcExpr, found, fn));
+
+    // If desired, do function-to-pointer decay.
+    if (doFunctionPointerConverion)
+      SingleFunctionExpression =
+        DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+  }
+
+  if (!SingleFunctionExpression.isUsable()) {
+    if (complain) {
+      Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+        << ovl.Expression->getName()
+        << DestTypeForComplaining
+        << OpRangeForComplaining 
+        << ovl.Expression->getQualifierLoc().getSourceRange();
+      NoteAllOverloadCandidates(SrcExpr);
+    }      
+    return ExprError();
+  }
+
+  return SingleFunctionExpression;
 }
 
 /// \brief Add a single candidate to the overload set.
@@ -8499,16 +8521,66 @@
 /// function (and includes the object parameter), Args/NumArgs are the
 /// arguments to the function call (not including the object
 /// parameter). The caller needs to validate that the member
-/// expression refers to a member function or an overloaded member
-/// function.
+/// expression refers to a non-static member function or an overloaded
+/// member function.
 ExprResult
 Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
                                 SourceLocation LParenLoc, Expr **Args,
                                 unsigned NumArgs, SourceLocation RParenLoc) {
+  assert(MemExprE->getType() == Context.BoundMemberTy ||
+         MemExprE->getType() == Context.OverloadTy);
+
   // Dig out the member expression. This holds both the object
   // argument and the member function we're referring to.
   Expr *NakedMemExpr = MemExprE->IgnoreParens();
 
+  // Determine whether this is a call to a pointer-to-member function.
+  if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
+    assert(op->getType() == Context.BoundMemberTy);
+    assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
+
+    QualType fnType =
+      op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
+
+    const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
+    QualType resultType = proto->getCallResultType(Context);
+    ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+
+    // Check that the object type isn't more qualified than the
+    // member function we're calling.
+    Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+
+    QualType objectType = op->getLHS()->getType();
+    if (op->getOpcode() == BO_PtrMemI)
+      objectType = objectType->castAs<PointerType>()->getPointeeType();
+    Qualifiers objectQuals = objectType.getQualifiers();
+
+    Qualifiers difference = objectQuals - funcQuals;
+    difference.removeObjCGCAttr();
+    difference.removeAddressSpace();
+    if (difference) {
+      std::string qualsString = difference.getAsString();
+      Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+        << fnType.getUnqualifiedType()
+        << qualsString
+        << (qualsString.find(' ') == std::string::npos ? 1 : 2);
+    }
+              
+    CXXMemberCallExpr *call
+      = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+                                        resultType, valueKind, RParenLoc);
+
+    if (CheckCallReturnType(proto->getResultType(),
+                            op->getRHS()->getSourceRange().getBegin(),
+                            call, 0))
+      return ExprError();
+
+    if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+      return ExprError();
+
+    return MaybeBindToTemporary(call);
+  }
+
   MemberExpr *MemExpr;
   CXXMethodDecl *Method = 0;
   DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e6609c0..5e21a36 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -77,12 +77,6 @@
   if (!E)
     return;
 
-  if (E->isBoundMemberFunction(Context)) {
-    Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-      << E->getSourceRange();
-    return;
-  }
-
   SourceLocation Loc;
   SourceRange R1, R2;
   if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))