diff options
author | John McCall <rjmccall@apple.com> | 2010-04-13 20:37:33 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-04-13 20:37:33 +0000 |
commit | 77e8b11524187f81548450e9e2ad9dd0e7200909 (patch) | |
tree | 7b8b1c4517ae74c319931df7d31e3c99d6a3fa47 /lib/Sema/SemaTemplate.cpp | |
parent | c034974f103873bdccc91da99a30ab30295b5226 (diff) |
Support befriending members of class template specializations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101173 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 828085b8bc..9816e76530 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1229,6 +1229,10 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, /// /// \param NumParamLists the number of template parameter lists in ParamLists. /// +/// \param IsFriend Whether to apply the slightly different rules for +/// matching template parameters to scope specifiers in friend +/// declarations. +/// /// \param IsExplicitSpecialization will be set true if the entity being /// declared is an explicit specialization, false otherwise. /// @@ -1243,6 +1247,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, const CXXScopeSpec &SS, TemplateParameterList **ParamLists, unsigned NumParamLists, + bool IsFriend, bool &IsExplicitSpecialization) { IsExplicitSpecialization = false; @@ -1308,6 +1313,13 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, if (Idx >= NumParamLists) { // We have a template-id without a corresponding template parameter // list. + + // ...which is fine if this is a friend declaration. + if (IsFriend) { + IsExplicitSpecialization = true; + break; + } + if (DependentTemplateId) { // FIXME: the location information here isn't great. Diag(SS.getRange().getBegin(), @@ -3538,6 +3550,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, (TemplateParameterList**)TemplateParameterLists.get(), TemplateParameterLists.size(), + TUK == TUK_Friend, isExplicitSpecialization); if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -4302,7 +4315,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, bool Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); - + // Try to find the member we are instantiating. NamedDecl *Instantiation = 0; NamedDecl *InstantiatedFrom = 0; @@ -4348,6 +4361,25 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // this mismatch later. return false; } + + // If this is a friend, just bail out here before we start turning + // things into explicit specializations. + if (Member->getFriendObjectKind() != Decl::FOK_None) { + // Preserve instantiation information. + if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) { + cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction( + cast<CXXMethodDecl>(InstantiatedFrom), + cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind()); + } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) { + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( + cast<CXXRecordDecl>(InstantiatedFrom), + cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind()); + } + + Previous.clear(); + Previous.addDecl(Instantiation); + return false; + } // Make sure that this is a specialization of a member. if (!InstantiatedFrom) { |