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);
+ }
+ };
+ };
+}