DeclFriend.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the section of the AST representing C++ friend
  15. // declarations.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_DECLFRIEND_H
  19. #define LLVM_CLANG_AST_DECLFRIEND_H
  20. #include "clang/AST/Decl.h"
  21. #include "clang/AST/DeclBase.h"
  22. #include "clang/AST/DeclCXX.h"
  23. #include "clang/AST/DeclTemplate.h"
  24. #include "clang/AST/ExternalASTSource.h"
  25. #include "clang/AST/TypeLoc.h"
  26. #include "clang/Basic/LLVM.h"
  27. #include "clang/Basic/SourceLocation.h"
  28. #include "llvm/ADT/ArrayRef.h"
  29. #include "llvm/ADT/PointerUnion.h"
  30. #include "llvm/Support/Casting.h"
  31. #include "llvm/Support/Compiler.h"
  32. #include "llvm/Support/TrailingObjects.h"
  33. #include <cassert>
  34. #include <iterator>
  35. namespace clang {
  36. class ASTContext;
  37. /// FriendDecl - Represents the declaration of a friend entity,
  38. /// which can be a function, a type, or a templated function or type.
  39. /// For example:
  40. ///
  41. /// @code
  42. /// template <typename T> class A {
  43. /// friend int foo(T);
  44. /// friend class B;
  45. /// friend T; // only in C++0x
  46. /// template <typename U> friend class C;
  47. /// template <typename U> friend A& operator+=(A&, const U&) { ... }
  48. /// };
  49. /// @endcode
  50. ///
  51. /// The semantic context of a friend decl is its declaring class.
  52. class FriendDecl final
  53. : public Decl,
  54. private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
  55. virtual void anchor();
  56. public:
  57. using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>;
  58. private:
  59. friend class CXXRecordDecl;
  60. friend class CXXRecordDecl::friend_iterator;
  61. // The declaration that's a friend of this class.
  62. FriendUnion Friend;
  63. // A pointer to the next friend in the sequence.
  64. LazyDeclPtr NextFriend;
  65. // Location of the 'friend' specifier.
  66. SourceLocation FriendLoc;
  67. /// True if this 'friend' declaration is unsupported. Eventually we
  68. /// will support every possible friend declaration, but for now we
  69. /// silently ignore some and set this flag to authorize all access.
  70. unsigned UnsupportedFriend : 1;
  71. // The number of "outer" template parameter lists in non-templatic
  72. // (currently unsupported) friend type declarations, such as
  73. // template <class T> friend class A<T>::B;
  74. unsigned NumTPLists : 31;
  75. FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
  76. SourceLocation FriendL,
  77. ArrayRef<TemplateParameterList *> FriendTypeTPLists)
  78. : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL),
  79. UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) {
  80. for (unsigned i = 0; i < NumTPLists; ++i)
  81. getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
  82. }
  83. FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
  84. : Decl(Decl::Friend, Empty), UnsupportedFriend(false),
  85. NumTPLists(NumFriendTypeTPLists) {}
  86. FriendDecl *getNextFriend() {
  87. if (!NextFriend.isOffset())
  88. return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
  89. return getNextFriendSlowCase();
  90. }
  91. FriendDecl *getNextFriendSlowCase();
  92. public:
  93. friend class ASTDeclReader;
  94. friend class ASTDeclWriter;
  95. friend class ASTNodeImporter;
  96. friend TrailingObjects;
  97. static FriendDecl *
  98. Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
  99. SourceLocation FriendL,
  100. ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt);
  101. static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
  102. unsigned FriendTypeNumTPLists);
  103. /// If this friend declaration names an (untemplated but possibly
  104. /// dependent) type, return the type; otherwise return null. This
  105. /// is used for elaborated-type-specifiers and, in C++0x, for
  106. /// arbitrary friend type declarations.
  107. TypeSourceInfo *getFriendType() const {
  108. return Friend.dyn_cast<TypeSourceInfo*>();
  109. }
  110. unsigned getFriendTypeNumTemplateParameterLists() const {
  111. return NumTPLists;
  112. }
  113. TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
  114. assert(N < NumTPLists);
  115. return getTrailingObjects<TemplateParameterList *>()[N];
  116. }
  117. /// If this friend declaration doesn't name a type, return the inner
  118. /// declaration.
  119. NamedDecl *getFriendDecl() const {
  120. return Friend.dyn_cast<NamedDecl *>();
  121. }
  122. /// Retrieves the location of the 'friend' keyword.
  123. SourceLocation getFriendLoc() const {
  124. return FriendLoc;
  125. }
  126. /// Retrieves the source range for the friend declaration.
  127. SourceRange getSourceRange() const override LLVM_READONLY {
  128. if (NamedDecl *ND = getFriendDecl()) {
  129. if (const auto *FD = dyn_cast<FunctionDecl>(ND))
  130. return FD->getSourceRange();
  131. if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
  132. return FTD->getSourceRange();
  133. if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
  134. return CTD->getSourceRange();
  135. if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) {
  136. if (DD->getOuterLocStart() != DD->getInnerLocStart())
  137. return DD->getSourceRange();
  138. }
  139. return SourceRange(getFriendLoc(), ND->getEndLoc());
  140. }
  141. else if (TypeSourceInfo *TInfo = getFriendType()) {
  142. SourceLocation StartL =
  143. (NumTPLists == 0) ? getFriendLoc()
  144. : getTrailingObjects<TemplateParameterList *>()[0]
  145. ->getTemplateLoc();
  146. return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
  147. }
  148. else
  149. return SourceRange(getFriendLoc(), getLocation());
  150. }
  151. /// Determines if this friend kind is unsupported.
  152. bool isUnsupportedFriend() const {
  153. return UnsupportedFriend;
  154. }
  155. void setUnsupportedFriend(bool Unsupported) {
  156. UnsupportedFriend = Unsupported;
  157. }
  158. // Implement isa/cast/dyncast/etc.
  159. static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  160. static bool classofKind(Kind K) { return K == Decl::Friend; }
  161. };
  162. /// An iterator over the friend declarations of a class.
  163. class CXXRecordDecl::friend_iterator {
  164. friend class CXXRecordDecl;
  165. FriendDecl *Ptr;
  166. explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
  167. public:
  168. friend_iterator() = default;
  169. using value_type = FriendDecl *;
  170. using reference = FriendDecl *;
  171. using pointer = FriendDecl *;
  172. using difference_type = int;
  173. using iterator_category = std::forward_iterator_tag;
  174. reference operator*() const { return Ptr; }
  175. friend_iterator &operator++() {
  176. assert(Ptr && "attempt to increment past end of friend list");
  177. Ptr = Ptr->getNextFriend();
  178. return *this;
  179. }
  180. friend_iterator operator++(int) {
  181. friend_iterator tmp = *this;
  182. ++*this;
  183. return tmp;
  184. }
  185. bool operator==(const friend_iterator &Other) const {
  186. return Ptr == Other.Ptr;
  187. }
  188. bool operator!=(const friend_iterator &Other) const {
  189. return Ptr != Other.Ptr;
  190. }
  191. friend_iterator &operator+=(difference_type N) {
  192. assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
  193. while (N--)
  194. ++*this;
  195. return *this;
  196. }
  197. friend_iterator operator+(difference_type N) const {
  198. friend_iterator tmp = *this;
  199. tmp += N;
  200. return tmp;
  201. }
  202. };
  203. inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
  204. return friend_iterator(getFirstFriend());
  205. }
  206. inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
  207. return friend_iterator(nullptr);
  208. }
  209. inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
  210. return friend_range(friend_begin(), friend_end());
  211. }
  212. inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
  213. assert(!FD->NextFriend && "friend already has next friend?");
  214. FD->NextFriend = data().FirstFriend;
  215. data().FirstFriend = FD;
  216. }
  217. } // namespace clang
  218. #endif // LLVM_CLANG_AST_DECLFRIEND_H
  219. #ifdef __GNUC__
  220. #pragma GCC diagnostic pop
  221. #endif