Omnibus friend decl refactoring.  Instead of cloning AST classes for friend
declarations of same, introduce a single AST class and add appropriate bits
(encoded in the namespace) for whether a decl is "real" or not.  Much hackery
about previously-declared / not-previously-declared, but it's essentially
mandated by the standard that friends alter lookup, and this is at least
fairly non-intrusive.

Refactor the Sema methods specific to friends for cleaner flow and less nesting.

Incidentally solve a few bugs, but I remain confident that we can put them back.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80353 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 045c12a..15e8bc3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -735,7 +735,7 @@
 
     const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
     const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
-    if (OldMethod && NewMethod && 
+    if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() &&
         NewMethod->getLexicalDeclContext()->isRecord()) {
       //    -- Member function declarations with the same name and the 
       //       same parameter types cannot be overloaded if any of them 
@@ -2411,6 +2411,7 @@
 
   bool isVirtualOkay = false;
   FunctionDecl *NewFD;
+
   if (isFriend) {
     // DC is the namespace in which the function is being declared.
     assert((DC->isFileContext() || PrevDecl) && "previously-undeclared "
@@ -2420,13 +2421,9 @@
     //   A function can be defined in a friend declaration of a
     //   class . . . . Such a function is implicitly inline.
     isInline |= IsFunctionDefinition;
+  }
 
-    NewFD = FriendFunctionDecl::Create(Context, DC,
-                                       D.getIdentifierLoc(), Name, R, DInfo,
-                                       isInline,
-                                       D.getDeclSpec().getFriendSpecLoc());
-    
-  } else if (D.getKind() == Declarator::DK_Constructor) {
+  if (D.getKind() == Declarator::DK_Constructor) {
     // This is a C++ constructor declaration.
     assert(DC->isRecord() &&
            "Constructors can only be declared in a member context");
@@ -2514,10 +2511,13 @@
     NewFD->setInvalidDecl();
   
   // Set the lexical context. If the declarator has a C++
-  // scope specifier, the lexical context will be different
-  // from the semantic context.
+  // scope specifier, or is the object of a friend declaration, the
+  // lexical context will be different from the semantic context.
   NewFD->setLexicalDeclContext(CurContext);
 
+  if (isFriend)
+    NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL);
+
   // Match up the template parameter lists with the scope specifier, then
   // determine whether we have a template or a template specialization.
   FunctionTemplateDecl *FunctionTemplate = 0;
@@ -4310,6 +4310,10 @@
   // lexical context will be different from the semantic context.
   New->setLexicalDeclContext(CurContext);
 
+  // Mark this as a friend decl if applicable.
+  if (TUK == TUK_Friend)
+    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL);
+
   // Set the access specifier.
   if (!Invalid && TUK != TUK_Friend)
     SetMemberAccessSpecifier(New, PrevDecl, AS);