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