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 "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:
     33   DeclGroup() : NumDecls(0) {}
     34   DeclGroup(unsigned numdecls, Decl** decls);
     35 
     36 public:
     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 
     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 
     60   Kind getKind() const {
     61     return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
     62   }
     63 
     64 public:
     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 
    138 namespace llvm {
    139   // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
    140   template <typename T>
    141   struct PointerLikeTypeTraits;
    142   template <>
    143   struct PointerLikeTypeTraits<clang::DeclGroupRef> {
    144     static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
    145       return P.getAsOpaquePtr();
    146     }
    147     static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
    148       return clang::DeclGroupRef::getFromOpaquePtr(P);
    149     }
    150     enum { NumLowBitsAvailable = 0 };
    151   };
    152 }
    153 #endif
    154