1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | |
3 | // [class.mfct.non-static]p3: |
4 | // When an id-expression (5.1) that is not part of a class member |
5 | // access syntax (5.2.5) and not used to form a pointer to member |
6 | // (5.3.1) is used in the body of a non-static member function of |
7 | // class X, if name lookup (3.4.1) resolves the name in the |
8 | // id-expression to a non-static non-type member of some class C, |
9 | // the id-expression is transformed into a class member access |
10 | // expression (5.2.5) using (*this) (9.3.2) as the |
11 | // postfix-expression to the left of the . operator. [ Note: if C is |
12 | // not X or a base class of X, the class member access expression is |
13 | // ill-formed. --end note] Similarly during name lookup, when an |
14 | // unqualified-id (5.1) used in the definition of a member function |
15 | // for class X resolves to a static member, an enumerator or a |
16 | // nested type of class X or of a base class of X, the |
17 | // unqualified-id is transformed into a qualified-id (5.1) in which |
18 | // the nested-name-specifier names the class of the member function. |
19 | |
20 | namespace test0 { |
21 | class A { |
22 | int data_member; |
23 | int instance_method(); |
24 | static int static_method(); |
25 | |
26 | bool test() { |
27 | return data_member + instance_method() < static_method(); |
28 | } |
29 | }; |
30 | } |
31 | |
32 | namespace test1 { |
33 | struct Opaque1 {}; struct Opaque2 {}; struct Opaque3 {}; |
34 | |
35 | struct A { |
36 | void foo(Opaque1); // expected-note {{candidate}} |
37 | void foo(Opaque2); // expected-note {{candidate}} |
38 | }; |
39 | |
40 | struct B : A { |
41 | void test(); |
42 | }; |
43 | |
44 | struct C1 : A { }; |
45 | struct C2 : B { }; |
46 | |
47 | void B::test() { |
48 | A::foo(Opaque1()); |
49 | A::foo(Opaque2()); |
50 | A::foo(Opaque3()); // expected-error {{no matching member function}} |
51 | |
52 | C1::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} |
53 | C2::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} |
54 | } |
55 | } |
56 | |
57 | namespace test2 { |
58 | struct Unrelated { |
59 | void foo(); |
60 | }; |
61 | |
62 | template <class T> struct B; |
63 | template <class T> struct C; |
64 | |
65 | template <class T> struct A { |
66 | void foo(); |
67 | |
68 | void test0() { |
69 | Unrelated::foo(); // expected-error {{call to non-static member function without an object argument}} |
70 | } |
71 | |
72 | void test1() { |
73 | B<T>::foo(); |
74 | } |
75 | |
76 | static void test2() { |
77 | B<T>::foo(); // expected-error {{call to non-static member function without an object argument}} |
78 | } |
79 | |
80 | void test3() { |
81 | C<T>::foo(); // expected-error {{no member named 'foo'}} |
82 | } |
83 | }; |
84 | |
85 | template <class T> struct B : A<T> { |
86 | }; |
87 | |
88 | template <class T> struct C { |
89 | }; |
90 | |
91 | int test() { |
92 | A<int> a; |
93 | a.test0(); // no instantiation note here, decl is ill-formed |
94 | a.test1(); |
95 | a.test2(); // expected-note {{in instantiation}} |
96 | a.test3(); // expected-note {{in instantiation}} |
97 | } |
98 | } |
99 | |