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 21namespace clang { 22 23class ASTContext; 24class Decl; 25class DeclGroup; 26class DeclGroupIterator; 27 28class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { 29 // FIXME: Include a TypeSpecifier object. 30 unsigned NumDecls; 31 32private: 33 DeclGroup() : NumDecls(0) {} 34 DeclGroup(unsigned numdecls, Decl** decls); 35 36public: 37 static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); 38 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 54class 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 60 Kind getKind() const { 61 return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); 62 } 63 64public: 65 DeclGroupRef() : D(nullptr) {} 66 67 explicit DeclGroupRef(Decl* d) : D(d) {} 68 explicit DeclGroupRef(DeclGroup* dg) 69 : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} 70 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 82 bool isNull() const { return D == nullptr; } 83 bool isSingleDecl() const { return getKind() == SingleDeclKind; } 84 bool isDeclGroup() const { return getKind() == DeclGroupKind; } 85 86 Decl *getSingleDecl() { 87 assert(isSingleDecl() && "Isn't a single decl"); 88 return D; 89 } 90 const Decl *getSingleDecl() const { 91 return const_cast<DeclGroupRef*>(this)->getSingleDecl(); 92 } 93 94 DeclGroup &getDeclGroup() { 95 assert(isDeclGroup() && "Isn't a declgroup"); 96 return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); 97 } 98 const DeclGroup &getDeclGroup() const { 99 return const_cast<DeclGroupRef*>(this)->getDeclGroup(); 100 } 101 102 iterator begin() { 103 if (isSingleDecl()) 104 return D ? &D : nullptr; 105 return &getDeclGroup()[0]; 106 } 107 108 iterator end() { 109 if (isSingleDecl()) 110 return D ? &D+1 : nullptr; 111 DeclGroup &G = getDeclGroup(); 112 return &G[0] + G.size(); 113 } 114 115 const_iterator begin() const { 116 if (isSingleDecl()) 117 return D ? &D : nullptr; 118 return &getDeclGroup()[0]; 119 } 120 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 128 void *getAsOpaquePtr() const { return D; } 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 138namespace 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: 145 static inline void *getAsVoidPointer(clang::DeclGroupRef P) { 146 return P.getAsOpaquePtr(); 147 } 148 static inline clang::DeclGroupRef getFromVoidPointer(void *P) { 149 return clang::DeclGroupRef::getFromOpaquePtr(P); 150 } 151 enum { NumLowBitsAvailable = 0 }; 152 }; 153} 154#endif 155