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/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index aac79e9..ab5578b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2353,6 +2353,7 @@
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+ bool isFriend = D.getDeclSpec().isFriendSpecified();
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
@@ -2382,7 +2383,20 @@
bool isVirtualOkay = false;
FunctionDecl *NewFD;
- if (D.getKind() == Declarator::DK_Constructor) {
+ if (isFriend) {
+ // DC is the namespace in which the function is being declared.
+ assert(DC->isFileContext() || PrevDecl);
+
+ // C++ [class.friend]p5
+ // 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,
+ isInline,
+ D.getDeclSpec().getFriendSpecLoc());
+ } else if (D.getKind() == Declarator::DK_Constructor) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
@@ -2643,7 +2657,7 @@
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
- if (!IsFunctionDefinition) {
+ if (!IsFunctionDefinition && !isFriend) {
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
@@ -4142,7 +4156,7 @@
// If a friend declaration in a non-local class first declares a
// class or function, the friend class or function is a member of
// the innermost enclosing namespace.
- while (!SearchDC->isNamespace() && !SearchDC->isTranslationUnit())
+ while (!SearchDC->isFileContext())
SearchDC = SearchDC->getParent();
// The entity of a decl scope is a DeclContext; see PushDeclContext.