Improve handling of friend types in several ways:
  - When instantiating a friend type template, perform semantic
  analysis on the resulting type.
  - Downgrade the errors concerning friend type declarations that do
  not refer to classes to ExtWarns in C++98/03. C++0x allows
  practically any type to be befriended, and ignores the friend
  declaration if the type is not a class.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100635 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/class.access/class.friend/p2-cxx03.cpp b/test/CXX/class.access/class.friend/p2-cxx03.cpp
new file mode 100644
index 0000000..0391c4b
--- /dev/null
+++ b/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 type 'T' cannot be a friend}}
+};
+
+class X1 { };
+enum E1 { };
+X0<X1> x0a;
+X0<X1 *> x0b;
+X0<int> x0c;
+X0<E1> x0d;
+
diff --git a/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/test/CXX/class.access/class.friend/p3-cxx0x.cpp
new file mode 100644
index 0000000..4f55e53
--- /dev/null
+++ b/test/CXX/class.access/class.friend/p3-cxx0x.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -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/test/CXX/class/class.friend/p2.cpp b/test/CXX/class/class.friend/p2.cpp
index 9fe2b17..eb5036f 100644
--- a/test/CXX/class/class.friend/p2.cpp
+++ b/test/CXX/class/class.friend/p2.cpp
@@ -4,7 +4,7 @@
 
 class A {
   friend class B {}; // expected-error {{cannot define a type in a friend declaration}}
-  friend int; // expected-error {{friends can only be classes or functions}}
-  friend B0; // expected-error {{must specify 'struct' to befriend}}
+  friend int; // expected-warning {{non-class type 'int' cannot be a friend}}
+  friend B0; // expected-warning {{must specify 'struct' to befriend}}
   friend class C; // okay
 };
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
index c530311..b04e869 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
@@ -13,7 +13,7 @@
   friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}}
 
   friend enum A; // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
-                 // expected-error {{enum types cannot be friends}}
+                 // expected-warning {{cannot be a friend}}
 };
 
 template <class T> struct B { // expected-note {{previous use is here}}
diff --git a/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/test/CXX/temp/temp.decls/temp.friend/p3.cpp
index 17d8c85..d116e01 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p3.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p3.cpp
@@ -8,6 +8,5 @@
   template <class T> friend class A;
   template <class T> friend class Undeclared;
   
-  // FIXME: Diagnostic below could be (and was) better.
-  template <class T> friend typename A<T>::Member; // expected-error {{classes or functions}}
+  template <class T> friend typename A<T>::Member; // expected-warning {{non-class type 'typename A<T>::Member' cannot be a friend}}
 };
diff --git a/test/Parser/cxx-friend.cpp b/test/Parser/cxx-friend.cpp
index 2fe30cd..59350b5 100644
--- a/test/Parser/cxx-friend.cpp
+++ b/test/Parser/cxx-friend.cpp
@@ -21,9 +21,9 @@
   // 'A' here should refer to the declaration above.  
   friend class A;
 
-  friend C; // expected-error {{must specify 'class' to befriend}}
-  friend U; // expected-error {{must specify 'union' to befriend}}
-  friend int; // expected-error {{friends can only be classes or functions}}
+  friend C; // expected-warning {{must specify 'class' to befriend}}
+  friend U; // expected-warning {{must specify 'union' to befriend}}
+  friend int; // expected-warning {{non-class type 'int' cannot be a friend}}
 
   friend void myfunc();