Argument-dependent lookup for friend declarations.  Add a new decl type,
FriendFunctionDecl, and create instances as appropriate.

The design of FriendFunctionDecl is still somewhat up in the air;  you can
befriend arbitrary types of functions --- methods, constructors, etc. ---
and it's not clear that this representation captures that very well.
We'll have a better picture when we start consuming this data in access
control.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78653 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 20862d4..a0bcfb2 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3305,7 +3305,8 @@
 }
 
 Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S,
-                       llvm::PointerUnion<const DeclSpec*,Declarator*> DU) {
+                       llvm::PointerUnion<const DeclSpec*,Declarator*> DU,
+                                      bool IsDefinition) {
   Declarator *D = DU.dyn_cast<Declarator*>();
   const DeclSpec &DS = (D ? D->getDeclSpec() : *DU.get<const DeclSpec*>());
 
@@ -3483,10 +3484,18 @@
       Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
   }
 
+  bool Redeclaration = (FD != 0);
+
+  // If we found a match, create a friend function declaration with
+  // that function as the previous declaration.
+  if (Redeclaration) {
+    // Create it in the semantic context of the original declaration.
+    DC = FD->getDeclContext();
+
   // If we didn't find something matching the type exactly, create
   // a declaration.  This declaration should only be findable via
   // argument-dependent lookup.
-  if (!FD) {
+  } else {
     assert(DC->isFileContext());
 
     // This implies that it has to be an operator or function.
@@ -3498,23 +3507,25 @@
          D->getKind() == Declarator::DK_Destructor ? 1 : 2);
       return DeclPtrTy();
     }
-
-    bool Redeclaration = false;
-    NamedDecl *ND = ActOnFunctionDeclarator(S, *D, DC, T,
-                                            /* PrevDecl = */ NULL,
-                                            MultiTemplateParamsArg(*this),
-                                            /* isFunctionDef */ false,
-                                            Redeclaration);
-
-    FD = cast_or_null<FunctionDecl>(ND);
-
-    // Note that we're creating a declaration but *not* pushing
-    // it onto the scope chains.
-
-    // TODO: make accessible via argument-dependent lookup.
   }
 
-  // TODO: actually register the function as a friend.
+  NamedDecl *ND = ActOnFunctionDeclarator(S, *D, DC, T,
+                                          /* PrevDecl = */ FD,
+                                          MultiTemplateParamsArg(*this),
+                                          IsDefinition,
+                                          Redeclaration);
+  FD = cast_or_null<FriendFunctionDecl>(ND);
+
+  // If this is a dependent context, just add the decl to the
+  // class's decl list and don't both with the lookup tables.  This
+  // doesn't affect lookup because any call that might find this
+  // function via ADL necessarily has to involve dependently-typed
+  // arguments and hence can't be resolved until
+  // template-instantiation anyway.
+  if (CurContext->isDependentContext())
+    CurContext->addHiddenDecl(FD);
+  else
+    CurContext->addDecl(FD);
 
   return DeclPtrTy::make(FD);
 }