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
20namespace clang {
21
22class ASTContext;
23class Decl;
24class DeclGroup;
25class DeclGroupIterator;
26
27class DeclGroup {
28  // FIXME: Include a TypeSpecifier object.
29  union {
30    unsigned NumDecls;
31
32    Decl *Aligner;
33  };
34
35private:
36  DeclGroup() : NumDecls(0) {}
37  DeclGroup(unsigned numdecls, Decl** decls);
38
39public:
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
55class 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
65public:
66  DeclGroupRef() : D(nullptr) {}
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 == nullptr; }
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 : nullptr;
106    return &getDeclGroup()[0];
107  }
108
109  iterator end() {
110    if (isSingleDecl())
111      return D ? &D+1 : nullptr;
112    DeclGroup &G = getDeclGroup();
113    return &G[0] + G.size();
114  }
115
116  const_iterator begin() const {
117    if (isSingleDecl())
118      return D ? &D : nullptr;
119    return &getDeclGroup()[0];
120  }
121
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
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
139namespace 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