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/Sema.h b/lib/Sema/Sema.h
index 905b2e9..c592242 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2143,6 +2143,9 @@
   virtual DeclPtrTy ActOnFriendDecl(Scope *S,
                           llvm::PointerUnion<const DeclSpec*,Declarator*> D,
                                     bool IsDefinition);
+  DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec& DS,
+                                bool IsDefinition);
+  DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator& D, bool IsDefinition);
 
   QualType CheckConstructorDeclarator(Declarator &D, QualType R,
                                       FunctionDecl::StorageClass& SC);
@@ -2955,6 +2958,7 @@
                                      bool Recursive = false);
 
   NamedDecl *FindInstantiatedDecl(NamedDecl *D);
+  DeclContext *FindInstantiatedContext(DeclContext *DC);
     
   // Objective-C declarations.
   virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
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);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 602caf2..4874c92 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3567,116 +3567,124 @@
 Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S,
                        llvm::PointerUnion<const DeclSpec*,Declarator*> DU,
                                       bool IsDefinition) {
-  Declarator *D = DU.dyn_cast<Declarator*>();
-  const DeclSpec &DS = (D ? D->getDeclSpec() : *DU.get<const DeclSpec*>());
+  if (DU.is<Declarator*>())
+    return ActOnFriendFunctionDecl(S, *DU.get<Declarator*>(), IsDefinition);
+  else
+    return ActOnFriendTypeDecl(S, *DU.get<const DeclSpec*>(), IsDefinition);
+}
+
+Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
+                                          const DeclSpec &DS,
+                                          bool IsDefinition) {
+  SourceLocation Loc = DS.getSourceRange().getBegin();
 
   assert(DS.isFriendSpecified());
   assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
 
-  // If there's no declarator, then this can only be a friend class
-  // declaration (or else it's just syntactically invalid).
-  if (!D) {
-    SourceLocation Loc = DS.getSourceRange().getBegin();
+  // Check to see if the decl spec was syntactically like "struct foo".
+  RecordDecl *RD = NULL;
 
-    QualType T;
-    DeclContext *DC;
+  switch (DS.getTypeSpecType()) {
+  case DeclSpec::TST_class:
+  case DeclSpec::TST_struct:
+  case DeclSpec::TST_union:
+    RD = dyn_cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
+    if (!RD) return DeclPtrTy();
 
-    // In C++0x, we just accept any old type.
-    if (getLangOptions().CPlusPlus0x) {
-      bool invalid = false;
-      QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
-      if (invalid)
-        return DeclPtrTy();
+    // The parser doesn't quite handle
+    //   friend class A {}
+    // as we'd like, because it might have been the (valid) prefix of
+    //   friend class A {} foo();
+    // So even in C++0x mode we don't want to 
+    IsDefinition |= RD->isDefinition();
+    break;
 
-      // The semantic context in which to create the decl.  If it's not
-      // a record decl (or we don't yet know if it is), create it in the
-      // current context.
-      DC = CurContext;
-      if (const RecordType *RT = T->getAs<RecordType>())
-        DC = RT->getDecl()->getDeclContext();
-
-    // The C++98 rules are somewhat more complex.
-    } else {
-      // C++ [class.friend]p2:
-      //   An elaborated-type-specifier shall be used in a friend declaration
-      //   for a class.*
-      //   * The class-key of the elaborated-type-specifier is required.
-      CXXRecordDecl *RD = 0;
-    
-      switch (DS.getTypeSpecType()) {
-      case DeclSpec::TST_class:
-      case DeclSpec::TST_struct:
-      case DeclSpec::TST_union:
-        RD = dyn_cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
-        if (!RD) return DeclPtrTy();
-        break;
-        
-      case DeclSpec::TST_typename:
-        if (const RecordType *RT = 
-            ((const Type*) DS.getTypeRep())->getAs<RecordType>())
-          RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
-        // fallthrough
-      default:
-        if (RD) {
-          Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
-            << (RD->isUnion())
-            << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
-                                         RD->isUnion() ? " union" : " class");
-          return DeclPtrTy::make(RD);
-        }
-
-        Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
-          << DS.getSourceRange();
-        return DeclPtrTy();
-      }
-
-      // The record declaration we get from friend declarations is not
-      // canonicalized; see ActOnTag.
-
-      // C++ [class.friend]p2: A class shall not be defined inside
-      //   a friend declaration.
-      if (RD->isDefinition())
-        Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
-          << RD->getSourceRange();
-
-      // C++98 [class.friend]p1: A friend of a class is a function
-      //   or class that is not a member of the class . . .
-      // But that's a silly restriction which nobody implements for
-      // inner classes, and C++0x removes it anyway, so we only report
-      // this (as a warning) if we're being pedantic.
-      // 
-      // Also, definitions currently get treated in a way that causes
-      // this error, so only report it if we didn't see a definition.
-      else if (RD->getDeclContext() == CurContext &&
-               !getLangOptions().CPlusPlus0x)
-        Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
-      
-      T = QualType(RD->getTypeForDecl(), 0);
-      DC = RD->getDeclContext();
-    }
-
-    FriendClassDecl *FCD = FriendClassDecl::Create(Context, DC, Loc, T,
-                                                   DS.getFriendSpecLoc());
-    FCD->setLexicalDeclContext(CurContext);
-
-    if (CurContext->isDependentContext())
-      CurContext->addHiddenDecl(FCD);
-    else
-      CurContext->addDecl(FCD);
-
-    return DeclPtrTy::make(FCD);
+  default: break;
   }
 
-  // We have a declarator.
-  assert(D);
+  FriendDecl::FriendUnion FU = RD;
 
-  SourceLocation Loc = D->getIdentifierLoc();
+  // C++ [class.friend]p2:
+  //   An elaborated-type-specifier shall be used in a friend declaration
+  //   for a class.*
+  //   * The class-key of the elaborated-type-specifier is required.
+  // So if we didn't get a record decl above, we're invalid in C++98 mode.
+  if (!RD) {
+    bool invalid = false;
+    QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
+    if (invalid) return DeclPtrTy();
+    
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      FU = RD = cast<CXXRecordDecl>(RT->getDecl());
+      
+      // Untagged typenames are invalid prior to C++0x, but we can
+      // suggest an easy fix which should work.
+      if (!getLangOptions().CPlusPlus0x) {
+        Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
+          << (RD->isUnion())
+          << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
+                                        RD->isUnion() ? " union" : " class");
+        return DeclPtrTy();
+      }
+    }else if (!getLangOptions().CPlusPlus0x) {
+      Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
+          << DS.getSourceRange();
+      return DeclPtrTy();
+    }else {
+      FU = T.getTypePtr();
+    }
+  }
+
+  assert(FU && "should have a friend decl/type by here!");
+
+  // C++ [class.friend]p2: A class shall not be defined inside
+  //   a friend declaration.
+  if (IsDefinition) {
+    Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
+      << DS.getSourceRange();
+    return DeclPtrTy();
+  }
+
+  // C++98 [class.friend]p1: A friend of a class is a function
+  //   or class that is not a member of the class . . .
+  // But that's a silly restriction which nobody implements for
+  // inner classes, and C++0x removes it anyway, so we only report
+  // this (as a warning) if we're being pedantic.
+  if (!getLangOptions().CPlusPlus0x) {
+    assert(RD && "must have a record decl in C++98 mode");
+    if (RD->getDeclContext() == CurContext)
+      Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
+  }
+
+  FriendDecl *FD = FriendDecl::Create(Context, CurContext, Loc, FU,
+                                      DS.getFriendSpecLoc());
+  CurContext->addDecl(FD);
+
+  return DeclPtrTy::make(FD);
+}
+
+Sema::DeclPtrTy Sema::ActOnFriendFunctionDecl(Scope *S,
+                                              Declarator &D,
+                                              bool IsDefinition) {
+  const DeclSpec &DS = D.getDeclSpec();
+
+  assert(DS.isFriendSpecified());
+  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+  SourceLocation Loc = D.getIdentifierLoc();
   DeclaratorInfo *DInfo = 0;
-  QualType T = GetTypeForDeclarator(*D, S, &DInfo);
+  QualType T = GetTypeForDeclarator(D, S, &DInfo);
 
   // C++ [class.friend]p1
   //   A friend of a class is a function or class....
   // Note that this sees through typedefs, which is intended.
+  // It *doesn't* see through dependent types, which is correct
+  // according to [temp.arg.type]p3:
+  //   If a declaration acquires a function type through a
+  //   type dependent on a template-parameter and this causes
+  //   a declaration that does not use the syntactic form of a
+  //   function declarator to have a function type, the program
+  //   is ill-formed.
   if (!T->isFunctionType()) {
     Diag(Loc, diag::err_unexpected_friend);
 
@@ -3700,8 +3708,8 @@
   //    declared as a friend, scopes outside the innermost enclosing
   //    namespace scope are not considered.
 
-  CXXScopeSpec &ScopeQual = D->getCXXScopeSpec();
-  DeclarationName Name = GetNameForDeclarator(*D);
+  CXXScopeSpec &ScopeQual = D.getCXXScopeSpec();
+  DeclarationName Name = GetNameForDeclarator(D);
   assert(Name);
 
   // The existing declaration we found.
@@ -3727,7 +3735,7 @@
     // TODO: better diagnostics for this case.  Suggesting the right
     // qualified scope would be nice...
     if (!Dec || Dec->getDeclContext() != DC) {
-      D->setInvalidType();
+      D.setInvalidType();
       Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
       return DeclPtrTy();
     }
@@ -3789,36 +3797,36 @@
     assert(DC->isFileContext());
 
     // This implies that it has to be an operator or function.
-    if (D->getKind() == Declarator::DK_Constructor ||
-        D->getKind() == Declarator::DK_Destructor ||
-        D->getKind() == Declarator::DK_Conversion) {
+    if (D.getKind() == Declarator::DK_Constructor ||
+        D.getKind() == Declarator::DK_Destructor ||
+        D.getKind() == Declarator::DK_Conversion) {
       Diag(Loc, diag::err_introducing_special_friend) <<
-        (D->getKind() == Declarator::DK_Constructor ? 0 :
-         D->getKind() == Declarator::DK_Destructor ? 1 : 2);
+        (D.getKind() == Declarator::DK_Constructor ? 0 :
+         D.getKind() == Declarator::DK_Destructor ? 1 : 2);
       return DeclPtrTy();
     }
   }
 
-  NamedDecl *ND = ActOnFunctionDeclarator(S, *D, DC, T, DInfo,
+  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo,
                                           /* PrevDecl = */ FD,
                                           MultiTemplateParamsArg(*this),
                                           IsDefinition,
                                           Redeclaration);
-  FD = cast_or_null<FriendFunctionDecl>(ND);
+  if (!ND) return DeclPtrTy();
+  FD = cast<FunctionDecl>(ND);
 
   assert(FD->getDeclContext() == DC);
   assert(FD->getLexicalDeclContext() == CurContext);
 
-  // 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);
+  // We only add the function declaration to the lookup tables, not
+  // the decl list, and only if the context isn't dependent.
+  if (!CurContext->isDependentContext())
+    DC->makeDeclVisibleInContext(FD);
+
+  FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
+                                       D.getIdentifierLoc(), FD,
+                                       DS.getFriendSpecLoc());
+  CurContext->addDecl(FrD);
 
   return DeclPtrTy::make(FD);
 }
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 6627499..4a699de 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -643,6 +643,13 @@
          "Can perform only C++ lookup");
   unsigned IDNS 
     = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
+
+  // If we're testing for redeclarations, also look in the friend namespaces.
+  if (RedeclarationOnly) {
+    if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend;
+    if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend;
+  }
+
   Scope *Initial = S;
   DeclContext *OutOfLineCtx = 0;
   IdentifierResolver::iterator 
@@ -1769,9 +1776,9 @@
     DeclContext::lookup_iterator I, E;
     for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
       Decl *D = *I;
-      // Only count friend declarations which were declared in
-      // associated classes.
-      if (D->isInIdentifierNamespace(Decl::IDNS_Friend)) {
+      // If the only declaration here is an ordinary friend, consider
+      // it only if it was declared in an associated classes.
+      if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
         DeclContext *LexDC = D->getLexicalDeclContext();
         if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
           continue;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a0353e3..0bf832f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -45,7 +45,7 @@
     Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
     Decl *VisitEnumDecl(EnumDecl *D);
     Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
-    Decl *VisitFriendClassDecl(FriendClassDecl *D);
+    Decl *VisitFriendDecl(FriendDecl *D);
     Decl *VisitFunctionDecl(FunctionDecl *D);
     Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
     Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
@@ -250,25 +250,35 @@
   return Field;
 }
 
-Decl *TemplateDeclInstantiator::VisitFriendClassDecl(FriendClassDecl *D) {
-  QualType T = D->getFriendType();
-  if (T->isDependentType())  {
-    T = SemaRef.SubstType(T, TemplateArgs, D->getLocation(),
-                          DeclarationName());
-    assert(T.isNull() || getLangOptions().CPlusPlus0x || T->isRecordType());
+Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
+  FriendDecl::FriendUnion FU;
+
+  // Handle friend type expressions by simply substituting template
+  // parameters into the pattern type.
+  if (Type *Ty = D->getFriendType()) {
+    QualType T = SemaRef.SubstType(QualType(Ty,0), TemplateArgs,
+                                   D->getLocation(), DeclarationName());
+    if (T.isNull()) return 0;
+
+    assert(getLangOptions().CPlusPlus0x || T->isRecordType());
+    FU = T.getTypePtr();
+
+  // Handle everything else by appropriate substitution.
+  } else {
+    NamedDecl *ND = D->getFriendDecl();
+    assert(ND && "friend decl must be a decl or a type!");
+
+    Decl *NewND = Visit(ND);
+    if (!NewND) return 0;
+
+    FU = cast<NamedDecl>(NewND);
   }
-
-  // FIXME: the target context might be dependent.
-  DeclContext *DC = D->getDeclContext();
-  assert(DC->isFileContext());
-
-  FriendClassDecl *NewD =
-    FriendClassDecl::Create(SemaRef.Context, DC, D->getLocation(), T,
-                            D->getFriendLoc());
-  NewD->setLexicalDeclContext(Owner);
-
-  Owner->addDecl(NewD);
-  return NewD;
+  
+  FriendDecl *FD =
+    FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), FU,
+                       D->getFriendLoc());
+  Owner->addDecl(FD);
+  return FD;
 }
 
 Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
@@ -424,10 +434,20 @@
   if (!D->isInjectedClassName())
     Record->setInstantiationOfMemberClass(D);
 
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state.
+  if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+    Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
+
   Owner->addDecl(Record);
   return Record;
 }
 
+/// Normal class members are of more specific types and therefore
+/// don't make it here.  This function serves two purposes:
+///   1) instantiating function templates
+///   2) substituting friend declarations
+/// FIXME: preserve function definitions in case #2
 Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
   // Check whether there is already a function template specialization for
   // this declaration.
@@ -457,33 +477,27 @@
     return 0;
 
   // Build the instantiated method declaration.
-  FunctionDecl *Function;
-  if (FriendFunctionDecl* FFD = dyn_cast<FriendFunctionDecl>(D)) {
-    // The new decl's semantic context.  FIXME:  this might need
-    // to be instantiated.
-    DeclContext *DC = D->getDeclContext();
-
-    // This assert is bogus and exists only to catch cases we don't
-    // handle yet.
-    assert(!DC->isDependentContext());
-
-    Function =
-      FriendFunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
-                                 D->getDeclName(), T, D->getDeclaratorInfo(),
-                                 D->isInline(), FFD->getFriendLoc());
-    Function->setLexicalDeclContext(Owner);
-  } else {
-    Function =
-      FunctionDecl::Create(SemaRef.Context, Owner, D->getLocation(), 
+  DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext());
+  FunctionDecl *Function =
+      FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), 
                            D->getDeclName(), T, D->getDeclaratorInfo(),
                            D->getStorageClass(),
                            D->isInline(), D->hasWrittenPrototype());
-  }
-  
+  Function->setLexicalDeclContext(Owner);
+
   // Attach the parameters
   for (unsigned P = 0; P < Params.size(); ++P)
     Params[P]->setOwningFunction(Function);
   Function->setParams(SemaRef.Context, Params.data(), Params.size());
+
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state and add it to the owner.
+  if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) {
+    bool WasDeclared = (FOK == Decl::FOK_Declared);
+    Function->setObjectOfFriendDecl(WasDeclared);
+    if (!Owner->isDependentContext())
+      DC->makeDeclVisibleInContext(Function);
+  }
   
   if (InitFunctionInstantiation(Function, D))
     Function->setInvalidDecl();
@@ -502,17 +516,6 @@
                                                 InsertPos);
   }
 
-  // If this was a friend function decl, it's a member which
-  // needs to be added.
-  if (isa<FriendFunctionDecl>(Function)) {
-    // If the new context is still dependent, this declaration
-    // needs to remain hidden.
-    if (Owner->isDependentContext())
-      Owner->addHiddenDecl(Function);
-    else
-      Owner->addDecl(Function);
-  }
-
   return Function;
 }
 
@@ -1127,6 +1130,17 @@
   return 0;
 }
 
+/// \brief Finds the instantiation of the given declaration context
+/// within the current instantiation.
+///
+/// \returns NULL if there was an error
+DeclContext *Sema::FindInstantiatedContext(DeclContext* DC) {
+  if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
+    Decl* ID = FindInstantiatedDecl(D);
+    return cast_or_null<DeclContext>(ID);
+  } else return DC;
+}
+
 /// \brief Find the instantiation of the given declaration within the
 /// current instantiation.
 ///
@@ -1161,13 +1175,8 @@
     return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
   }
 
-  if (NamedDecl *ParentDecl = dyn_cast<NamedDecl>(ParentDC)) {
-    ParentDecl = FindInstantiatedDecl(ParentDecl);
-    if (!ParentDecl)
-      return 0;
-
-    ParentDC = cast<DeclContext>(ParentDecl);
-  }
+  ParentDC = FindInstantiatedContext(ParentDC);
+  if (!ParentDC) return 0;
 
   if (ParentDC != D->getDeclContext()) {
     // We performed some kind of instantiation in the parent context,