diff options
Diffstat (limited to 'clang/include/clang/AST/DeclGroup.h')
-rw-r--r-- | clang/include/clang/AST/DeclGroup.h | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/clang/include/clang/AST/DeclGroup.h b/clang/include/clang/AST/DeclGroup.h new file mode 100644 index 0000000..63cdac5 --- /dev/null +++ b/clang/include/clang/AST/DeclGroup.h @@ -0,0 +1,151 @@ +//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLGROUP_H +#define LLVM_CLANG_AST_DECLGROUP_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace clang { + +class ASTContext; +class Decl; +class DeclGroup; +class DeclGroupIterator; + +class DeclGroup { + // FIXME: Include a TypeSpecifier object. + unsigned NumDecls; + +private: + DeclGroup() : NumDecls(0) {} + DeclGroup(unsigned numdecls, Decl** decls); + +public: + static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); + + unsigned size() const { return NumDecls; } + + Decl*& operator[](unsigned i) { + assert (i < NumDecls && "Out-of-bounds access."); + return ((Decl**) (this+1))[i]; + } + + Decl* const& operator[](unsigned i) const { + assert (i < NumDecls && "Out-of-bounds access."); + return ((Decl* const*) (this+1))[i]; + } +}; + +class DeclGroupRef { + // Note this is not a PointerIntPair because we need the address of the + // non-group case to be valid as a Decl** for iteration. + enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; + Decl* D; + + Kind getKind() const { + return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); + } + +public: + DeclGroupRef() : D(0) {} + + explicit DeclGroupRef(Decl* d) : D(d) {} + explicit DeclGroupRef(DeclGroup* dg) + : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} + + static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { + if (NumDecls == 0) + return DeclGroupRef(); + if (NumDecls == 1) + return DeclGroupRef(Decls[0]); + return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); + } + + typedef Decl** iterator; + typedef Decl* const * const_iterator; + + bool isNull() const { return D == 0; } + bool isSingleDecl() const { return getKind() == SingleDeclKind; } + bool isDeclGroup() const { return getKind() == DeclGroupKind; } + + Decl *getSingleDecl() { + assert(isSingleDecl() && "Isn't a declgroup"); + return D; + } + const Decl *getSingleDecl() const { + return const_cast<DeclGroupRef*>(this)->getSingleDecl(); + } + + DeclGroup &getDeclGroup() { + assert(isDeclGroup() && "Isn't a declgroup"); + return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); + } + const DeclGroup &getDeclGroup() const { + return const_cast<DeclGroupRef*>(this)->getDeclGroup(); + } + + iterator begin() { + if (isSingleDecl()) + return D ? &D : 0; + return &getDeclGroup()[0]; + } + + iterator end() { + if (isSingleDecl()) + return D ? &D+1 : 0; + DeclGroup &G = getDeclGroup(); + return &G[0] + G.size(); + } + + const_iterator begin() const { + if (isSingleDecl()) + return D ? &D : 0; + return &getDeclGroup()[0]; + } + + const_iterator end() const { + if (isSingleDecl()) + return D ? &D+1 : 0; + const DeclGroup &G = getDeclGroup(); + return &G[0] + G.size(); + } + + void *getAsOpaquePtr() const { return D; } + static DeclGroupRef getFromOpaquePtr(void *Ptr) { + DeclGroupRef X; + X.D = static_cast<Decl*>(Ptr); + return X; + } +}; + +} // end clang namespace + +namespace llvm { + // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. + template <typename T> + class PointerLikeTypeTraits; + template <> + class PointerLikeTypeTraits<clang::DeclGroupRef> { + public: + static inline void *getAsVoidPointer(clang::DeclGroupRef P) { + return P.getAsOpaquePtr(); + } + static inline clang::DeclGroupRef getFromVoidPointer(void *P) { + return clang::DeclGroupRef::getFromOpaquePtr(P); + } + enum { NumLowBitsAvailable = 0 }; + }; +} +#endif |