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