Support befriending members of class template specializations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101173 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 828085b..9816e76 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1229,6 +1229,10 @@
///
/// \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 @@
const CXXScopeSpec &SS,
TemplateParameterList **ParamLists,
unsigned NumParamLists,
+ bool IsFriend,
bool &IsExplicitSpecialization) {
IsExplicitSpecialization = false;
@@ -1308,6 +1313,13 @@
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 @@
= MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
(TemplateParameterList**)TemplateParameterLists.get(),
TemplateParameterLists.size(),
+ TUK == TUK_Friend,
isExplicitSpecialization);
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
@@ -4302,7 +4315,7 @@
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 @@
// 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) {