• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
test()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 
test()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 
test0test2::A68     void test0() {
69       Unrelated::foo(); // expected-error {{call to non-static member function without an object argument}}
70     }
71 
test1test2::A72     void test1() {
73       B<T>::foo();
74     }
75 
test2test2::A76     static void test2() {
77       B<T>::foo(); // expected-error {{call to non-static member function without an object argument}}
78     }
79 
test3test2::A80     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 
test()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