| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | #ifndef LLVM_CLANG_AST_DECLFRIEND_H |
| 15 | #define LLVM_CLANG_AST_DECLFRIEND_H |
| 16 | |
| 17 | #include "clang/AST/Decl.h" |
| 18 | #include "clang/AST/DeclBase.h" |
| 19 | #include "clang/AST/DeclCXX.h" |
| 20 | #include "clang/AST/DeclTemplate.h" |
| 21 | #include "clang/AST/ExternalASTSource.h" |
| 22 | #include "clang/AST/TypeLoc.h" |
| 23 | #include "clang/Basic/LLVM.h" |
| 24 | #include "clang/Basic/SourceLocation.h" |
| 25 | #include "llvm/ADT/ArrayRef.h" |
| 26 | #include "llvm/ADT/None.h" |
| 27 | #include "llvm/ADT/PointerUnion.h" |
| 28 | #include "llvm/Support/Casting.h" |
| 29 | #include "llvm/Support/Compiler.h" |
| 30 | #include "llvm/Support/TrailingObjects.h" |
| 31 | #include <cassert> |
| 32 | #include <iterator> |
| 33 | |
| 34 | namespace clang { |
| 35 | |
| 36 | class ASTContext; |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | class FriendDecl final |
| 54 | : public Decl, |
| 55 | private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> { |
| 56 | virtual void anchor(); |
| 57 | |
| 58 | public: |
| 59 | using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>; |
| 60 | |
| 61 | private: |
| 62 | friend class CXXRecordDecl; |
| 63 | friend class CXXRecordDecl::friend_iterator; |
| 64 | |
| 65 | |
| 66 | FriendUnion Friend; |
| 67 | |
| 68 | |
| 69 | LazyDeclPtr NextFriend; |
| 70 | |
| 71 | |
| 72 | SourceLocation FriendLoc; |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | unsigned UnsupportedFriend : 1; |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | unsigned NumTPLists : 31; |
| 83 | |
| 84 | FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, |
| 85 | SourceLocation FriendL, |
| 86 | ArrayRef<TemplateParameterList *> FriendTypeTPLists) |
| 87 | : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL), |
| 88 | UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) { |
| 89 | for (unsigned i = 0; i < NumTPLists; ++i) |
| 90 | getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i]; |
| 91 | } |
| 92 | |
| 93 | FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) |
| 94 | : Decl(Decl::Friend, Empty), UnsupportedFriend(false), |
| 95 | NumTPLists(NumFriendTypeTPLists) {} |
| 96 | |
| 97 | FriendDecl *getNextFriend() { |
| 98 | if (!NextFriend.isOffset()) |
| 99 | return cast_or_null<FriendDecl>(NextFriend.get(nullptr)); |
| 100 | return getNextFriendSlowCase(); |
| 101 | } |
| 102 | |
| 103 | FriendDecl *getNextFriendSlowCase(); |
| 104 | |
| 105 | public: |
| 106 | friend class ASTDeclReader; |
| 107 | friend class ASTDeclWriter; |
| 108 | friend class ASTNodeImporter; |
| 109 | friend TrailingObjects; |
| 110 | |
| 111 | static FriendDecl *Create(ASTContext &C, DeclContext *DC, |
| 112 | SourceLocation L, FriendUnion Friend_, |
| 113 | SourceLocation FriendL, |
| 114 | ArrayRef<TemplateParameterList*> FriendTypeTPLists |
| 115 | = None); |
| 116 | static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, |
| 117 | unsigned FriendTypeNumTPLists); |
| 118 | |
| 119 | |
| 120 | |
| 121 | |
| 122 | |
| 123 | TypeSourceInfo *getFriendType() const { |
| 124 | return Friend.dyn_cast<TypeSourceInfo*>(); |
| 125 | } |
| 126 | |
| 127 | unsigned getFriendTypeNumTemplateParameterLists() const { |
| 128 | return NumTPLists; |
| 129 | } |
| 130 | |
| 131 | TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { |
| 132 | assert(N < NumTPLists); |
| 133 | return getTrailingObjects<TemplateParameterList *>()[N]; |
| 134 | } |
| 135 | |
| 136 | |
| 137 | |
| 138 | NamedDecl *getFriendDecl() const { |
| 139 | return Friend.dyn_cast<NamedDecl *>(); |
| 140 | } |
| 141 | |
| 142 | |
| 143 | SourceLocation getFriendLoc() const { |
| 144 | return FriendLoc; |
| 145 | } |
| 146 | |
| 147 | |
| 148 | SourceRange getSourceRange() const override LLVM_READONLY { |
| 149 | if (NamedDecl *ND = getFriendDecl()) { |
| 150 | if (const auto *FD = dyn_cast<FunctionDecl>(ND)) |
| 151 | return FD->getSourceRange(); |
| 152 | if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) |
| 153 | return FTD->getSourceRange(); |
| 154 | if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) |
| 155 | return CTD->getSourceRange(); |
| 156 | if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) { |
| 157 | if (DD->getOuterLocStart() != DD->getInnerLocStart()) |
| 158 | return DD->getSourceRange(); |
| 159 | } |
| 160 | return SourceRange(getFriendLoc(), ND->getEndLoc()); |
| 161 | } |
| 162 | else if (TypeSourceInfo *TInfo = getFriendType()) { |
| 163 | SourceLocation StartL = |
| 164 | (NumTPLists == 0) ? getFriendLoc() |
| 165 | : getTrailingObjects<TemplateParameterList *>()[0] |
| 166 | ->getTemplateLoc(); |
| 167 | return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); |
| 168 | } |
| 169 | else |
| 170 | return SourceRange(getFriendLoc(), getLocation()); |
| 171 | } |
| 172 | |
| 173 | |
| 174 | bool isUnsupportedFriend() const { |
| 175 | return UnsupportedFriend; |
| 176 | } |
| 177 | void setUnsupportedFriend(bool Unsupported) { |
| 178 | UnsupportedFriend = Unsupported; |
| 179 | } |
| 180 | |
| 181 | |
| 182 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
| 183 | static bool classofKind(Kind K) { return K == Decl::Friend; } |
| 184 | }; |
| 185 | |
| 186 | |
| 187 | class CXXRecordDecl::friend_iterator { |
| 188 | friend class CXXRecordDecl; |
| 189 | |
| 190 | FriendDecl *Ptr; |
| 191 | |
| 192 | explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {} |
| 193 | |
| 194 | public: |
| 195 | friend_iterator() = default; |
| 196 | |
| 197 | using value_type = FriendDecl *; |
| 198 | using reference = FriendDecl *; |
| 199 | using pointer = FriendDecl *; |
| 200 | using difference_type = int; |
| 201 | using iterator_category = std::forward_iterator_tag; |
| 202 | |
| 203 | reference operator*() const { return Ptr; } |
| 204 | |
| 205 | friend_iterator &operator++() { |
| 206 | (0) . __assert_fail ("Ptr && \"attempt to increment past end of friend list\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclFriend.h", 206, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Ptr && "attempt to increment past end of friend list"); |
| 207 | Ptr = Ptr->getNextFriend(); |
| 208 | return *this; |
| 209 | } |
| 210 | |
| 211 | friend_iterator operator++(int) { |
| 212 | friend_iterator tmp = *this; |
| 213 | ++*this; |
| 214 | return tmp; |
| 215 | } |
| 216 | |
| 217 | bool operator==(const friend_iterator &Other) const { |
| 218 | return Ptr == Other.Ptr; |
| 219 | } |
| 220 | |
| 221 | bool operator!=(const friend_iterator &Other) const { |
| 222 | return Ptr != Other.Ptr; |
| 223 | } |
| 224 | |
| 225 | friend_iterator &operator+=(difference_type N) { |
| 226 | (0) . __assert_fail ("N >= 0 && \"cannot rewind a CXXRecordDecl..friend_iterator\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclFriend.h", 226, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator"); |
| 227 | while (N--) |
| 228 | ++*this; |
| 229 | return *this; |
| 230 | } |
| 231 | |
| 232 | friend_iterator operator+(difference_type N) const { |
| 233 | friend_iterator tmp = *this; |
| 234 | tmp += N; |
| 235 | return tmp; |
| 236 | } |
| 237 | }; |
| 238 | |
| 239 | inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { |
| 240 | return friend_iterator(getFirstFriend()); |
| 241 | } |
| 242 | |
| 243 | inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { |
| 244 | return friend_iterator(nullptr); |
| 245 | } |
| 246 | |
| 247 | inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const { |
| 248 | return friend_range(friend_begin(), friend_end()); |
| 249 | } |
| 250 | |
| 251 | inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { |
| 252 | (0) . __assert_fail ("!FD->NextFriend && \"friend already has next friend?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclFriend.h", 252, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!FD->NextFriend && "friend already has next friend?"); |
| 253 | FD->NextFriend = data().FirstFriend; |
| 254 | data().FirstFriend = FD; |
| 255 | } |
| 256 | |
| 257 | } |
| 258 | |
| 259 | #endif |
| 260 | |