1 //===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_DECLGROUP_H 15 #define LLVM_CLANG_AST_DECLGROUP_H 16 17 #include "llvm/Support/DataTypes.h" 18 #include "llvm/Support/TrailingObjects.h" 19 #include <cassert> 20 21 namespace clang { 22 23 class ASTContext; 24 class Decl; 25 class DeclGroup; 26 class DeclGroupIterator; 27 28 class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { 29 // FIXME: Include a TypeSpecifier object. 30 unsigned NumDecls; 31 32 private: DeclGroup()33 DeclGroup() : NumDecls(0) {} 34 DeclGroup(unsigned numdecls, Decl** decls); 35 36 public: 37 static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); 38 size()39 unsigned size() const { return NumDecls; } 40 41 Decl*& operator[](unsigned i) { 42 assert (i < NumDecls && "Out-of-bounds access."); 43 return getTrailingObjects<Decl *>()[i]; 44 } 45 46 Decl* const& operator[](unsigned i) const { 47 assert (i < NumDecls && "Out-of-bounds access."); 48 return getTrailingObjects<Decl *>()[i]; 49 } 50 51 friend TrailingObjects; 52 }; 53 54 class DeclGroupRef { 55 // Note this is not a PointerIntPair because we need the address of the 56 // non-group case to be valid as a Decl** for iteration. 57 enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; 58 Decl* D; 59 getKind()60 Kind getKind() const { 61 return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); 62 } 63 64 public: DeclGroupRef()65 DeclGroupRef() : D(nullptr) {} 66 DeclGroupRef(Decl * d)67 explicit DeclGroupRef(Decl* d) : D(d) {} DeclGroupRef(DeclGroup * dg)68 explicit DeclGroupRef(DeclGroup* dg) 69 : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} 70 Create(ASTContext & C,Decl ** Decls,unsigned NumDecls)71 static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { 72 if (NumDecls == 0) 73 return DeclGroupRef(); 74 if (NumDecls == 1) 75 return DeclGroupRef(Decls[0]); 76 return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); 77 } 78 79 typedef Decl** iterator; 80 typedef Decl* const * const_iterator; 81 isNull()82 bool isNull() const { return D == nullptr; } isSingleDecl()83 bool isSingleDecl() const { return getKind() == SingleDeclKind; } isDeclGroup()84 bool isDeclGroup() const { return getKind() == DeclGroupKind; } 85 getSingleDecl()86 Decl *getSingleDecl() { 87 assert(isSingleDecl() && "Isn't a declgroup"); 88 return D; 89 } getSingleDecl()90 const Decl *getSingleDecl() const { 91 return const_cast<DeclGroupRef*>(this)->getSingleDecl(); 92 } 93 getDeclGroup()94 DeclGroup &getDeclGroup() { 95 assert(isDeclGroup() && "Isn't a declgroup"); 96 return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); 97 } getDeclGroup()98 const DeclGroup &getDeclGroup() const { 99 return const_cast<DeclGroupRef*>(this)->getDeclGroup(); 100 } 101 begin()102 iterator begin() { 103 if (isSingleDecl()) 104 return D ? &D : nullptr; 105 return &getDeclGroup()[0]; 106 } 107 end()108 iterator end() { 109 if (isSingleDecl()) 110 return D ? &D+1 : nullptr; 111 DeclGroup &G = getDeclGroup(); 112 return &G[0] + G.size(); 113 } 114 begin()115 const_iterator begin() const { 116 if (isSingleDecl()) 117 return D ? &D : nullptr; 118 return &getDeclGroup()[0]; 119 } 120 end()121 const_iterator end() const { 122 if (isSingleDecl()) 123 return D ? &D+1 : nullptr; 124 const DeclGroup &G = getDeclGroup(); 125 return &G[0] + G.size(); 126 } 127 getAsOpaquePtr()128 void *getAsOpaquePtr() const { return D; } getFromOpaquePtr(void * Ptr)129 static DeclGroupRef getFromOpaquePtr(void *Ptr) { 130 DeclGroupRef X; 131 X.D = static_cast<Decl*>(Ptr); 132 return X; 133 } 134 }; 135 136 } // end clang namespace 137 138 namespace llvm { 139 // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. 140 template <typename T> 141 class PointerLikeTypeTraits; 142 template <> 143 class PointerLikeTypeTraits<clang::DeclGroupRef> { 144 public: getAsVoidPointer(clang::DeclGroupRef P)145 static inline void *getAsVoidPointer(clang::DeclGroupRef P) { 146 return P.getAsOpaquePtr(); 147 } getFromVoidPointer(void * P)148 static inline clang::DeclGroupRef getFromVoidPointer(void *P) { 149 return clang::DeclGroupRef::getFromOpaquePtr(P); 150 } 151 enum { NumLowBitsAvailable = 0 }; 152 }; 153 } 154 #endif 155