Propagate whether an id-expression is the immediate argument of
an '&' expression from the second caller of ActOnIdExpression.

Teach template argument deduction that an overloaded id-expression
doesn't give a valid type for deduction purposes to a non-static
member function unless the expression has the correct syntactic
form.

Teach ActOnIdExpression that it shouldn't try to create implicit
member expressions for '&function', because this isn't a        
permitted form of use for member functions.

Teach CheckAddressOfOperand to diagnose these more carefully.
Some of these cases aren't reachable right now because earlier
diagnostics interrupt them.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112258 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index 9d5cd2f..83823f6 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -79,7 +79,7 @@
 
   void (HasMembers::*pmf)() = &HasMembers::f;
   void (*pnf)() = &Fake::f;
-  &hm.f; // expected-error {{must explicitly qualify}} expected-warning{{result unused}}
+  &hm.f; // expected-error {{cannot create a non-constant pointer to member function}}
 
   void (HasMembers::*pmgv)() = &HasMembers::g;
   void (HasMembers::*pmgi)(int) = &HasMembers::g;
@@ -142,8 +142,8 @@
     void f() {
       void (c::*p)();
       p = &h; // expected-error {{must explicitly qualify}}
-      p = &this->h; // expected-error {{must explicitly qualify}}
-      p = &(*this).h; // expected-error {{must explicitly qualify}}
+      p = &this->h; // expected-error {{cannot create a non-constant pointer to member function}}
+      p = &(*this).h; // expected-error {{cannot create a non-constant pointer to member function}}
     }
   };
 }
@@ -174,3 +174,64 @@
   void m()
   { (void)(Condition) &base::Continuous::cond; }
 }
+
+namespace rdar8358512 {
+  // We can't call this with an overload set because we're not allowed
+  // to look into overload sets unless the parameter has some kind of
+  // function type.
+  template <class F> void bind(F f); // expected-note 6 {{candidate template ignored}}
+  template <class F, class T> void bindmem(F (T::*f)()); // expected-note 4 {{candidate template ignored}}
+  template <class F> void bindfn(F (*f)()); // expected-note 4 {{candidate template ignored}}
+
+  struct A {
+    void member();
+
+    void nonstat();
+    void nonstat(int);
+
+    void mixed();
+    static void mixed(int);
+
+    static void stat();
+    static void stat(int);
+    
+    template <typename T> struct Test0 {
+      void test() {
+        bind(&nonstat); // expected-error {{no matching function for call}}
+        bind(&A::nonstat); // expected-error {{no matching function for call}}
+
+        bind(&mixed); // expected-error {{no matching function for call}}
+        bind(&A::mixed); // expected-error {{no matching function for call}}
+
+        bind(&stat); // expected-error {{no matching function for call}}
+        bind(&A::stat); // expected-error {{no matching function for call}}
+      }
+    };
+
+    template <typename T> struct Test1 {
+      void test() {
+        bindmem(&nonstat); // expected-error {{no matching function for call}}
+        bindmem(&A::nonstat);
+
+        bindmem(&mixed); // expected-error {{no matching function for call}}
+        bindmem(&A::mixed);
+
+        bindmem(&stat); // expected-error {{no matching function for call}}
+        bindmem(&A::stat); // expected-error {{no matching function for call}}
+      }
+    };
+
+    template <typename T> struct Test2 {
+      void test() {
+        bindfn(&nonstat); // expected-error {{no matching function for call}}
+        bindfn(&A::nonstat); // expected-error {{no matching function for call}}
+
+        bindfn(&mixed); // expected-error {{no matching function for call}}
+        bindfn(&A::mixed); // expected-error {{no matching function for call}}
+
+        bindfn(&stat);
+        bindfn(&A::stat);
+      }
+    };
+  };
+}