summaryrefslogtreecommitdiff
path: root/clang/test/CXX/class/class.friend
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/class/class.friend')
-rw-r--r--clang/test/CXX/class/class.friend/p1-ambiguous.cpp37
-rw-r--r--clang/test/CXX/class/class.friend/p1-cxx11.cpp12
-rw-r--r--clang/test/CXX/class/class.friend/p1.cpp77
-rw-r--r--clang/test/CXX/class/class.friend/p2.cpp10
-rw-r--r--clang/test/CXX/class/class.friend/p6.cpp10
5 files changed, 146 insertions, 0 deletions
diff --git a/clang/test/CXX/class/class.friend/p1-ambiguous.cpp b/clang/test/CXX/class/class.friend/p1-ambiguous.cpp
new file mode 100644
index 0000000..a9dca4f
--- /dev/null
+++ b/clang/test/CXX/class/class.friend/p1-ambiguous.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Make sure that friend declarations don't introduce ambiguous
+// declarations.
+
+// Test case courtesy of Shantonu Sen.
+// Bug 4784.
+
+class foo;
+
+extern "C" {
+ int c_func(foo *a);
+};
+int cpp_func(foo *a);
+
+class foo {
+public:
+ friend int c_func(foo *a);
+ friend int cpp_func(foo *a);
+ int caller();
+private:
+ int x;
+};
+
+int c_func(foo *a) {
+ return a->x;
+}
+
+int cpp_func(foo *a) {
+ return a->x;
+}
+
+int foo::caller() {
+ c_func(this);
+ cpp_func(this);
+ return 0;
+}
diff --git a/clang/test/CXX/class/class.friend/p1-cxx11.cpp b/clang/test/CXX/class/class.friend/p1-cxx11.cpp
new file mode 100644
index 0000000..235f295
--- /dev/null
+++ b/clang/test/CXX/class/class.friend/p1-cxx11.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+class A {
+ class AInner {
+ };
+
+ void a_member();
+ friend void A::a_member(); // ok in c++11, ill-formed in c++98
+ friend void a_member(); // ok in both, refers to non-member
+ friend class A::AInner; // ok in c++11, extension in c++98
+ friend class AInner; // ok in both, refers to non-member
+};
diff --git a/clang/test/CXX/class/class.friend/p1.cpp b/clang/test/CXX/class/class.friend/p1.cpp
new file mode 100644
index 0000000..07b3a10
--- /dev/null
+++ b/clang/test/CXX/class/class.friend/p1.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct Outer {
+ struct Inner {
+ int intfield;
+ };
+};
+
+struct Base {
+ void base_member();
+
+ typedef int Int;
+ Int typedeffed_member();
+};
+
+struct Derived : public Base {
+};
+
+int myglobal;
+
+void global_function();
+extern "C" {
+ void global_c_function();
+}
+
+class A {
+ class AInner {
+ };
+
+ friend class PreDeclared;
+ friend class Outer::Inner;
+ friend int Outer::Inner::intfield; // expected-error {{friends can only be classes or functions}}
+ friend int Outer::Inner::missing_field; //expected-error {{friends can only be classes or functions}}
+ friend int myoperation(float); // okay
+ friend int myglobal; // expected-error {{friends can only be classes or functions}}
+
+ friend void global_function();
+ friend void global_c_function();
+
+ friend class UndeclaredSoFar;
+ UndeclaredSoFar x; // expected-error {{unknown type name 'UndeclaredSoFar'}}
+
+ void a_member();
+ friend void A::a_member(); // expected-error {{friends cannot be members of the declaring class}}
+ friend void a_member(); // okay (because we ignore class scopes when looking up friends)
+ friend class A::AInner; // this is okay as an extension
+ friend class AInner; // okay, refers to ::AInner
+
+ friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}}
+
+ friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}}
+
+ friend int Base::typedeffed_member(); // okay: should look through typedef
+
+ // These test that the friend is properly not being treated as a
+ // member function.
+ friend A operator|(const A& l, const A& r); // okay
+ friend A operator|(const A& r); // expected-error {{overloaded 'operator|' must be a binary operator (has 1 parameter)}}
+
+ friend operator bool() const; // expected-error {{must use a qualified name when declaring a conversion operator as a friend}} \
+ // expected-error{{non-member function cannot have 'const' qualifier}}
+
+ typedef void ftypedef();
+ friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
+
+ class facet;
+ friend class facet; // should not assert
+ class facet {};
+};
+
+A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'A'}}
+
+class PreDeclared;
+
+int myoperation(float f) {
+ return (int) f;
+}
diff --git a/clang/test/CXX/class/class.friend/p2.cpp b/clang/test/CXX/class/class.friend/p2.cpp
new file mode 100644
index 0000000..fb3cd19
--- /dev/null
+++ b/clang/test/CXX/class/class.friend/p2.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct B0;
+
+class A {
+ friend class B {}; // expected-error {{cannot define a type in a friend declaration}}
+ friend int; // expected-warning {{non-class friend type 'int' is a C++11 extension}}
+ friend B0; // expected-warning {{specify 'struct' to befriend 'B0'}}
+ friend class C; // okay
+};
diff --git a/clang/test/CXX/class/class.friend/p6.cpp b/clang/test/CXX/class/class.friend/p6.cpp
new file mode 100644
index 0000000..7d7a064
--- /dev/null
+++ b/clang/test/CXX/class/class.friend/p6.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -verify %s
+
+class A {
+ friend static class B; // expected-error {{'static' is invalid in friend declarations}}
+ friend extern class C; // expected-error {{'extern' is invalid in friend declarations}}
+ friend auto class D; // expected-warning {{incompatible with C++11}} expected-error {{'auto' is invalid in friend declarations}}
+ friend register class E; // expected-error {{'register' is invalid in friend declarations}}
+ friend mutable class F; // expected-error {{'mutable' is invalid in friend declarations}}
+ friend typedef class G; // expected-error {{'typedef' is invalid in friend declarations}}
+};