File indexing completed on 2026-05-10 08:36:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
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
0065 FriendUnion Friend;
0066
0067
0068 LazyDeclPtr NextFriend;
0069
0070
0071 SourceLocation FriendLoc;
0072
0073
0074 SourceLocation EllipsisLoc;
0075
0076
0077
0078
0079 LLVM_PREFERRED_TYPE(bool)
0080 unsigned UnsupportedFriend : 1;
0081
0082
0083
0084
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
0123
0124
0125
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
0140
0141 NamedDecl *getFriendDecl() const {
0142 return Friend.dyn_cast<NamedDecl *>();
0143 }
0144
0145
0146 SourceLocation getFriendLoc() const {
0147 return FriendLoc;
0148 }
0149
0150
0151 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
0152
0153
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
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
0196 static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0197 static bool classofKind(Kind K) { return K == Decl::Friend; }
0198 };
0199
0200
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 }
0272
0273 #endif