diff options
author | Enea Zaffanella <zaffanella@cs.unipr.it> | 2013-01-31 09:54:08 +0000 |
---|---|---|
committer | Enea Zaffanella <zaffanella@cs.unipr.it> | 2013-01-31 09:54:08 +0000 |
commit | eb22c870aca64819ec919607c6328b8ded2480c0 (patch) | |
tree | a78d4cb0d2f2379f5520cd60afa501be603167bd /clang | |
parent | 102846714a88538554c7ff69773140152e6135e9 (diff) | |
download | bcm5719-llvm-eb22c870aca64819ec919607c6328b8ded2480c0.tar.gz bcm5719-llvm-eb22c870aca64819ec919607c6328b8ded2480c0.zip |
Added outer template parameter lists to friend type AST nodes.
llvm-svn: 174050
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/DeclFriend.h | 50 | ||||
-rw-r--r-- | clang/lib/AST/DeclFriend.cpp | 21 | ||||
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 15 |
6 files changed, 84 insertions, 28 deletions
diff --git a/clang/include/clang/AST/DeclFriend.h b/clang/include/clang/AST/DeclFriend.h index 37e45868b57..253c23c199a 100644 --- a/clang/include/clang/AST/DeclFriend.h +++ b/clang/include/clang/AST/DeclFriend.h @@ -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()); } diff --git a/clang/lib/AST/DeclFriend.cpp b/clang/lib/AST/DeclFriend.cpp index 553d170fc3d..37a812e71aa 100644 --- a/clang/lib/AST/DeclFriend.cpp +++ b/clang/lib/AST/DeclFriend.cpp @@ -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); } + diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 6057f601362..f863bb49d57 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -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()); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c0697f117cd..9ef91467dac 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 5fe1011579a..469b3938ee5 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -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); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 7be49a283f8..c2e1513586f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -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); |