summaryrefslogtreecommitdiff
path: root/clang/test/CXX/class/class.mfct
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/class/class.mfct')
-rw-r--r--clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
new file mode 100644
index 0000000..9116e71
--- /dev/null
+++ b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
@@ -0,0 +1,98 @@
+// 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}}
+ }
+}