Refactoring around friend class templates.  Better error message for friend enums.
Don't create a new declaration for friend classes if a declaration already exists.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83505 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b33f8cc..e00cbf8 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4283,8 +4283,10 @@
 
       std::string InsertionText = std::string(" ") + RD->getKindName();
 
-      Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
-        << (RD->isUnion())
+      Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type)
+        << (unsigned) RD->getTagKind()
+        << T
+        << SourceRange(DS.getFriendSpecLoc())
         << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
                                                  InsertionText);
       return DeclPtrTy();
@@ -4295,21 +4297,11 @@
     }
   }
 
-  bool IsDefinition = false;
-
-  // We want to do a few things differently if the type was declared with
-  // a tag:  specifically, we want to use the associated RecordDecl as
-  // the object of our friend declaration, and we want to disallow
-  // class definitions.
-  switch (DS.getTypeSpecType()) {
-  default: break;
-  case DeclSpec::TST_class:
-  case DeclSpec::TST_struct:
-  case DeclSpec::TST_union:
-    CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
-    if (RD)
-      IsDefinition |= RD->isDefinition();
-    break;
+  // Enum types cannot be friends.
+  if (T->getAs<EnumType>()) {
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
+      << SourceRange(DS.getFriendSpecLoc());
+    return DeclPtrTy();
   }
 
   // C++98 [class.friend]p1: A friend of a class is a function