// RUN: %clang_cc1 -fsyntax-only -verify %s
// [class.mfct.non-static]p3:
// When an id-expression (5.1) that is not part of a class member
// access syntax (5.2.5) and not used to form a pointer to member
// (5.3.1) is used in the body of a non-static member function of
// class X, if name lookup (3.4.1) resolves the name in the
// id-expression to a non-static non-type member of some class C,
// the id-expression is transformed into a class member access
// expression (5.2.5) using (*this) (9.3.2) as the
// postfix-expression to the left of the . operator. [ Note: if C is
// not X or a base class of X, the class member access expression is
// ill-formed. --end note] Similarly during name lookup, when an
// unqualified-id (5.1) used in the definition of a member function
// for class X resolves to a static member, an enumerator or a
// nested type of class X or of a base class of X, the
// unqualified-id is transformed into a qualified-id (5.1) in which
// the nested-name-specifier names the class of the member function.
namespace test0 {
class A {
int data_member;
int instance_method();
static int static_method();
bool test() {
return data_member + instance_method() < static_method();
}
};
}
namespace test1 {
struct Opaque1 {}; struct Opaque2 {}; struct Opaque3 {};
struct A {
void foo(Opaque1); // expected-note {{candidate}}
void foo(Opaque2); // expected-note {{candidate}}
};
struct B : A {
void test();
};
struct C1 : A { };
struct C2 : B { };
void B::test() {
A::foo(Opaque1());
A::foo(Opaque2());
A::foo(Opaque3()); // expected-error {{no matching member function}}
C1::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}}
C2::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}}
}
}
namespace test2 {
struct Unrelated {
void foo();
};
template <class T> struct B;
template <class T> struct C;
template <class T> struct A {
void foo();
void test0() {
Unrelated::foo(); // expected-error {{call to non-static member function without an object argument}}
}
void test1() {
B<T>::foo();
}
static void test2() {
B<T>::foo(); // expected-error {{call to non-static member function without an object argument}}
}
void test3() {
C<T>::foo(); // expected-error {{no member named 'foo'}}
}
};
template <class T> struct B : A<T> {
};
template <class T> struct C {
};
int test() {
A<int> a;
a.test0(); // no instantiation note here, decl is ill-formed
a.test1();
a.test2(); // expected-note {{in instantiation}}
a.test3(); // expected-note {{in instantiation}}
}
}