зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
a8d3904ffa
Коммит
8c84028ed9
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче