SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
- assert(TUK == TUK_Declaration || TUK == TUK_Definition);
+ assert(TUK != TUK_Reference && "References are not specializations");
// Find the class template we're specializing
TemplateName Name = TemplateD.getAsVal<TemplateName>();
// Check the validity of the template headers that introduce this
// template.
+ // FIXME: We probably shouldn't complain about these headers for
+ // friend declarations.
TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
(TemplateParameterList**)TemplateParameterLists.get(),
}
}
}
- } else if (!TemplateParams)
+ } else if (!TemplateParams && TUK != TUK_Friend)
Diag(KWLoc, diag::err_template_spec_needs_header)
<< CodeModificationHint::CreateInsertion(KWLoc, "template<> ");
AS_none);
}
+ // FIXME: Diagnose friend partial specializations
+
// FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
// Check whether we can declare a class template specialization in
// the current scope.
- if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
+ if (TUK != TUK_Friend &&
+ CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
TemplateNameLoc,
SS.getRange(),
isPartialSpecialization,
// The canonical type
QualType CanonType;
- if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
+ if (PrevDecl &&
+ (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
+ TUK == TUK_Friend)) {
// Since the only prior class template specialization with these
- // arguments was referenced but not declared, reuse that
+ // arguments was referenced but not declared, or we're only
+ // referencing this specialization as a friend, reuse that
// declaration node as our own, updating its source location to
// reflect our new declaration.
Specialization = PrevDecl;
}
} else {
// Create a new class template specialization declaration node for
- // this explicit specialization.
+ // this explicit specialization or friend declaration.
Specialization
= ClassTemplateSpecializationDecl::Create(Context,
ClassTemplate->getDeclContext(),
CanonType = Context.getTypeDeclType(Specialization);
}
- // Note that this is an explicit specialization.
- Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+ // If this is not a friend, note that this is an explicit specialization.
+ if (TUK != TUK_Friend)
+ Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
TemplateArgs.data(),
TemplateArgs.size(),
CanonType);
- Specialization->setTypeAsWritten(WrittenTy);
+ if (TUK != TUK_Friend)
+ Specialization->setTypeAsWritten(WrittenTy);
TemplateArgsIn.release();
// C++ [temp.expl.spec]p9:
if (TUK == TUK_Definition)
Specialization->startDefinition();
- // Add the specialization into its lexical context, so that it can
- // be seen when iterating through the list of declarations in that
- // context. However, specializations are not found by name lookup.
- CurContext->addDecl(Specialization);
+ if (TUK == TUK_Friend) {
+ FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+ TemplateNameLoc,
+ WrittenTy.getTypePtr(),
+ /*FIXME:*/KWLoc);
+ Friend->setAccess(AS_public);
+ CurContext->addDecl(Friend);
+ } else {
+ // Add the specialization into its lexical context, so that it can
+ // be seen when iterating through the list of declarations in that
+ // context. However, specializations are not found by name lookup.
+ CurContext->addDecl(Specialization);
+ }
return DeclPtrTy::make(Specialization);
}