Home | History | Annotate | Download | only in AST
      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:
     36   DeclGroup() : NumDecls(0) {}
     37   DeclGroup(unsigned numdecls, Decl** decls);
     38 
     39 public:
     40   static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
     41 
     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 
     61   Kind getKind() const {
     62     return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
     63   }
     64 
     65 public:
     66   DeclGroupRef() : D(0) {}
     67 
     68   explicit DeclGroupRef(Decl* d) : D(d) {}
     69   explicit DeclGroupRef(DeclGroup* dg)
     70     : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
     71 
     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 
     83   bool isNull() const { return D == 0; }
     84   bool isSingleDecl() const { return getKind() == SingleDeclKind; }
     85   bool isDeclGroup() const { return getKind() == DeclGroupKind; }
     86 
     87   Decl *getSingleDecl() {
     88     assert(isSingleDecl() && "Isn't a declgroup");
     89     return D;
     90   }
     91   const Decl *getSingleDecl() const {
     92     return const_cast<DeclGroupRef*>(this)->getSingleDecl();
     93   }
     94 
     95   DeclGroup &getDeclGroup() {
     96     assert(isDeclGroup() && "Isn't a declgroup");
     97     return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
     98   }
     99   const DeclGroup &getDeclGroup() const {
    100     return const_cast<DeclGroupRef*>(this)->getDeclGroup();
    101   }
    102 
    103   iterator begin() {
    104     if (isSingleDecl())
    105       return D ? &D : 0;
    106     return &getDeclGroup()[0];
    107   }
    108 
    109   iterator end() {
    110     if (isSingleDecl())
    111       return D ? &D+1 : 0;
    112     DeclGroup &G = getDeclGroup();
    113     return &G[0] + G.size();
    114   }
    115 
    116   const_iterator begin() const {
    117     if (isSingleDecl())
    118       return D ? &D : 0;
    119     return &getDeclGroup()[0];
    120   }
    121 
    122   const_iterator end() const {
    123     if (isSingleDecl())
    124       return D ? &D+1 : 0;
    125     const DeclGroup &G = getDeclGroup();
    126     return &G[0] + G.size();
    127   }
    128 
    129   void *getAsOpaquePtr() const { return D; }
    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:
    146     static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
    147       return P.getAsOpaquePtr();
    148     }
    149     static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
    150       return clang::DeclGroupRef::getFromOpaquePtr(P);
    151     }
    152     enum { NumLowBitsAvailable = 0 };
    153   };
    154 }
    155 #endif
    156