- //===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file defines the section of the AST representing C++ friend 
- // declarations. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_AST_DECLFRIEND_H 
- #define LLVM_CLANG_AST_DECLFRIEND_H 
-   
- #include "clang/AST/Decl.h" 
- #include "clang/AST/DeclBase.h" 
- #include "clang/AST/DeclCXX.h" 
- #include "clang/AST/DeclTemplate.h" 
- #include "clang/AST/ExternalASTSource.h" 
- #include "clang/AST/TypeLoc.h" 
- #include "clang/Basic/LLVM.h" 
- #include "clang/Basic/SourceLocation.h" 
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/ADT/PointerUnion.h" 
- #include "llvm/Support/Casting.h" 
- #include "llvm/Support/Compiler.h" 
- #include "llvm/Support/TrailingObjects.h" 
- #include <cassert> 
- #include <iterator> 
-   
- namespace clang { 
-   
- class ASTContext; 
-   
- /// FriendDecl - Represents the declaration of a friend entity, 
- /// which can be a function, a type, or a templated function or type. 
- /// For example: 
- /// 
- /// @code 
- /// template <typename T> class A { 
- ///   friend int foo(T); 
- ///   friend class B; 
- ///   friend T; // only in C++0x 
- ///   template <typename U> friend class C; 
- ///   template <typename U> friend A& operator+=(A&, const U&) { ... } 
- /// }; 
- /// @endcode 
- /// 
- /// The semantic context of a friend decl is its declaring class. 
- class FriendDecl final 
-     : public Decl, 
-       private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> { 
-   virtual void anchor(); 
-   
- public: 
-   using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>; 
-   
- private: 
-   friend class CXXRecordDecl; 
-   friend class CXXRecordDecl::friend_iterator; 
-   
-   // The declaration that's a friend of this class. 
-   FriendUnion Friend; 
-   
-   // A pointer to the next friend in the sequence. 
-   LazyDeclPtr NextFriend; 
-   
-   // Location of the 'friend' specifier. 
-   SourceLocation FriendLoc; 
-   
-   /// 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. 
-   unsigned 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; 
-   
-   FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, 
-              SourceLocation FriendL, 
-              ArrayRef<TemplateParameterList *> FriendTypeTPLists) 
-       : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL), 
-         UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) { 
-     for (unsigned i = 0; i < NumTPLists; ++i) 
-       getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i]; 
-   } 
-   
-   FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) 
-       : Decl(Decl::Friend, Empty), UnsupportedFriend(false), 
-         NumTPLists(NumFriendTypeTPLists) {} 
-   
-   FriendDecl *getNextFriend() { 
-     if (!NextFriend.isOffset()) 
-       return cast_or_null<FriendDecl>(NextFriend.get(nullptr)); 
-     return getNextFriendSlowCase(); 
-   } 
-   
-   FriendDecl *getNextFriendSlowCase(); 
-   
- public: 
-   friend class ASTDeclReader; 
-   friend class ASTDeclWriter; 
-   friend class ASTNodeImporter; 
-   friend TrailingObjects; 
-   
-   static FriendDecl * 
-   Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, 
-          SourceLocation FriendL, 
-          ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt); 
-   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 
-   /// is used for elaborated-type-specifiers and, in C++0x, for 
-   /// arbitrary friend type declarations. 
-   TypeSourceInfo *getFriendType() const { 
-     return Friend.dyn_cast<TypeSourceInfo*>(); 
-   } 
-   
-   unsigned getFriendTypeNumTemplateParameterLists() const { 
-     return NumTPLists; 
-   } 
-   
-   TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { 
-     assert(N < NumTPLists); 
-     return getTrailingObjects<TemplateParameterList *>()[N]; 
-   } 
-   
-   /// If this friend declaration doesn't name a type, return the inner 
-   /// declaration. 
-   NamedDecl *getFriendDecl() const { 
-     return Friend.dyn_cast<NamedDecl *>(); 
-   } 
-   
-   /// Retrieves the location of the 'friend' keyword. 
-   SourceLocation getFriendLoc() const { 
-     return FriendLoc; 
-   } 
-   
-   /// Retrieves the source range for the friend declaration. 
-   SourceRange getSourceRange() const override LLVM_READONLY { 
-     if (NamedDecl *ND = getFriendDecl()) { 
-       if (const auto *FD = dyn_cast<FunctionDecl>(ND)) 
-         return FD->getSourceRange(); 
-       if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) 
-         return FTD->getSourceRange(); 
-       if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 
-         return CTD->getSourceRange(); 
-       if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) { 
-         if (DD->getOuterLocStart() != DD->getInnerLocStart()) 
-           return DD->getSourceRange(); 
-       } 
-       return SourceRange(getFriendLoc(), ND->getEndLoc()); 
-     } 
-     else if (TypeSourceInfo *TInfo = getFriendType()) { 
-       SourceLocation StartL = 
-           (NumTPLists == 0) ? getFriendLoc() 
-                             : getTrailingObjects<TemplateParameterList *>()[0] 
-                                   ->getTemplateLoc(); 
-       return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); 
-     } 
-     else 
-       return SourceRange(getFriendLoc(), getLocation()); 
-   } 
-   
-   /// Determines if this friend kind is unsupported. 
-   bool isUnsupportedFriend() const { 
-     return UnsupportedFriend; 
-   } 
-   void setUnsupportedFriend(bool Unsupported) { 
-     UnsupportedFriend = Unsupported; 
-   } 
-   
-   // Implement isa/cast/dyncast/etc. 
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == Decl::Friend; } 
- }; 
-   
- /// An iterator over the friend declarations of a class. 
- class CXXRecordDecl::friend_iterator { 
-   friend class CXXRecordDecl; 
-   
-   FriendDecl *Ptr; 
-   
-   explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {} 
-   
- public: 
-   friend_iterator() = default; 
-   
-   using value_type = FriendDecl *; 
-   using reference = FriendDecl *; 
-   using pointer = FriendDecl *; 
-   using difference_type = int; 
-   using iterator_category = std::forward_iterator_tag; 
-   
-   reference operator*() const { return Ptr; } 
-   
-   friend_iterator &operator++() { 
-     assert(Ptr && "attempt to increment past end of friend list"); 
-     Ptr = Ptr->getNextFriend(); 
-     return *this; 
-   } 
-   
-   friend_iterator operator++(int) { 
-     friend_iterator tmp = *this; 
-     ++*this; 
-     return tmp; 
-   } 
-   
-   bool operator==(const friend_iterator &Other) const { 
-     return Ptr == Other.Ptr; 
-   } 
-   
-   bool operator!=(const friend_iterator &Other) const { 
-     return Ptr != Other.Ptr; 
-   } 
-   
-   friend_iterator &operator+=(difference_type N) { 
-     assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator"); 
-     while (N--) 
-       ++*this; 
-     return *this; 
-   } 
-   
-   friend_iterator operator+(difference_type N) const { 
-     friend_iterator tmp = *this; 
-     tmp += N; 
-     return tmp; 
-   } 
- }; 
-   
- inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { 
-   return friend_iterator(getFirstFriend()); 
- } 
-   
- inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { 
-   return friend_iterator(nullptr); 
- } 
-   
- inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const { 
-   return friend_range(friend_begin(), friend_end()); 
- } 
-   
- inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { 
-   assert(!FD->NextFriend && "friend already has next friend?"); 
-   FD->NextFriend = data().FirstFriend; 
-   data().FirstFriend = FD; 
- } 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_AST_DECLFRIEND_H 
-