Added outer template parameter lists to friend type AST nodes.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174050 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Enea Zaffanella 2013-01-31 09:54:08 +00:00
Родитель a8d3904ffa
Коммит 8c84028ed9
6 изменённых файлов: 84 добавлений и 28 удалений

Просмотреть файл

@ -54,22 +54,40 @@ private:
/// True if this 'friend' declaration is unsupported. Eventually we
/// will support every possible friend declaration, but for now we
/// silently ignore some and set this flag to authorize all access.
bool UnsupportedFriend;
bool UnsupportedFriend : 1;
// The number of "outer" template parameter lists in non-templatic
// (currently unsupported) friend type declarations, such as
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
// The tail-allocated friend type template parameter lists (if any).
TemplateParameterList* const *getTPLists() const {
return reinterpret_cast<TemplateParameterList* const *>(this + 1);
}
TemplateParameterList **getTPLists() {
return reinterpret_cast<TemplateParameterList**>(this + 1);
}
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL)
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
NextFriend(),
FriendLoc(FriendL),
UnsupportedFriend(false) {
UnsupportedFriend(false),
NumTPLists(FriendTypeTPLists.size()) {
for (unsigned i = 0; i < NumTPLists; ++i)
getTPLists()[i] = FriendTypeTPLists[i];
}
explicit FriendDecl(EmptyShell Empty)
: Decl(Decl::Friend, Empty), NextFriend() { }
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
: Decl(Decl::Friend, Empty), NextFriend(),
NumTPLists(NumFriendTypeTPLists) { }
FriendDecl *getNextFriend() {
if (!NextFriend.isOffset())
@ -81,8 +99,11 @@ private:
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL);
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID);
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists
= ArrayRef<TemplateParameterList*>());
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned FriendTypeNumTPLists);
/// If this friend declaration names an (untemplated but possibly
/// dependent) type, return the type; otherwise return null. This
@ -91,6 +112,13 @@ public:
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
unsigned getFriendTypeNumTemplateParameterLists() const {
return NumTPLists;
}
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
assert(N < NumTPLists);
return getTPLists()[N];
}
/// If this friend declaration doesn't name a type, return the inner
/// declaration.
@ -114,8 +142,12 @@ public:
}
return SourceRange(getFriendLoc(), ND->getLocEnd());
}
else if (TypeSourceInfo *TInfo = getFriendType())
return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc());
else if (TypeSourceInfo *TInfo = getFriendType()) {
SourceLocation StartL = (NumTPLists == 0)
? getFriendLoc()
: getTPLists()[0]->getTemplateLoc();
return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
}
else
return SourceRange(getFriendLoc(), getLocation());
}

Просмотреть файл

@ -27,7 +27,8 @@ FriendDecl *FriendDecl::getNextFriendSlowCase() {
FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
FriendUnion Friend,
SourceLocation FriendL) {
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists) {
#ifndef NDEBUG
if (Friend.is<NamedDecl*>()) {
NamedDecl *D = Friend.get<NamedDecl*>();
@ -40,15 +41,25 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
// to the original declaration when instantiating members.
assert(D->getFriendObjectKind() ||
(cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
// These template parameters are for friend types only.
assert(FriendTypeTPLists.size() == 0);
}
#endif
FriendDecl *FD = new (C) FriendDecl(DC, L, Friend, FriendL);
std::size_t Size = sizeof(FriendDecl)
+ FriendTypeTPLists.size() * sizeof(TemplateParameterList*);
void *Mem = C.Allocate(Size);
FriendDecl *FD = new (Mem) FriendDecl(DC, L, Friend, FriendL,
FriendTypeTPLists);
cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
return FD;
}
FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendDecl));
return new (Mem) FriendDecl(EmptyShell());
FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned FriendTypeNumTPLists) {
std::size_t Size = sizeof(FriendDecl)
+ FriendTypeNumTPLists * sizeof(TemplateParameterList*);
void *Mem = AllocateDeserializedDecl(C, ID, Size);
return new (Mem) FriendDecl(EmptyShell(), FriendTypeNumTPLists);
}

Просмотреть файл

@ -83,7 +83,7 @@ namespace {
void VisitUsingShadowDecl(UsingShadowDecl *D);
void PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args);
const TemplateArgumentList *Args = 0);
void prettyPrintAttributes(Decl *D);
};
}
@ -580,6 +580,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
if (TypeSourceInfo *TSI = D->getFriendType()) {
unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
for (unsigned i = 0; i < NumTPLists; ++i)
PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
Out << "friend ";
Out << " " << TSI->getType().getAsString(Policy);
}
@ -771,8 +774,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
Visit(*D->decls_begin());
}
void DeclPrinter::PrintTemplateParameters(
const TemplateParameterList *Params, const TemplateArgumentList *Args = 0) {
void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args) {
assert(Params);
assert(!Args || Params->size() == Args->size());

Просмотреть файл

@ -10347,7 +10347,8 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
IdentifierInfo *Name,
SourceLocation NameLoc,
AttributeList *Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
@ -10431,7 +10432,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
}
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
TSI, FriendLoc);
TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
return Friend;
@ -10453,7 +10454,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
TL.setNameLoc(NameLoc);
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
TSI, FriendLoc);
TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
Friend->setUnsupportedFriend(true);
CurContext->addDecl(Friend);

Просмотреть файл

@ -1262,10 +1262,12 @@ void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
VisitDecl(D);
if (Record[Idx++])
D->Friend = GetTypeSourceInfo(Record, Idx);
else
if (Record[Idx++]) // hasFriendDecl
D->Friend = ReadDeclAs<NamedDecl>(Record, Idx);
else
D->Friend = GetTypeSourceInfo(Record, Idx);
for (unsigned i = 0; i != D->NumTPLists; ++i)
D->getTPLists()[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
D->NextFriend = Record[Idx++];
D->UnsupportedFriend = (Record[Idx++] != 0);
D->FriendLoc = ReadSourceLocation(Record, Idx);
@ -2003,7 +2005,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = AccessSpecDecl::CreateDeserialized(Context, ID);
break;
case DECL_FRIEND:
D = FriendDecl::CreateDeserialized(Context, ID);
D = FriendDecl::CreateDeserialized(Context, ID, Record[Idx++]);
break;
case DECL_FRIEND_TEMPLATE:
D = FriendTemplateDecl::CreateDeserialized(Context, ID);

Просмотреть файл

@ -1017,12 +1017,19 @@ void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
}
void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) {
// Record the number of friend type template parameter lists here
// so as to simplify memory allocation during deserialization.
Record.push_back(D->NumTPLists);
VisitDecl(D);
Record.push_back(D->Friend.is<TypeSourceInfo*>());
if (D->Friend.is<TypeSourceInfo*>())
Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record);
bool hasFriendDecl = D->Friend.is<NamedDecl*>();
Record.push_back(hasFriendDecl);
if (hasFriendDecl)
Writer.AddDeclRef(D->getFriendDecl(), Record);
else
Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
Writer.AddTypeSourceInfo(D->getFriendType(), Record);
for (unsigned i = 0; i < D->NumTPLists; ++i)
Writer.AddTemplateParameterList(D->getFriendTypeTemplateParameterList(i),
Record);
Writer.AddDeclRef(D->getNextFriend(), Record);
Record.push_back(D->UnsupportedFriend);
Writer.AddSourceLocation(D->FriendLoc, Record);