]> granicus.if.org Git - clang/commitdiff
Classify bound member function types are member function types. Fixes
authorDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 21:04:55 +0000 (21:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 21:04:55 +0000 (21:04 +0000)
PR9973 / <rdar://problem/9479191>.

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

lib/AST/ExprClassification.cpp
test/SemaCXX/member-pointer.cpp

index 888a93c8aac0817ebc6b354a9358a6896fb4300d..7e4d06ac3070558cfb0e6c0740acd22b5ad9af55 100644 (file)
@@ -465,14 +465,16 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
   //   is a pointer to a data member is of the same value category as its first
   //   operand.
   if (E->getOpcode() == BO_PtrMemD)
-    return E->getType()->isFunctionType() ? Cl::CL_MemberFunction :
-      ClassifyInternal(Ctx, E->getLHS());
+    return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy)
+             ? Cl::CL_MemberFunction 
+             : ClassifyInternal(Ctx, E->getLHS());
 
   // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
   //   second operand is a pointer to data member and a prvalue otherwise.
   if (E->getOpcode() == BO_PtrMemI)
-    return E->getType()->isFunctionType() ?
-      Cl::CL_MemberFunction : Cl::CL_LValue;
+    return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy)
+             ? Cl::CL_MemberFunction 
+             : Cl::CL_LValue;
 
   // All other binary operations are prvalues.
   return Cl::CL_PRValue;
index 31c651a4ad5d6e527a5ed4d8298b6e3577225b68..de3b211acf50076f509e857a1c82eaa4c37933c0 100644 (file)
@@ -271,3 +271,28 @@ namespace rdar8358512 {
 
   template void B<int>::test0b(); // expected-note {{in instantiation}}
 }
+
+namespace PR9973 {
+  template<class R, class T> struct dm
+  {
+    typedef R T::*F;
+    F f_;
+    template<class U> int & call(U u)
+    { return u->*f_; } // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type '<bound member function type>'}}
+
+    template<class U> int operator()(U u)
+    { call(u); } // expected-note{{in instantiation of}}
+  };
+
+  template<class R, class T> 
+  dm<R, T> mem_fn(R T::*) ;
+
+  struct test
+  { int nullary_v(); };
+
+  void f()
+  {
+    test* t;
+    mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}}
+  }
+}