clang API Documentation

DeclFriend.h
Go to the documentation of this file.
00001 //===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the section of the AST representing C++ friend
00011 // declarations.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_AST_DECLFRIEND_H
00016 #define LLVM_CLANG_AST_DECLFRIEND_H
00017 
00018 #include "clang/AST/DeclCXX.h"
00019 #include "clang/AST/DeclTemplate.h"
00020 #include "clang/AST/TypeLoc.h"
00021 #include "llvm/Support/Compiler.h"
00022 
00023 namespace clang {
00024 
00025 /// FriendDecl - Represents the declaration of a friend entity,
00026 /// which can be a function, a type, or a templated function or type.
00027 //  For example:
00028 ///
00029 /// @code
00030 /// template <typename T> class A {
00031 ///   friend int foo(T);
00032 ///   friend class B;
00033 ///   friend T; // only in C++0x
00034 ///   template <typename U> friend class C;
00035 ///   template <typename U> friend A& operator+=(A&, const U&) { ... }
00036 /// };
00037 /// @endcode
00038 ///
00039 /// The semantic context of a friend decl is its declaring class.
00040 class FriendDecl : public Decl {
00041   virtual void anchor();
00042 public:
00043   typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
00044 
00045 private:
00046   // The declaration that's a friend of this class.
00047   FriendUnion Friend;
00048 
00049   // A pointer to the next friend in the sequence.
00050   LazyDeclPtr NextFriend;
00051 
00052   // Location of the 'friend' specifier.
00053   SourceLocation FriendLoc;
00054 
00055   /// True if this 'friend' declaration is unsupported.  Eventually we
00056   /// will support every possible friend declaration, but for now we
00057   /// silently ignore some and set this flag to authorize all access.
00058   bool UnsupportedFriend : 1;
00059 
00060   // The number of "outer" template parameter lists in non-templatic
00061   // (currently unsupported) friend type declarations, such as
00062   //     template <class T> friend class A<T>::B;
00063   unsigned NumTPLists : 31;
00064 
00065   // The tail-allocated friend type template parameter lists (if any).
00066   TemplateParameterList* const *getTPLists() const {
00067     return reinterpret_cast<TemplateParameterList* const *>(this + 1);
00068   }
00069   TemplateParameterList **getTPLists() {
00070     return reinterpret_cast<TemplateParameterList**>(this + 1);
00071   }
00072 
00073   friend class CXXRecordDecl::friend_iterator;
00074   friend class CXXRecordDecl;
00075 
00076   FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
00077              SourceLocation FriendL,
00078              ArrayRef<TemplateParameterList*> FriendTypeTPLists)
00079     : Decl(Decl::Friend, DC, L),
00080       Friend(Friend),
00081       NextFriend(),
00082       FriendLoc(FriendL),
00083       UnsupportedFriend(false),
00084       NumTPLists(FriendTypeTPLists.size()) {
00085     for (unsigned i = 0; i < NumTPLists; ++i)
00086       getTPLists()[i] = FriendTypeTPLists[i];
00087   }
00088 
00089   FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
00090     : Decl(Decl::Friend, Empty), NextFriend(),
00091       NumTPLists(NumFriendTypeTPLists) { }
00092 
00093   FriendDecl *getNextFriend() {
00094     if (!NextFriend.isOffset())
00095       return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
00096     return getNextFriendSlowCase();
00097   }
00098   FriendDecl *getNextFriendSlowCase();
00099 
00100 public:
00101   static FriendDecl *Create(ASTContext &C, DeclContext *DC,
00102                             SourceLocation L, FriendUnion Friend_,
00103                             SourceLocation FriendL,
00104                             ArrayRef<TemplateParameterList*> FriendTypeTPLists
00105                             = None);
00106   static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
00107                                         unsigned FriendTypeNumTPLists);
00108 
00109   /// If this friend declaration names an (untemplated but possibly
00110   /// dependent) type, return the type; otherwise return null.  This
00111   /// is used for elaborated-type-specifiers and, in C++0x, for
00112   /// arbitrary friend type declarations.
00113   TypeSourceInfo *getFriendType() const {
00114     return Friend.dyn_cast<TypeSourceInfo*>();
00115   }
00116   unsigned getFriendTypeNumTemplateParameterLists() const {
00117     return NumTPLists;
00118   }
00119   TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
00120     assert(N < NumTPLists);
00121     return getTPLists()[N];
00122   }
00123 
00124   /// If this friend declaration doesn't name a type, return the inner
00125   /// declaration.
00126   NamedDecl *getFriendDecl() const {
00127     return Friend.dyn_cast<NamedDecl*>();
00128   }
00129 
00130   /// Retrieves the location of the 'friend' keyword.
00131   SourceLocation getFriendLoc() const {
00132     return FriendLoc;
00133   }
00134 
00135   /// Retrieves the source range for the friend declaration.
00136   SourceRange getSourceRange() const override LLVM_READONLY {
00137     if (NamedDecl *ND = getFriendDecl()) {
00138       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
00139         return FD->getSourceRange();
00140       if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
00141         return FTD->getSourceRange();
00142       if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
00143         return CTD->getSourceRange();
00144       if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
00145         if (DD->getOuterLocStart() != DD->getInnerLocStart())
00146           return DD->getSourceRange();
00147       }
00148       return SourceRange(getFriendLoc(), ND->getLocEnd());
00149     }
00150     else if (TypeSourceInfo *TInfo = getFriendType()) {
00151       SourceLocation StartL = (NumTPLists == 0)
00152         ? getFriendLoc()
00153         : getTPLists()[0]->getTemplateLoc();
00154       return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
00155     }
00156     else
00157       return SourceRange(getFriendLoc(), getLocation());
00158   }
00159 
00160   /// Determines if this friend kind is unsupported.
00161   bool isUnsupportedFriend() const {
00162     return UnsupportedFriend;
00163   }
00164   void setUnsupportedFriend(bool Unsupported) {
00165     UnsupportedFriend = Unsupported;
00166   }
00167 
00168   // Implement isa/cast/dyncast/etc.
00169   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
00170   static bool classofKind(Kind K) { return K == Decl::Friend; }
00171 
00172   friend class ASTDeclReader;
00173   friend class ASTDeclWriter;
00174 };
00175 
00176 /// An iterator over the friend declarations of a class.
00177 class CXXRecordDecl::friend_iterator {
00178   FriendDecl *Ptr;
00179 
00180   friend class CXXRecordDecl;
00181   explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
00182 public:
00183   friend_iterator() {}
00184 
00185   typedef FriendDecl *value_type;
00186   typedef FriendDecl *reference;
00187   typedef FriendDecl *pointer;
00188   typedef int difference_type;
00189   typedef std::forward_iterator_tag iterator_category;
00190 
00191   reference operator*() const { return Ptr; }
00192 
00193   friend_iterator &operator++() {
00194     assert(Ptr && "attempt to increment past end of friend list");
00195     Ptr = Ptr->getNextFriend();
00196     return *this;
00197   }
00198 
00199   friend_iterator operator++(int) {
00200     friend_iterator tmp = *this;
00201     ++*this;
00202     return tmp;
00203   }
00204 
00205   bool operator==(const friend_iterator &Other) const {
00206     return Ptr == Other.Ptr;
00207   }
00208 
00209   bool operator!=(const friend_iterator &Other) const {
00210     return Ptr != Other.Ptr;
00211   }
00212 
00213   friend_iterator &operator+=(difference_type N) {
00214     assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
00215     while (N--)
00216       ++*this;
00217     return *this;
00218   }
00219 
00220   friend_iterator operator+(difference_type N) const {
00221     friend_iterator tmp = *this;
00222     tmp += N;
00223     return tmp;
00224   }
00225 };
00226 
00227 inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
00228   return friend_iterator(getFirstFriend());
00229 }
00230 
00231 inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
00232   return friend_iterator(nullptr);
00233 }
00234 
00235 inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
00236   return friend_range(friend_begin(), friend_end());
00237 }
00238 
00239 inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
00240   assert(!FD->NextFriend && "friend already has next friend?");
00241   FD->NextFriend = data().FirstFriend;
00242   data().FirstFriend = FD;
00243 }
00244   
00245 }
00246 
00247 #endif