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