xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/DeclGroup.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- DeclGroup.h - Classes for representing groups of Decls ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_DECLGROUP_H
14 #define LLVM_CLANG_AST_DECLGROUP_H
15 
16 #include "llvm/Support/TrailingObjects.h"
17 #include <cassert>
18 #include <cstdint>
19 
20 namespace clang {
21 
22 class ASTContext;
23 class Decl;
24 
25 class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
26   // FIXME: Include a TypeSpecifier object.
27   unsigned NumDecls = 0;
28 
29 private:
30   DeclGroup() = default;
31   DeclGroup(unsigned numdecls, Decl** decls);
32 
33 public:
34   friend TrailingObjects;
35 
36   static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
37 
size()38   unsigned size() const { return NumDecls; }
39 
40   Decl *&operator[](unsigned i) { return getTrailingObjects(NumDecls)[i]; }
41 
42   Decl* const& operator[](unsigned i) const {
43     return getTrailingObjects(NumDecls)[i];
44   }
45 };
46 
47 class DeclGroupRef {
48   // Note this is not a PointerIntPair because we need the address of the
49   // non-group case to be valid as a Decl** for iteration.
50   enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
51 
52   Decl* D = nullptr;
53 
getKind()54   Kind getKind() const {
55     return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
56   }
57 
58 public:
59   DeclGroupRef() = default;
DeclGroupRef(Decl * d)60   explicit DeclGroupRef(Decl* d) : D(d) {}
DeclGroupRef(DeclGroup * dg)61   explicit DeclGroupRef(DeclGroup* dg)
62     : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
63 
Create(ASTContext & C,Decl ** Decls,unsigned NumDecls)64   static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
65     if (NumDecls == 0)
66       return DeclGroupRef();
67     if (NumDecls == 1)
68       return DeclGroupRef(Decls[0]);
69     return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
70   }
71 
72   using iterator = Decl **;
73   using const_iterator = Decl * const *;
74 
isNull()75   bool isNull() const { return D == nullptr; }
isSingleDecl()76   bool isSingleDecl() const { return getKind() == SingleDeclKind; }
isDeclGroup()77   bool isDeclGroup() const { return getKind() == DeclGroupKind; }
78 
getSingleDecl()79   Decl *getSingleDecl() {
80     assert(isSingleDecl() && "Isn't a single decl");
81     return D;
82   }
getSingleDecl()83   const Decl *getSingleDecl() const {
84     return const_cast<DeclGroupRef*>(this)->getSingleDecl();
85   }
86 
getDeclGroup()87   DeclGroup &getDeclGroup() {
88     assert(isDeclGroup() && "Isn't a declgroup");
89     return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
90   }
getDeclGroup()91   const DeclGroup &getDeclGroup() const {
92     return const_cast<DeclGroupRef*>(this)->getDeclGroup();
93   }
94 
begin()95   iterator begin() {
96     if (isSingleDecl())
97       return D ? &D : nullptr;
98     return &getDeclGroup()[0];
99   }
100 
end()101   iterator end() {
102     if (isSingleDecl())
103       return D ? &D+1 : nullptr;
104     DeclGroup &G = getDeclGroup();
105     return &G[0] + G.size();
106   }
107 
begin()108   const_iterator begin() const {
109     if (isSingleDecl())
110       return D ? &D : nullptr;
111     return &getDeclGroup()[0];
112   }
113 
end()114   const_iterator end() const {
115     if (isSingleDecl())
116       return D ? &D+1 : nullptr;
117     const DeclGroup &G = getDeclGroup();
118     return &G[0] + G.size();
119   }
120 
getAsOpaquePtr()121   void *getAsOpaquePtr() const { return D; }
getFromOpaquePtr(void * Ptr)122   static DeclGroupRef getFromOpaquePtr(void *Ptr) {
123     DeclGroupRef X;
124     X.D = static_cast<Decl*>(Ptr);
125     return X;
126   }
127 };
128 
129 } // namespace clang
130 
131 namespace llvm {
132 
133   // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
134   template <typename T>
135   struct PointerLikeTypeTraits;
136   template <>
137   struct PointerLikeTypeTraits<clang::DeclGroupRef> {
138     static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
139       return P.getAsOpaquePtr();
140     }
141 
142     static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
143       return clang::DeclGroupRef::getFromOpaquePtr(P);
144     }
145 
146     static constexpr int NumLowBitsAvailable = 0;
147   };
148 
149 } // namespace llvm
150 
151 #endif // LLVM_CLANG_AST_DECLGROUP_H
152