Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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