DeclFriend.h 8.2 KB

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