diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-26 06:47:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-26 06:47:28 +0000 |
commit | d85bea2affdd59d83d1be7d24b97f436484c3625 (patch) | |
tree | c54ffce5ad16d80e08ccbb6ebfd047206c93ac1a /lib/Sema/SemaTemplate.cpp | |
parent | 74e3c92aa3eb1750ac2eb89994046eb69db39100 (diff) |
Rework the Parse-Sema interaction for friends to better support friend
class templates. We now treat friend class templates much more like
normal class templates, except that they still get special name lookup
rules. Fixes PR5057 and eliminates a bunch of spurious diagnostics in
<iostream>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82848 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d5fb7e82a8..72274525fd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -579,6 +579,18 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName, true); + } else if (TUK == TUK_Friend) { + // C++ [namespace.memdef]p3: + // [...] When looking for a prior declaration of a class or a function + // declared as a friend, and when the name of the friend class or + // function is neither a qualified name nor a template-id, scopes outside + // the innermost enclosing namespace scope are not considered. + SemanticContext = CurContext; + while (!SemanticContext->isFileContext()) + SemanticContext = SemanticContext->getLookupParent(); + + Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName, + true); } else { SemanticContext = CurContext; Previous = LookupName(S, Name, LookupOrdinaryName, true); @@ -654,13 +666,6 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: If we had a scope specifier, we better have a previous template // declaration! - // If this is a friend declaration of an undeclared template, - // create the template in the innermost namespace scope. - if (TUK == TUK_Friend && !PrevClassTemplate) { - while (!SemanticContext->isFileContext()) - SemanticContext = SemanticContext->getParent(); - } - CXXRecordDecl *NewClass = CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc, PrevClassTemplate? @@ -682,10 +687,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, (void)T; // Set the access specifier. - if (TUK == TUK_Friend) - NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */ - PrevClassTemplate != NULL); - else + if (!Invalid && TUK != TUK_Friend) SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); // Set the lexical context of these templates @@ -701,11 +703,14 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK != TUK_Friend) PushOnScopeChains(NewTemplate, S); else { - // We might be replacing an existing declaration in the lookup tables; - // if so, borrow its access specifier. - if (PrevClassTemplate) + if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) { NewTemplate->setAccess(PrevClassTemplate->getAccess()); + NewClass->setAccess(PrevClassTemplate->getAccess()); + } + NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */ + PrevClassTemplate != NULL); + // Friend templates are visible in fairly strange ways. if (!CurContext->isDependentContext()) { DeclContext *DC = SemanticContext->getLookupContext(); @@ -714,6 +719,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, PushOnScopeChains(NewTemplate, EnclosingScope, /* AddToContext = */ false); } + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, + NewClass->getLocation(), + NewTemplate, + /*FIXME:*/NewClass->getLocation()); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); } if (Invalid) { |