diff options
| author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 | 
|---|---|---|
| committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 | 
| commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
| tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/test/CXX/class.access/class.friend | |
| parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
| parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) | |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/test/CXX/class.access/class.friend')
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p1.cpp | 356 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p11.cpp | 19 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p2-cxx03.cpp | 13 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp | 29 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p6.cpp | 20 | 
5 files changed, 437 insertions, 0 deletions
| diff --git a/clang/test/CXX/class.access/class.friend/p1.cpp b/clang/test/CXX/class.access/class.friend/p1.cpp new file mode 100644 index 0000000..68ff83f --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p1.cpp @@ -0,0 +1,356 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++'0x [class.friend] p1: +//   A friend of a class is a function or class that is given permission to use +//   the private and protected member names from the class. A class specifies +//   its friends, if any, by way of friend declarations. Such declarations give +//   special access rights to the friends, but they do not make the nominated +//   friends members of the befriending class. + +struct S { static void f(); }; +S* g() { return 0; } + +struct X { +  friend struct S; +  friend S* g(); +}; + +void test1() { +  S s; +  g()->f(); +  S::f(); +  X::g(); // expected-error{{no member named 'g' in 'X'}} +  X::S x_s; // expected-error{{no member named 'S' in 'X'}} +  X x; +  x.g(); // expected-error{{no member named 'g' in 'X'}} +} + +// Test that we recurse through namespaces to find already declared names, but +// new names are declared within the enclosing namespace. +namespace N { +  struct X { +    friend struct S; +    friend S* g(); + +    friend struct S2; +    friend struct S2* g2(); +  }; + +  struct S2 { static void f2(); }; +  S2* g2() { return 0; } + +  void test() { +    g()->f(); +    S s; +    S::f(); +    X::g(); // expected-error{{no member named 'g' in 'N::X'}} +    X::S x_s; // expected-error{{no member named 'S' in 'N::X'}} +    X x; +    x.g(); // expected-error{{no member named 'g' in 'N::X'}} + +    g2(); +    S2 s2; +    ::g2(); // expected-error{{no member named 'g2' in the global namespace}} +    ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}} +    X::g2(); // expected-error{{no member named 'g2' in 'N::X'}} +    X::S2 x_s2; // expected-error{{no member named 'S2' in 'N::X'}} +    x.g2(); // expected-error{{no member named 'g2' in 'N::X'}} +  } +} + +namespace test0 { +  class ClassFriend { +    void test(); +  }; + +  class MemberFriend { +    void test(); +  }; + +  void declared_test(); + +  class Class { +    static void member(); // expected-note 2 {{declared private here}} + +    friend class ClassFriend; +    friend class UndeclaredClassFriend; + +    friend void undeclared_test(); +    friend void declared_test(); +    friend void MemberFriend::test(); +  }; + +  void declared_test() { +    Class::member(); +  } + +  void undeclared_test() { +    Class::member(); +  } + +  void unfriended_test() { +    Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} +  } + +  void ClassFriend::test() { +    Class::member(); +  } + +  void MemberFriend::test() { +    Class::member(); +  } + +  class UndeclaredClassFriend { +    void test() { +      Class::member(); +    } +  }; + +  class ClassNonFriend { +    void test() { +      Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} +    } +  }; +} + +// Make sure that friends have access to inherited protected members. +namespace test2 { +  struct X; + +  class ilist_half_node { +    friend struct ilist_walker_bad; +    X *Prev; +  protected: +    X *getPrev() { return Prev; } // expected-note{{member is declared here}} +  }; + +  class ilist_node : private ilist_half_node { // expected-note {{declared private here}} expected-note {{constrained by private inheritance here}} +    friend struct ilist_walker; +    X *Next; +    X *getNext() { return Next; } // expected-note {{declared private here}} +  }; + +  struct X : ilist_node {}; + +  struct ilist_walker { +    static X *getPrev(X *N) { return N->getPrev(); } +    static X *getNext(X *N) { return N->getNext(); } +  };   + +  struct ilist_walker_bad { +    static X *getPrev(X *N) { return N->getPrev(); } // \ +    // expected-error {{'getPrev' is a private member of 'test2::ilist_half_node'}} \ +    // expected-error {{cannot cast 'test2::X' to its private base class 'test2::ilist_half_node'}} + +    static X *getNext(X *N) { return N->getNext(); } // \ +    // expected-error {{'getNext' is a private member of 'test2::ilist_node'}} +  };   +} + +namespace test3 { +  class A { protected: int x; }; // expected-note {{declared protected here}} + +  class B : public A { +    friend int foo(B*); +  }; + +  int foo(B *p) { +    return p->x; +  } + +  int foo(const B *p) { +    return p->x; // expected-error {{'x' is a protected member of 'test3::A'}} +  } +} + +namespace test3a { +  class A { protected: int x; }; + +  class B : public A { +    friend int foo(B*); +  }; + +  int foo(B * const p) { +    return p->x; +  } +} + +namespace test4 { +  template <class T> class Holder { +    T object; +    friend bool operator==(Holder &a, Holder &b) { +      return a.object == b.object; // expected-error {{invalid operands to binary expression}} +    } +  }; + +  struct Inequal {}; +  bool test() { +    Holder<Inequal> a, b; +    return a == b;  // expected-note {{requested here}} +  } +} + + +// PR6174 +namespace test5 { +  namespace ns { +    class A; +  } + +  class ns::A { +  private: int x; +    friend class B; +  }; + +  namespace ns { +    class B { +      int test(A *p) { return p->x; } +    }; +  } +} + +// PR6207 +namespace test6 { +  struct A {}; + +  struct B { +    friend A::A(); +    friend A::~A(); +    friend A &A::operator=(const A&); +  }; +} + +namespace test7 { +  template <class T> struct X { +    X(); +    ~X(); +    void foo(); +    void bar(); +  }; + +  class A { +    friend void X<int>::foo(); +    friend X<int>::X(); +    friend X<int>::X(const X&); + +  private: +    A(); // expected-note 2 {{declared private here}} +  }; + +  template<> void X<int>::foo() { +    A a; +  } + +  template<> void X<int>::bar() { +    A a; // expected-error {{calling a private constructor}} +  } + +  template<> X<int>::X() { +    A a; +  } + +  template<> X<int>::~X() { +    A a; // expected-error {{calling a private constructor}} +  } +} + +// Return types, parameters and default arguments to friend functions. +namespace test8 { +  class A { +    typedef int I; // expected-note 4 {{declared private here}} +    static const I x = 0; // expected-note {{implicitly declared private here}} +    friend I f(I i); +    template<typename T> friend I g(I i); +  }; + +  const A::I A::x; +  A::I f(A::I i = A::x) {} +  template<typename T> A::I g(A::I i) { +    T t; +  } +  template A::I g<A::I>(A::I i); + +  A::I f2(A::I i = A::x) {} // expected-error 3 {{is a private member of}} +  template<typename T> A::I g2(A::I i) { // expected-error 2 {{is a private member of}} +    T t; +  } +  template A::I g2<A::I>(A::I i); +} + +// PR6885 +namespace test9 { +  class B { +    friend class test9; +  }; +} + +// PR7230 +namespace test10 { +  extern "C" void f(void); +  extern "C" void g(void); + +  namespace NS { +    class C { +      void foo(void); // expected-note {{declared private here}} +      friend void test10::f(void); +    }; +    static C* bar; +  } + +  void f(void) { +    NS::bar->foo(); +  } + +  void g(void) { +    NS::bar->foo(); // expected-error {{private member}} +  } +} + +// PR8705 +namespace test11 { +  class A { +    void test0(int); +    void test1(int); +    void test2(int); +    void test3(int); +  }; + +  class B { +    typedef int private_type; // expected-note 2 {{implicitly declared private here}} +    friend void A::test0(int); +    friend void A::test1(int); +  }; + +  void A::test0(B::private_type x) {} +  void A::test1(int x = B::private_type()) {} +  void A::test2(B::private_type x) {} // expected-error {{'private_type' is a private member of 'test11::B'}} +  void A::test3(int x = B::private_type()) {} // expected-error {{'private_type' is a private member of 'test11::B'}} +} + + +// PR9221 +namespace test12 { +  struct A { +    void foo(); +  }; +  class B : private A { +    friend void A::foo(); +    void *mem; +  }; +  void A::foo() { +    void *var = static_cast<B*>(this)->mem; +  } +} + +namespace PR9103 { +  struct base { +  protected: +    static void foo(void) {} +  }; + +  struct cls: base { +    friend void bar(void) { +      base::foo(); +    } +  }; +} diff --git a/clang/test/CXX/class.access/class.friend/p11.cpp b/clang/test/CXX/class.access/class.friend/p11.cpp new file mode 100644 index 0000000..a05b2d2 --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p11.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar://problem/8540720 +namespace test0 { +  void foo() { +    void bar(); +    class A { +      friend void bar(); +    }; +  } +} + +namespace test1 { +  void foo() { +    class A { +      friend void bar(); // expected-error {{no matching function found in local scope}} +    }; +  } +} diff --git a/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp b/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp new file mode 100644 index 0000000..f8cabfd --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +class X0 { +  friend T; // expected-warning{{non-class friend type 'T' is a C++11 extension}} +}; + +class X1 { }; +enum E1 { }; +X0<X1> x0a; +X0<X1 *> x0b; +X0<int> x0c; +X0<E1> x0d; + diff --git a/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp new file mode 100644 index 0000000..00fc0a3 --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +template<typename T> +class X0 { +  friend T; +}; + +class Y1 { }; +enum E1 { }; +X0<Y1> x0a; +X0<Y1 *> x0b; +X0<int> x0c; +X0<E1> x0d; + +template<typename T> +class X1 { +  friend typename T::type; // expected-error{{no type named 'type' in 'Y1'}} +}; + +struct Y2 { +  struct type { }; +}; + +struct Y3 { +  typedef int type; +}; + +X1<Y2> x1a; +X1<Y3> x1b; +X1<Y1> x1c; // expected-note{{in instantiation of template class 'X1<Y1>' requested here}} diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp b/clang/test/CXX/class.access/class.friend/p6.cpp new file mode 100644 index 0000000..7f7d909 --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p6.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f1(); + +struct X { +  void f2(); +}; + +struct Y { +  friend void ::f1() { } // expected-error{{friend function definition cannot be qualified with '::'}} +  friend void X::f2() { } // expected-error{{friend function definition cannot be qualified with 'X::'}} +}; + +void local() { +  void f(); + +  struct Local { +    friend void f() { } // expected-error{{friend function cannot be defined in a local class}} +  }; +} | 
