1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
// 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(); // expected-error {{call to non-static member function without an object argument}}
}
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(); // expected-note {{in instantiation}}
a.test2(); // expected-note {{in instantiation}}
a.test3(); // expected-note {{in instantiation}}
}
}
namespace test3 {
struct A {
void f0();
template<typename T>
void f1();
static void f2();
template<typename T>
static void f3();
int x0;
static constexpr int x1 = 0;
template<typename T>
static constexpr int x2 = 0;
};
template<typename T>
struct B : T {
auto g0() -> decltype(T::f0());
auto g1() -> decltype(T::template f1<int>());
auto g2() -> decltype(T::f2());
auto g3() -> decltype(T::template f3<int>());
auto g4() -> decltype(T::x0);
auto g5() -> decltype(T::x1);
auto g6() -> decltype(T::template x2<int>);
decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}}
decltype(T::template f1<int>()) g8(); // expected-error {{call to non-static member function without an object argument}}
decltype(T::f2()) g9();
decltype(T::template f3<int>()) g10();
decltype(T::x0) g11();
decltype(T::x1) g12();
decltype(T::template x2<int>) g13();
};
template struct B<A>; // expected-note {{in instantiation of}}
template<typename T>
struct C : T {
static auto g0() -> decltype(T::f0()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}}
static auto g1() -> decltype(T::template f1<int>()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}}
static auto g2() -> decltype(T::f2());
static auto g3() -> decltype(T::template f3<int>());
static auto g4() -> decltype(T::x0); // expected-error {{'this' cannot be implicitly used in a static member function declaration}}
static auto g5() -> decltype(T::x1);
static auto g6() -> decltype(T::template x2<int>);
static decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}}
static decltype(T::template f1<int>()) g8(); // expected-error {{call to non-static member function without an object argument}}
static decltype(T::f2()) g9();
static decltype(T::template f3<int>()) g10();
static decltype(T::x0) g11();
static decltype(T::x1) g12();
static decltype(T::template x2<int>) g13();
};
template struct C<A>; // expected-note {{in instantiation of}}
}
|