]> granicus.if.org Git - clang/commitdiff
Added outer template parameter lists to friend type AST nodes.
authorEnea Zaffanella <zaffanella@cs.unipr.it>
Thu, 31 Jan 2013 09:54:08 +0000 (09:54 +0000)
committerEnea Zaffanella <zaffanella@cs.unipr.it>
Thu, 31 Jan 2013 09:54:08 +0000 (09:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174050 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclFriend.h
lib/AST/DeclFriend.cpp
lib/AST/DeclPrinter.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp

index 37e45868b57cdb2f1df8a918e98c289188a48129..253c23c199af920830b66099d11cfb9c746a5008 100644 (file)
@@ -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());
   }
index 553d170fc3d5112b4bed98c60b420c596cb72ff5..37a812e71aae0b1c4b098d69ee09275f141e90fe 100644 (file)
@@ -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);
 }
+
index 6057f601362029394d9816c12fb0ad5c94bd0d55..f863bb49d57c71a3f12fcfb3395e42d5da089cde 100644 (file)
@@ -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());
 
index c0697f117cdf79a45792abb3e105376955a280e6..9ef91467dac5bef8e1ebb94751e4523a1ef422e0 100644 (file)
@@ -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);
index 5fe1011579a776659cc48238b896f6fdb8530b54..469b3938ee5a35297862bc97451ae563b808d024 100644 (file)
@@ -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);
index 7be49a283f835e242c959011ea35435c541c5367..c2e1513586fa6c8c20f02baf5695f7a9f54f93d4 100644 (file)
@@ -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);