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);
}