r174050 - Added outer template parameter lists to friend type AST nodes.

Enea Zaffanella zaffanella at cs.unipr.it
Thu Jan 31 01:54:08 PST 2013


Author: enea
Date: Thu Jan 31 03:54:08 2013
New Revision: 174050

URL: http://llvm.org/viewvc/llvm-project?rev=174050&view=rev
Log:
Added outer template parameter lists to friend type AST nodes.

Modified:
    cfe/trunk/include/clang/AST/DeclFriend.h
    cfe/trunk/lib/AST/DeclFriend.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclFriend.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclFriend.h?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclFriend.h (original)
+++ cfe/trunk/include/clang/AST/DeclFriend.h Thu Jan 31 03:54:08 2013
@@ -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());
   }

Modified: cfe/trunk/lib/AST/DeclFriend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclFriend.cpp?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclFriend.cpp (original)
+++ cfe/trunk/lib/AST/DeclFriend.cpp Thu Jan 31 03:54:08 2013
@@ -27,7 +27,8 @@ FriendDecl *FriendDecl::getNextFriendSlo
 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(ASTContex
     // 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);
 }
+

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Thu Jan 31 03:54:08 2013
@@ -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(Func
 
 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(L
     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());
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jan 31 03:54:08 2013
@@ -10347,7 +10347,8 @@ FriendDecl *Sema::CheckFriendTypeDecl(So
 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(Scop
     }
 
     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(Scop
   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);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Jan 31 03:54:08 2013
@@ -1262,10 +1262,12 @@ void ASTDeclReader::VisitAccessSpecDecl(
 
 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 I
     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);

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=174050&r1=174049&r2=174050&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Jan 31 03:54:08 2013
@@ -1017,12 +1017,19 @@ void ASTDeclWriter::VisitAccessSpecDecl(
 }
 
 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);





More information about the cfe-commits mailing list