366 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
 | |
| 
 | |
| friend class A; // expected-error {{'friend' used outside of class}}
 | |
| void f() { friend class A; } // expected-error {{'friend' used outside of class}}
 | |
| class C { friend class A; };
 | |
| class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}}
 | |
| 
 | |
| // PR5760
 | |
| namespace test0 {
 | |
|   namespace ns {
 | |
|     void f(int);
 | |
|   }
 | |
| 
 | |
|   struct A {
 | |
|     friend void ns::f(int a);
 | |
|   };
 | |
| }
 | |
| 
 | |
| // Test derived from LLVM's Registry.h
 | |
| namespace test1 {
 | |
|   template <class T> struct Outer {
 | |
|     void foo(T);
 | |
|     struct Inner {
 | |
|       friend void Outer::foo(T);
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   void test() {
 | |
|     (void) Outer<int>::Inner();
 | |
|   }
 | |
| }
 | |
| 
 | |
| // PR5476
 | |
| namespace test2 {
 | |
|   namespace foo {
 | |
|     void Func(int x);
 | |
|   }
 | |
| 
 | |
|   class Bar {
 | |
|     friend void ::test2::foo::Func(int x);
 | |
|   };
 | |
| }
 | |
| 
 | |
| // PR5134
 | |
| namespace test3 {
 | |
|   class Foo {
 | |
|     friend const int getInt(int inInt = 0) {}
 | |
| 
 | |
|   };
 | |
| }
 | |
| 
 | |
| namespace test4 {
 | |
|   class T4A {
 | |
|     friend class T4B;
 | |
|   
 | |
|   public:
 | |
|     T4A(class T4B *);
 | |
| 
 | |
|   protected:
 | |
|     T4B *mB;          // error here
 | |
|   };
 | |
|  
 | |
|   class T4B {};
 | |
| }
 | |
| 
 | |
| namespace rdar8529993 {
 | |
| struct A { ~A(); };
 | |
| 
 | |
| struct B : A
 | |
| {
 | |
|   template<int> friend A::~A(); // expected-error {{destructor cannot be declared as a template}}
 | |
| };
 | |
| }
 | |
| 
 | |
| // PR7915
 | |
| namespace test5 {
 | |
|   struct A;
 | |
|   struct A1 { friend void A(); };
 | |
| 
 | |
|   struct B { friend void B(); };
 | |
| }
 | |
| 
 | |
| // PR8479
 | |
| namespace test6_1 {
 | |
|   class A {
 | |
|    public:
 | |
|    private:
 | |
|     friend class vectorA;
 | |
|     A() {}
 | |
|   };
 | |
|   class vectorA {
 | |
|    public:
 | |
|     vectorA(int i, const A& t = A()) {}
 | |
|   };
 | |
|   void f() {
 | |
|     vectorA v(1);
 | |
|   }
 | |
| }
 | |
| namespace test6_2 {
 | |
|   template<class T>
 | |
|   class vector {
 | |
|    public:
 | |
|     vector(int i, const T& t = T()) {}
 | |
|   };
 | |
|   class A {
 | |
|    public:
 | |
|    private:
 | |
|     friend class vector<A>;
 | |
|     A() {}
 | |
|   };
 | |
|   void f() {
 | |
|     vector<A> v(1);
 | |
|   }
 | |
| }
 | |
| namespace test6_3 {
 | |
|   template<class T>
 | |
|   class vector {
 | |
|    public:
 | |
|     vector(int i) {}
 | |
|     void f(const T& t = T()) {}
 | |
|   };
 | |
|   class A {
 | |
|    public:
 | |
|    private:
 | |
|     friend void vector<A>::f(const A&);
 | |
|     A() {}
 | |
|   };
 | |
|   void f() {
 | |
|     vector<A> v(1);
 | |
|     v.f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace test7 {
 | |
|   extern "C" {
 | |
|     class X {
 | |
|       friend int test7_f() { return 42; }
 | |
|     };
 | |
|   }
 | |
| }
 | |
| 
 | |
| // PR15485
 | |
| namespace test8 {
 | |
|   namespace ns1 {
 | |
|     namespace ns2 {
 | |
|       template<class T> void f(T t); // expected-note {{target of using declaration}}
 | |
|     }
 | |
|     using ns2::f; // expected-note {{using declaration}}
 | |
|   }
 | |
|   struct A { void f(); }; // expected-note {{target of using declaration}}
 | |
|   struct B : public A { using A::f; }; // expected-note {{using declaration}}
 | |
|   struct X {
 | |
|     template<class T> friend void ns1::f(T t); // expected-error {{cannot befriend target of using declaration}}
 | |
|     friend void B::f(); // expected-error {{cannot befriend target of using declaration}}
 | |
|   };
 | |
| }
 | |
| 
 | |
| // PR16423
 | |
| namespace test9 {
 | |
|   class C {
 | |
|   };
 | |
|   struct A {
 | |
|     friend void C::f(int, int, int) {}  // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}}
 | |
|   };
 | |
| }
 | |
| 
 | |
| namespace test10 {
 | |
|   struct X {};
 | |
|   extern void f10_a();
 | |
|   extern void f10_a(X);
 | |
|   struct A {
 | |
|     friend void f10_a();
 | |
|     friend void f10_b();
 | |
|     friend void f10_c();
 | |
|     friend void f10_d();
 | |
|     friend void f10_a(X);
 | |
|     friend void f10_b(X);
 | |
|     friend void f10_c(X);
 | |
|     friend void f10_d(X);
 | |
|   };
 | |
|   extern void f10_b();
 | |
|   extern void f10_b(X);
 | |
|   struct B {
 | |
|     friend void f10_a();
 | |
|     friend void f10_b();
 | |
|     friend void f10_c();
 | |
|     friend void f10_d();
 | |
|     friend void f10_a(X);
 | |
|     friend void f10_b(X);
 | |
|     friend void f10_c(X);
 | |
|     friend void f10_d(X);
 | |
|   };
 | |
|   extern void f10_c();
 | |
|   extern void f10_c(X);
 | |
| 
 | |
|   // FIXME: Give a better diagnostic for the case where a function exists but is
 | |
|   // not visible.
 | |
|   void g(X x) {
 | |
|     f10_a();
 | |
|     f10_b();
 | |
|     f10_c();
 | |
|     f10_d(); // expected-error {{undeclared identifier}}
 | |
| 
 | |
|     ::test10::f10_a();
 | |
|     ::test10::f10_b();
 | |
|     ::test10::f10_c();
 | |
|     ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}
 | |
| 
 | |
|     f10_a(x);
 | |
|     f10_b(x);
 | |
|     f10_c(x);
 | |
|     f10_d(x); // PR16597: expected-error {{undeclared identifier}}
 | |
| 
 | |
|     ::test10::f10_a(x);
 | |
|     ::test10::f10_b(x);
 | |
|     ::test10::f10_c(x);
 | |
|     ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
 | |
|   }
 | |
| 
 | |
|   struct Y : X {
 | |
|     friend void f10_d();
 | |
|     friend void f10_d(X);
 | |
|   };
 | |
| 
 | |
|   struct Z {
 | |
|     operator X();
 | |
|     friend void f10_d();
 | |
|     friend void f10_d(X);
 | |
|   };
 | |
| 
 | |
|   void g(X x, Y y, Z z) {
 | |
|     f10_d(); // expected-error {{undeclared identifier}}
 | |
|     ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}
 | |
| 
 | |
|     // f10_d is visible to ADL in the second and third cases.
 | |
|     f10_d(x); // expected-error {{undeclared identifier}}
 | |
|     f10_d(y);
 | |
|     f10_d(z);
 | |
| 
 | |
|     // No ADL here.
 | |
|     ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
 | |
|     ::test10::f10_d(y); // expected-error {{no type named 'f10_d'}}
 | |
|     ::test10::f10_d(z); // expected-error {{no type named 'f10_d'}}
 | |
|   }
 | |
| 
 | |
|   void local_externs(X x, Y y) {
 | |
|     extern void f10_d();
 | |
|     extern void f10_d(X);
 | |
|     f10_d();
 | |
|     f10_d(x);
 | |
|     // FIXME: This lookup should fail, because the local extern declaration
 | |
|     // should suppress ADL.
 | |
|     f10_d(y);
 | |
|     {
 | |
|       int f10_d;
 | |
|       f10_d(); // expected-error {{not a function}}
 | |
|       f10_d(x); // expected-error {{not a function}}
 | |
|       f10_d(y); // expected-error {{not a function}}
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void i(X x, Y y) {
 | |
|     f10_d(); // expected-error {{undeclared identifier}}
 | |
|     f10_d(x); // expected-error {{undeclared identifier}}
 | |
|     f10_d(y);
 | |
|   }
 | |
| 
 | |
|   struct C {
 | |
|     friend void f10_d();
 | |
|     friend void f10_d(X);
 | |
|   };
 | |
| 
 | |
|   void j(X x, Y y) {
 | |
|     f10_d(); // expected-error {{undeclared identifier}}
 | |
|     f10_d(x); // expected-error {{undeclared identifier}}
 | |
|     f10_d(y);
 | |
|   }
 | |
| 
 | |
|   extern void f10_d();
 | |
|   extern void f10_d(X);
 | |
|   void k(X x, Y y, Z z) {
 | |
|     // All OK now.
 | |
|     f10_d();
 | |
|     f10_d(x);
 | |
|     ::test10::f10_d();
 | |
|     ::test10::f10_d(x);
 | |
|     ::test10::f10_d(y);
 | |
|     ::test10::f10_d(z);
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace test11 {
 | |
|   class __attribute__((visibility("hidden"))) B;
 | |
| 
 | |
|   class A {
 | |
|     friend class __attribute__((visibility("hidden"), noreturn)) B; // expected-warning {{'noreturn' attribute only applies to functions and methods}}
 | |
|   };
 | |
| }
 | |
| 
 | |
| namespace pr21851 {
 | |
| // PR21851 was a problem where we assumed that when the friend function redecl
 | |
| // lookup found a C++ method, it would necessarily have a qualifier. Below we
 | |
| // have some test cases where unqualified lookup finds C++ methods without using
 | |
| // qualifiers. Unfortunately, we can't exercise the case of an access check
 | |
| // failure because nested classes always have access to the members of outer
 | |
| // classes.
 | |
| 
 | |
| void friend_own_method() {
 | |
|   class A {
 | |
|     void m() {}
 | |
|     friend void m();
 | |
|   };
 | |
| }
 | |
| 
 | |
| void friend_enclosing_method() {
 | |
|   class A;
 | |
|   class C {
 | |
|     int p;
 | |
|     friend class A;
 | |
|   };
 | |
|   class A {
 | |
|     void enclosing_friend() {
 | |
|       (void)b->p;
 | |
|       (void)c->p;
 | |
|     }
 | |
|     class B {
 | |
|       void b(A *a) {
 | |
|         (void)a->c->p;
 | |
|       }
 | |
|       int p;
 | |
|       friend void enclosing_friend();
 | |
|     };
 | |
|     B *b;
 | |
|     C *c;
 | |
|   };
 | |
| }
 | |
| 
 | |
| static auto friend_file_func() {
 | |
|   extern void file_scope_friend();
 | |
|   class A {
 | |
|     int p;
 | |
|     friend void file_scope_friend();
 | |
|   };
 | |
|   return A();
 | |
| }
 | |
| 
 | |
| void file_scope_friend() {
 | |
|   auto a = friend_file_func();
 | |
|   (void)a.p;
 | |
| }
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| struct X_pr6954 {
 | |
|   operator int();
 | |
|   friend void f_pr6954(int x);
 | |
| };
 | |
| 
 | |
| int array0_pr6954[sizeof(X_pr6954<int>)];
 | |
| int array1_pr6954[sizeof(X_pr6954<float>)];
 | |
| 
 | |
| void g_pr6954() {
 | |
|   f_pr6954(5); // expected-error{{undeclared identifier 'f_pr6954'}}
 | |
| }
 | |
| 
 |