332 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// RUN: %clang_cc1 -fsyntax-only -verify %s
 | 
						|
// PR5057
 | 
						|
namespace test0 {
 | 
						|
  namespace std {
 | 
						|
    class X {
 | 
						|
    public:
 | 
						|
      template<typename T> friend struct Y;
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  namespace std {
 | 
						|
    template<typename T> struct Y {};
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace test1 {
 | 
						|
  template<typename T> void f1(T) { } // expected-note{{here}}
 | 
						|
 | 
						|
  class X {
 | 
						|
    template<typename T> friend void f0(T);
 | 
						|
    template<typename T> friend void f1(T);
 | 
						|
  };
 | 
						|
 | 
						|
  template<typename T> void f0(T) { }
 | 
						|
  template<typename T> void f1(T) { } // expected-error{{redefinition}}
 | 
						|
}
 | 
						|
 | 
						|
// PR4768
 | 
						|
namespace test2 {
 | 
						|
  template<typename T> struct X0 {
 | 
						|
    template<typename U> friend struct X0;
 | 
						|
  };
 | 
						|
  
 | 
						|
  template<typename T> struct X0<T*> {
 | 
						|
    template<typename U> friend struct X0;
 | 
						|
  };
 | 
						|
 | 
						|
  template<> struct X0<int> {
 | 
						|
    template<typename U> friend struct X0;
 | 
						|
  };
 | 
						|
 | 
						|
  template<typename T> struct X1 {
 | 
						|
    template<typename U> friend void f2(U);
 | 
						|
    template<typename U> friend void f3(U);
 | 
						|
  };
 | 
						|
 | 
						|
  template<typename U> void f2(U);
 | 
						|
 | 
						|
  X1<int> x1i;
 | 
						|
  X0<int*> x0ip;
 | 
						|
 | 
						|
  template<> void f2(int);
 | 
						|
 | 
						|
  // FIXME: Should this declaration of f3 be required for the specialization of
 | 
						|
  // f3<int> (further below) to work? GCC and EDG don't require it, we do...
 | 
						|
  template<typename U> void f3(U);
 | 
						|
 | 
						|
  template<> void f3(int);
 | 
						|
}
 | 
						|
 | 
						|
// PR5332
 | 
						|
namespace test3 {
 | 
						|
  template <typename T> class Foo {
 | 
						|
    template <typename U>
 | 
						|
    friend class Foo;
 | 
						|
  };
 | 
						|
 | 
						|
  Foo<int> foo;
 | 
						|
 | 
						|
  template<typename T, T Value> struct X2a;
 | 
						|
 | 
						|
  template<typename T, int Size> struct X2b;
 | 
						|
 | 
						|
  template<typename T>
 | 
						|
  class X3 {
 | 
						|
    template<typename U, U Value> friend struct X2a;
 | 
						|
 | 
						|
    // FIXME: the redeclaration note ends up here because redeclaration
 | 
						|
    // lookup ends up finding the friend target from X3<int>.
 | 
						|
    template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \
 | 
						|
      // expected-note {{previous non-type template parameter with type 'int' is here}}
 | 
						|
  };
 | 
						|
 | 
						|
  X3<int> x3i; // okay
 | 
						|
 | 
						|
  X3<long> x3l; // expected-note {{in instantiation}}
 | 
						|
}
 | 
						|
 | 
						|
// PR5716
 | 
						|
namespace test4 {
 | 
						|
  template<typename> struct A {
 | 
						|
    template<typename T> friend void f(const A<T>&);
 | 
						|
  };
 | 
						|
 | 
						|
  template<typename T> void f(const A<T>&) {
 | 
						|
    int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}}
 | 
						|
  }
 | 
						|
 | 
						|
  void f() {
 | 
						|
    f(A<int>()); // expected-note {{in instantiation of function template specialization}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace test5 {
 | 
						|
  class outer {
 | 
						|
    class foo;
 | 
						|
    template <typename T> friend struct cache;
 | 
						|
  };
 | 
						|
  class outer::foo {
 | 
						|
    template <typename T> friend struct cache;
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
// PR6022
 | 
						|
namespace PR6022 {
 | 
						|
  template <class T1, class T2 , class T3  > class A;
 | 
						|
 | 
						|
  namespace inner {
 | 
						|
    template<class T1, class T2, class T3, class T> 
 | 
						|
    A<T1, T2, T3>& f0(A<T1, T2, T3>&, T);
 | 
						|
  } 
 | 
						|
 | 
						|
  template<class T1, class T2, class T3>
 | 
						|
  class A {
 | 
						|
    template<class U1, class U2, class U3, class T>  
 | 
						|
    friend A<U1, U2, U3>& inner::f0(A<U1, U2, U3>&, T);
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
namespace FriendTemplateDefinition {
 | 
						|
  template<unsigned > struct int_c { };
 | 
						|
 | 
						|
  template<typename T>
 | 
						|
  struct X {
 | 
						|
    template<unsigned N>
 | 
						|
    friend void f(X, int_c<N>) {
 | 
						|
      int value = N;
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  void test_X(X<int> x, int_c<5> i5) {
 | 
						|
    f(x, i5);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace PR7013a {
 | 
						|
  template<class > struct X0
 | 
						|
  {
 | 
						|
    typedef int type;
 | 
						|
  };
 | 
						|
  template<typename > struct X1
 | 
						|
  {
 | 
						|
  };
 | 
						|
  template<typename , typename T> struct X2
 | 
						|
  {
 | 
						|
    typename T::type e;
 | 
						|
  };
 | 
						|
  namespace N
 | 
						|
  {
 | 
						|
    template <typename = int, typename = X1<int> > struct X3
 | 
						|
    {
 | 
						|
      template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
 | 
						|
    };
 | 
						|
    template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
 | 
						|
    {
 | 
						|
      X2<int, Tr> s;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  int n()
 | 
						|
  {
 | 
						|
    X2<int, X0<int> > ngs;
 | 
						|
    N::X3<> b;
 | 
						|
    op(ngs, b);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace PR7013b {
 | 
						|
  template<class > struct X0
 | 
						|
  {
 | 
						|
    typedef int type;
 | 
						|
  };
 | 
						|
  template<typename > struct X1
 | 
						|
  {
 | 
						|
  };
 | 
						|
  template<typename , typename T> struct X2
 | 
						|
  {
 | 
						|
    typename T::type e;
 | 
						|
  };
 | 
						|
  namespace N
 | 
						|
  {
 | 
						|
    template <typename = X1<int> > struct X3
 | 
						|
    {
 | 
						|
      template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
 | 
						|
    };
 | 
						|
    template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
 | 
						|
    {
 | 
						|
      X2<int, Tr> s;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  int n()
 | 
						|
  {
 | 
						|
    X2<int, X0<int> > ngs;
 | 
						|
    N::X3<> b;
 | 
						|
    op(ngs, b);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
namespace PR8649 {
 | 
						|
  template<typename T, typename U, unsigned N>
 | 
						|
  struct X {
 | 
						|
    template<unsigned M> friend class X<T, U, M>; // expected-error{{partial specialization cannot be declared as a friend}}
 | 
						|
  };
 | 
						|
 | 
						|
  X<int, float, 7> x;
 | 
						|
}
 | 
						|
 | 
						|
// Don't crash, and error on invalid friend type template.
 | 
						|
namespace friend_type_template_no_tag {
 | 
						|
  template <typename T> struct S {
 | 
						|
    template <typename U> friend S<U>; // expected-error{{friend type templates must use an elaborated type}}
 | 
						|
  };
 | 
						|
  template struct S<int>;
 | 
						|
}
 | 
						|
 | 
						|
namespace PR10660 {
 | 
						|
  struct A {
 | 
						|
    template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}}
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
namespace rdar11147355 {
 | 
						|
  template <class T>
 | 
						|
  struct A {
 | 
						|
    template <class U> class B;
 | 
						|
    template <class S> template <class U> friend class A<S>::B; // expected-warning {{dependent nested name specifier 'A<S>::' for friend template declaration is not supported; ignoring this friend declaration}}
 | 
						|
  private:
 | 
						|
    int n; // expected-note {{here}}
 | 
						|
  };
 | 
						|
 | 
						|
  template <class S> template <class U> class A<S>::B {
 | 
						|
  public:
 | 
						|
    // FIXME: This should be permitted.
 | 
						|
    int f(A<S*> a) { return a.n; } // expected-error {{private}}
 | 
						|
  };
 | 
						|
 | 
						|
  A<double>::B<double>  ab;
 | 
						|
  A<double*> a;
 | 
						|
  int k = ab.f(a); // expected-note {{instantiation of}}
 | 
						|
}
 | 
						|
 | 
						|
namespace RedeclUnrelated {
 | 
						|
  struct S {
 | 
						|
    int packaged_task;
 | 
						|
    template<typename> class future {
 | 
						|
      template<typename> friend class packaged_task;
 | 
						|
    };
 | 
						|
    future<void> share;
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
namespace PR12557 {
 | 
						|
  template <typename>
 | 
						|
  struct Foo;
 | 
						|
 | 
						|
  template <typename Foo_>
 | 
						|
  struct Bar {
 | 
						|
    typedef Foo_  Foo; // expected-note {{previous}}
 | 
						|
 | 
						|
    template <typename> friend struct Foo; // expected-error {{redefinition of 'Foo' as different kind of symbol}}
 | 
						|
  };
 | 
						|
 | 
						|
  Bar<int> b;
 | 
						|
}
 | 
						|
 | 
						|
namespace PR12585 {
 | 
						|
  struct A { };
 | 
						|
  template<typename> struct B {
 | 
						|
    template<typename> friend class A::does_not_exist; // \
 | 
						|
     // expected-error {{friend declaration of 'does_not_exist' does not match any declaration in 'PR12585::A'}}
 | 
						|
  };
 | 
						|
 | 
						|
  struct C {
 | 
						|
    template<typename> struct D;
 | 
						|
  };
 | 
						|
  template<typename> class E {
 | 
						|
    int n;
 | 
						|
    template<typename> friend struct C::D;
 | 
						|
  };
 | 
						|
  template<typename T> struct C::D {
 | 
						|
    int f() {
 | 
						|
      return E<int>().n;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  int n = C::D<void*>().f();
 | 
						|
 | 
						|
  struct F {
 | 
						|
    template<int> struct G;
 | 
						|
  };
 | 
						|
  template<typename T> struct H {
 | 
						|
    // FIXME: As with cases above, the note here is on an unhelpful declaration,
 | 
						|
    // and should point to the declaration of G within F.
 | 
						|
    template<T> friend struct F::G; // \
 | 
						|
      // expected-error {{different type 'char' in template redeclaration}} \
 | 
						|
      // expected-note {{previous}}
 | 
						|
  };
 | 
						|
  H<int> h1; // ok
 | 
						|
  H<char> h2; // expected-note {{instantiation}}
 | 
						|
}
 | 
						|
 | 
						|
// Ensure that we can still instantiate a friend function template
 | 
						|
// after the friend declaration is instantiated during the delayed
 | 
						|
// parsing of a member function, but before the friend function has
 | 
						|
// been parsed.
 | 
						|
namespace rdar12350696 {
 | 
						|
  template <class T> struct A {
 | 
						|
    void foo() {
 | 
						|
      A<int> a;
 | 
						|
    }
 | 
						|
    template <class U> friend void foo(const A<U> & a) {
 | 
						|
      int array[sizeof(T) == sizeof(U) ? -1 : 1]; // expected-error {{negative size}}
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  void test() {
 | 
						|
    A<int> b;
 | 
						|
    foo(b); // expected-note {{in instantiation}}
 | 
						|
  }
 | 
						|
}
 |