1// RUN: %clang_cc1 -fsyntax-only -verify %s
2
3struct Outer {
4  struct Inner {
5    int intfield;
6  };
7};
8
9struct Base {
10  void base_member();
11
12  typedef int Int;
13  Int typedeffed_member();
14};
15
16struct Derived : public Base {
17};
18
19int myglobal;
20
21void global_function();
22extern "C" {
23  void global_c_function();
24}
25
26class A {
27  class AInner {
28  };
29
30  friend class PreDeclared;
31  friend class Outer::Inner;
32  friend int Outer::Inner::intfield; // expected-error {{friends can only be classes or functions}}
33  friend int Outer::Inner::missing_field; //expected-error {{friends can only be classes or functions}}
34  friend int myoperation(float); // okay
35  friend int myglobal;   // expected-error {{friends can only be classes or functions}}
36
37  friend void global_function();
38  friend void global_c_function();
39
40  friend class UndeclaredSoFar;
41  UndeclaredSoFar x; // expected-error {{unknown type name 'UndeclaredSoFar'}}
42
43  void a_member();
44  friend void A::a_member(); // expected-error {{friends cannot be members of the declaring class}}
45  friend void a_member(); // okay (because we ignore class scopes when looking up friends)
46  friend class A::AInner; // this is okay as an extension
47  friend class AInner; // okay, refers to ::AInner
48
49  friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}}
50
51  friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}}
52
53  friend int Base::typedeffed_member(); // okay: should look through typedef
54
55  // These test that the friend is properly not being treated as a
56  // member function.
57  friend A operator|(const A& l, const A& r); // okay
58  friend A operator|(const A& r); // expected-error {{overloaded 'operator|' must be a binary operator (has 1 parameter)}}
59
60  friend operator bool() const; // expected-error {{must use a qualified name when declaring a conversion operator as a friend}} \
61       // expected-error{{non-member function cannot have 'const' qualifier}}
62
63  typedef void ftypedef();
64  friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
65
66  class facet;
67  friend class facet;  // should not assert
68  class facet {};
69};
70
71A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'A'}}
72
73class PreDeclared;
74
75int myoperation(float f) {
76  return (int) f;
77}
78