Clang Project

clang_source_code/include/clang/AST/DeclFriend.h
1//===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the section of the AST representing C++ friend
10// declarations.
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
34namespace clang {
35
36class ASTContext;
37
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.
53class FriendDecl final
54    : public Decl,
55      private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
56  virtual void anchor();
57
58public:
59  using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>;
60
61private:
62  friend class CXXRecordDecl;
63  friend class CXXRecordDecl::friend_iterator;
64
65  // The declaration that's a friend of this class.
66  FriendUnion Friend;
67
68  // A pointer to the next friend in the sequence.
69  LazyDeclPtr NextFriend;
70
71  // Location of the 'friend' specifier.
72  SourceLocation FriendLoc;
73
74  /// True if this 'friend' declaration is unsupported.  Eventually we
75  /// will support every possible friend declaration, but for now we
76  /// silently ignore some and set this flag to authorize all access.
77  unsigned UnsupportedFriend : 1;
78
79  // The number of "outer" template parameter lists in non-templatic
80  // (currently unsupported) friend type declarations, such as
81  //     template <class T> friend class A<T>::B;
82  unsigned NumTPLists : 31;
83
84  FriendDecl(DeclContext *DCSourceLocation 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 Emptyunsigned 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
105public:
106  friend class ASTDeclReader;
107  friend class ASTDeclWriter;
108  friend class ASTNodeImporter;
109  friend TrailingObjects;
110
111  static FriendDecl *Create(ASTContext &CDeclContext *DC,
112                            SourceLocation L, FriendUnion Friend_,
113                            SourceLocation FriendL,
114                            ArrayRef<TemplateParameterList*> FriendTypeTPLists
115                            = None);
116  static FriendDecl *CreateDeserialized(ASTContext &Cunsigned ID,
117                                        unsigned FriendTypeNumTPLists);
118
119  /// If this friend declaration names an (untemplated but possibly
120  /// dependent) type, return the type; otherwise return null.  This
121  /// is used for elaborated-type-specifiers and, in C++0x, for
122  /// arbitrary friend type declarations.
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 Nconst {
132    assert(N < NumTPLists);
133    return getTrailingObjects<TemplateParameterList *>()[N];
134  }
135
136  /// If this friend declaration doesn't name a type, return the inner
137  /// declaration.
138  NamedDecl *getFriendDecl() const {
139    return Friend.dyn_cast<NamedDecl *>();
140  }
141
142  /// Retrieves the location of the 'friend' keyword.
143  SourceLocation getFriendLoc() const {
144    return FriendLoc;
145  }
146
147  /// Retrieves the source range for the friend declaration.
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  /// Determines if this friend kind is unsupported.
174  bool isUnsupportedFriend() const {
175    return UnsupportedFriend;
176  }
177  void setUnsupportedFriend(bool Unsupported) {
178    UnsupportedFriend = Unsupported;
179  }
180
181  // Implement isa/cast/dyncast/etc.
182  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
183  static bool classofKind(Kind K) { return K == Decl::Friend; }
184};
185
186/// An iterator over the friend declarations of a class.
187class CXXRecordDecl::friend_iterator {
188  friend class CXXRecordDecl;
189
190  FriendDecl *Ptr;
191
192  explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
193
194public:
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 &Otherconst {
218    return Ptr == Other.Ptr;
219  }
220
221  bool operator!=(const friend_iterator &Otherconst {
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 Nconst {
233    friend_iterator tmp = *this;
234    tmp += N;
235    return tmp;
236  }
237};
238
239inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
240  return friend_iterator(getFirstFriend());
241}
242
243inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
244  return friend_iterator(nullptr);
245}
246
247inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
248  return friend_range(friend_begin(), friend_end());
249}
250
251inline 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// namespace clang
258
259#endif // LLVM_CLANG_AST_DECLFRIEND_H
260
clang::FriendDecl::anchor
clang::FriendDecl::Friend
clang::FriendDecl::NextFriend
clang::FriendDecl::FriendLoc
clang::FriendDecl::UnsupportedFriend
clang::FriendDecl::NumTPLists
clang::FriendDecl::getNextFriend
clang::FriendDecl::getNextFriendSlowCase
clang::FriendDecl::Create
clang::FriendDecl::CreateDeserialized
clang::FriendDecl::getFriendType
clang::FriendDecl::getFriendTypeNumTemplateParameterLists
clang::FriendDecl::getFriendTypeTemplateParameterList
clang::FriendDecl::getFriendDecl
clang::FriendDecl::getFriendLoc
clang::FriendDecl::getSourceRange
clang::CXXRecordDecl::friend_iterator
clang::CXXRecordDecl::friend_iterator::Ptr
clang::CXXRecordDecl::friend_begin
clang::CXXRecordDecl::friend_end
clang::CXXRecordDecl::friends
clang::CXXRecordDecl::pushFriendDecl