diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index eb62b6a9db..62ac3bb455 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6344,12 +6344,26 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, // There are four cases here. // - There's no scope specifier, in which case we just go to the - // appropriate namespace and create a function or function template + // appropriate scope and look for a function or function template // there as appropriate. // Recover from invalid scope qualifiers as if they just weren't there. if (SS.isInvalid() || !SS.isSet()) { - // Walk out to the nearest namespace scope looking for matches. - + // C++0x [namespace.memdef]p3: + // If the name in a friend declaration is neither qualified nor + // a template-id and the declaration is a function or an + // elaborated-type-specifier, the lookup to determine whether + // the entity has been previously declared shall not consider + // any scopes outside the innermost enclosing namespace. + // C++0x [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. For a friend function + // declaration, if there is no prior declaration, the program is + // ill-formed. + bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass(); + + // Find the appropriate context according to the above. DC = CurContext; while (true) { // Skip class contexts. If someone can cite chapter and verse @@ -6365,9 +6379,9 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, LookupQualifiedName(Previous, DC); // TODO: decide what we think about using declarations. - if (!Previous.empty()) + if (isLocal || !Previous.empty()) break; - + if (DC->isFileContext()) break; DC = DC->getParent(); } @@ -6381,6 +6395,8 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, && !getLangOptions().CPlusPlus0x) Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + S = getScopeForDeclContext(S, DC); + // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. @@ -6425,7 +6441,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); } - if (DC->isFileContext()) { + if (!DC->isRecord()) { // This implies that it has to be an operator or function. if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || D.getName().getKind() == UnqualifiedId::IK_DestructorName || |