clang API Documentation
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