Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:32

0001 //===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the section of the AST representing C++ friend
0010 // declarations.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_DECLFRIEND_H
0015 #define LLVM_CLANG_AST_DECLFRIEND_H
0016 
0017 #include "clang/AST/Decl.h"
0018 #include "clang/AST/DeclBase.h"
0019 #include "clang/AST/DeclCXX.h"
0020 #include "clang/AST/DeclTemplate.h"
0021 #include "clang/AST/ExternalASTSource.h"
0022 #include "clang/AST/TypeLoc.h"
0023 #include "clang/Basic/LLVM.h"
0024 #include "clang/Basic/SourceLocation.h"
0025 #include "llvm/ADT/ArrayRef.h"
0026 #include "llvm/ADT/PointerUnion.h"
0027 #include "llvm/Support/Casting.h"
0028 #include "llvm/Support/Compiler.h"
0029 #include "llvm/Support/TrailingObjects.h"
0030 #include <cassert>
0031 #include <iterator>
0032 
0033 namespace clang {
0034 
0035 class ASTContext;
0036 
0037 /// FriendDecl - Represents the declaration of a friend entity,
0038 /// which can be a function, a type, or a templated function or type.
0039 /// For example:
0040 ///
0041 /// @code
0042 /// template <typename T> class A {
0043 ///   friend int foo(T);
0044 ///   friend class B;
0045 ///   friend T; // only in C++0x
0046 ///   template <typename U> friend class C;
0047 ///   template <typename U> friend A& operator+=(A&, const U&) { ... }
0048 /// };
0049 /// @endcode
0050 ///
0051 /// The semantic context of a friend decl is its declaring class.
0052 class FriendDecl final
0053     : public Decl,
0054       private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
0055   virtual void anchor();
0056 
0057 public:
0058   using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>;
0059 
0060 private:
0061   friend class CXXRecordDecl;
0062   friend class CXXRecordDecl::friend_iterator;
0063 
0064   // The declaration that's a friend of this class.
0065   FriendUnion Friend;
0066 
0067   // A pointer to the next friend in the sequence.
0068   LazyDeclPtr NextFriend;
0069 
0070   // Location of the 'friend' specifier.
0071   SourceLocation FriendLoc;
0072 
0073   // Location of the '...', if present.
0074   SourceLocation EllipsisLoc;
0075 
0076   /// True if this 'friend' declaration is unsupported.  Eventually we
0077   /// will support every possible friend declaration, but for now we
0078   /// silently ignore some and set this flag to authorize all access.
0079   LLVM_PREFERRED_TYPE(bool)
0080   unsigned UnsupportedFriend : 1;
0081 
0082   // The number of "outer" template parameter lists in non-templatic
0083   // (currently unsupported) friend type declarations, such as
0084   //     template <class T> friend class A<T>::B;
0085   unsigned NumTPLists : 31;
0086 
0087   FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
0088              SourceLocation FriendL, SourceLocation EllipsisLoc,
0089              ArrayRef<TemplateParameterList *> FriendTypeTPLists)
0090       : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL),
0091         EllipsisLoc(EllipsisLoc), UnsupportedFriend(false),
0092         NumTPLists(FriendTypeTPLists.size()) {
0093     for (unsigned i = 0; i < NumTPLists; ++i)
0094       getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
0095   }
0096 
0097   FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
0098       : Decl(Decl::Friend, Empty), UnsupportedFriend(false),
0099         NumTPLists(NumFriendTypeTPLists) {}
0100 
0101   FriendDecl *getNextFriend() {
0102     if (!NextFriend.isOffset())
0103       return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
0104     return getNextFriendSlowCase();
0105   }
0106 
0107   FriendDecl *getNextFriendSlowCase();
0108 
0109 public:
0110   friend class ASTDeclReader;
0111   friend class ASTDeclWriter;
0112   friend class ASTNodeImporter;
0113   friend TrailingObjects;
0114 
0115   static FriendDecl *
0116   Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
0117          SourceLocation FriendL, SourceLocation EllipsisLoc = {},
0118          ArrayRef<TemplateParameterList *> FriendTypeTPLists = {});
0119   static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
0120                                         unsigned FriendTypeNumTPLists);
0121 
0122   /// If this friend declaration names an (untemplated but possibly
0123   /// dependent) type, return the type; otherwise return null.  This
0124   /// is used for elaborated-type-specifiers and, in C++0x, for
0125   /// arbitrary friend type declarations.
0126   TypeSourceInfo *getFriendType() const {
0127     return Friend.dyn_cast<TypeSourceInfo*>();
0128   }
0129 
0130   unsigned getFriendTypeNumTemplateParameterLists() const {
0131     return NumTPLists;
0132   }
0133 
0134   TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
0135     assert(N < NumTPLists);
0136     return getTrailingObjects<TemplateParameterList *>()[N];
0137   }
0138 
0139   /// If this friend declaration doesn't name a type, return the inner
0140   /// declaration.
0141   NamedDecl *getFriendDecl() const {
0142     return Friend.dyn_cast<NamedDecl *>();
0143   }
0144 
0145   /// Retrieves the location of the 'friend' keyword.
0146   SourceLocation getFriendLoc() const {
0147     return FriendLoc;
0148   }
0149 
0150   /// Retrieves the location of the '...', if present.
0151   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
0152 
0153   /// Retrieves the source range for the friend declaration.
0154   SourceRange getSourceRange() const override LLVM_READONLY {
0155     if (TypeSourceInfo *TInfo = getFriendType()) {
0156       SourceLocation StartL =
0157           (NumTPLists == 0) ? getFriendLoc()
0158                             : getTrailingObjects<TemplateParameterList *>()[0]
0159                                   ->getTemplateLoc();
0160       SourceLocation EndL = isPackExpansion() ? getEllipsisLoc()
0161                                               : TInfo->getTypeLoc().getEndLoc();
0162       return SourceRange(StartL, EndL);
0163     }
0164 
0165     if (isPackExpansion())
0166       return SourceRange(getFriendLoc(), getEllipsisLoc());
0167 
0168     if (NamedDecl *ND = getFriendDecl()) {
0169       if (const auto *FD = dyn_cast<FunctionDecl>(ND))
0170         return FD->getSourceRange();
0171       if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
0172         return FTD->getSourceRange();
0173       if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
0174         return CTD->getSourceRange();
0175       if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) {
0176         if (DD->getOuterLocStart() != DD->getInnerLocStart())
0177           return DD->getSourceRange();
0178       }
0179       return SourceRange(getFriendLoc(), ND->getEndLoc());
0180     }
0181 
0182     return SourceRange(getFriendLoc(), getLocation());
0183   }
0184 
0185   /// Determines if this friend kind is unsupported.
0186   bool isUnsupportedFriend() const {
0187     return UnsupportedFriend;
0188   }
0189   void setUnsupportedFriend(bool Unsupported) {
0190     UnsupportedFriend = Unsupported;
0191   }
0192 
0193   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
0194 
0195   // Implement isa/cast/dyncast/etc.
0196   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0197   static bool classofKind(Kind K) { return K == Decl::Friend; }
0198 };
0199 
0200 /// An iterator over the friend declarations of a class.
0201 class CXXRecordDecl::friend_iterator {
0202   friend class CXXRecordDecl;
0203 
0204   FriendDecl *Ptr;
0205 
0206   explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
0207 
0208 public:
0209   friend_iterator() = default;
0210 
0211   using value_type = FriendDecl *;
0212   using reference = FriendDecl *;
0213   using pointer = FriendDecl *;
0214   using difference_type = int;
0215   using iterator_category = std::forward_iterator_tag;
0216 
0217   reference operator*() const { return Ptr; }
0218 
0219   friend_iterator &operator++() {
0220     assert(Ptr && "attempt to increment past end of friend list");
0221     Ptr = Ptr->getNextFriend();
0222     return *this;
0223   }
0224 
0225   friend_iterator operator++(int) {
0226     friend_iterator tmp = *this;
0227     ++*this;
0228     return tmp;
0229   }
0230 
0231   bool operator==(const friend_iterator &Other) const {
0232     return Ptr == Other.Ptr;
0233   }
0234 
0235   bool operator!=(const friend_iterator &Other) const {
0236     return Ptr != Other.Ptr;
0237   }
0238 
0239   friend_iterator &operator+=(difference_type N) {
0240     assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
0241     while (N--)
0242       ++*this;
0243     return *this;
0244   }
0245 
0246   friend_iterator operator+(difference_type N) const {
0247     friend_iterator tmp = *this;
0248     tmp += N;
0249     return tmp;
0250   }
0251 };
0252 
0253 inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
0254   return friend_iterator(getFirstFriend());
0255 }
0256 
0257 inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
0258   return friend_iterator(nullptr);
0259 }
0260 
0261 inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
0262   return friend_range(friend_begin(), friend_end());
0263 }
0264 
0265 inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
0266   assert(!FD->NextFriend && "friend already has next friend?");
0267   FD->NextFriend = data().FirstFriend;
0268   data().FirstFriend = FD;
0269 }
0270 
0271 } // namespace clang
0272 
0273 #endif // LLVM_CLANG_AST_DECLFRIEND_H