forked from OSchip/llvm-project
Skeletal support for friend class templates.
llvm-svn: 81801
This commit is contained in:
parent
b4e19177cb
commit
27b5c253d8
|
@ -419,7 +419,8 @@ public:
|
|||
/// same entity may not (and probably don't) share this property.
|
||||
void setObjectOfFriendDecl(bool PreviouslyDeclared) {
|
||||
unsigned OldNS = IdentifierNamespace;
|
||||
assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary)
|
||||
assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary ||
|
||||
OldNS == (IDNS_Tag | IDNS_Ordinary))
|
||||
&& "unsupported namespace for undeclared friend");
|
||||
if (!PreviouslyDeclared) IdentifierNamespace = 0;
|
||||
|
||||
|
|
|
@ -1214,7 +1214,8 @@ public:
|
|||
|
||||
/// ActOnFriendTypeDecl - Parsed a friend type declaration.
|
||||
virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S,
|
||||
const DeclSpec &DS) {
|
||||
const DeclSpec &DS,
|
||||
bool IsTemplate) {
|
||||
return DeclPtrTy();
|
||||
}
|
||||
|
||||
|
|
|
@ -1015,11 +1015,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
ConsumeToken();
|
||||
|
||||
if (DS.isFriendSpecified()) {
|
||||
// FIXME: Friend templates are ignored for now.
|
||||
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
|
||||
return;
|
||||
|
||||
Actions.ActOnFriendTypeDecl(CurScope, DS);
|
||||
bool IsTemplate = TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate;
|
||||
Actions.ActOnFriendTypeDecl(CurScope, DS, IsTemplate);
|
||||
} else
|
||||
Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
|
||||
|
||||
|
|
|
@ -2246,7 +2246,7 @@ public:
|
|||
ExprArg AssertExpr,
|
||||
ExprArg AssertMessageExpr);
|
||||
|
||||
DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS);
|
||||
DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, bool IsTemplate);
|
||||
DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
|
||||
MultiTemplateParamsArg TemplateParams);
|
||||
|
||||
|
|
|
@ -4009,12 +4009,35 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
|
|||
}
|
||||
|
||||
Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
|
||||
const DeclSpec &DS) {
|
||||
const DeclSpec &DS,
|
||||
bool IsTemplate) {
|
||||
SourceLocation Loc = DS.getSourceRange().getBegin();
|
||||
|
||||
assert(DS.isFriendSpecified());
|
||||
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
|
||||
|
||||
// Handle friend templates specially.
|
||||
if (IsTemplate) {
|
||||
Decl *D;
|
||||
switch (DS.getTypeSpecType()) {
|
||||
default:
|
||||
// FIXME: implement this
|
||||
assert(false && "unelaborated type templates are currently unimplemented!");
|
||||
case DeclSpec::TST_class:
|
||||
case DeclSpec::TST_union:
|
||||
case DeclSpec::TST_struct:
|
||||
D = (Decl*) DS.getTypeRep();
|
||||
}
|
||||
|
||||
ClassTemplateDecl *Temp = cast<ClassTemplateDecl>(D);
|
||||
FriendDecl *FD = FriendDecl::Create(Context, CurContext, Loc, Temp,
|
||||
DS.getFriendSpecLoc());
|
||||
FD->setAccess(AS_public);
|
||||
CurContext->addDecl(FD);
|
||||
|
||||
return DeclPtrTy::make(FD);
|
||||
}
|
||||
|
||||
// Try to convert the decl specifier to a type.
|
||||
bool invalid = false;
|
||||
QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
|
||||
|
|
|
@ -556,13 +556,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
if (CheckTemplateDeclScope(S, TemplateParams))
|
||||
return true;
|
||||
|
||||
TagDecl::TagKind Kind;
|
||||
switch (TagSpec) {
|
||||
default: assert(0 && "Unknown tag type!");
|
||||
case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
|
||||
case DeclSpec::TST_union: Kind = TagDecl::TK_union; break;
|
||||
case DeclSpec::TST_class: Kind = TagDecl::TK_class; break;
|
||||
}
|
||||
TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
|
||||
assert(Kind != TagDecl::TK_enum && "can't build template of enumerated type");
|
||||
|
||||
// There is no such thing as an unnamed class template.
|
||||
if (!Name) {
|
||||
|
@ -657,6 +652,13 @@ 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?
|
||||
|
@ -678,7 +680,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
(void)T;
|
||||
|
||||
// Set the access specifier.
|
||||
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
|
||||
if (TUK == TUK_Friend)
|
||||
NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
|
||||
PrevClassTemplate != NULL);
|
||||
else
|
||||
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
|
||||
|
||||
// Set the lexical context of these templates
|
||||
NewClass->setLexicalDeclContext(CurContext);
|
||||
|
@ -690,7 +696,23 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
if (Attr)
|
||||
ProcessDeclAttributeList(S, NewClass, Attr);
|
||||
|
||||
PushOnScopeChains(NewTemplate, S);
|
||||
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)
|
||||
NewTemplate->setAccess(PrevClassTemplate->getAccess());
|
||||
|
||||
// Friend templates are visible in fairly strange ways.
|
||||
if (!CurContext->isDependentContext()) {
|
||||
DeclContext *DC = SemanticContext->getLookupContext();
|
||||
DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
|
||||
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
|
||||
PushOnScopeChains(NewTemplate, EnclosingScope,
|
||||
/* AddToContext = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
if (Invalid) {
|
||||
NewTemplate->setInvalidDecl();
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
class A {
|
||||
template <class T> friend class B;
|
||||
};
|
||||
|
Loading…
Reference in New Issue