Line data Source code
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 0 : unsigned size() const { return NumDecls; }
43 :
44 : Decl*& operator[](unsigned i) {
45 0 : assert (i < NumDecls && "Out-of-bounds access.");
46 0 : 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 12 : return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
63 : }
64 :
65 : public:
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 12 : bool isSingleDecl() const { return getKind() == SingleDeclKind; }
85 0 : 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 0 : assert(isDeclGroup() && "Isn't a declgroup");
97 0 : 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 6 : if (isSingleDecl())
105 18 : return D ? &D : nullptr;
106 0 : return &getDeclGroup()[0];
107 6 : }
108 :
109 : iterator end() {
110 6 : if (isSingleDecl())
111 18 : return D ? &D+1 : nullptr;
112 0 : DeclGroup &G = getDeclGroup();
113 0 : return &G[0] + G.size();
114 6 : }
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 :
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
|