File: | src/gnu/usr.bin/clang/libclangAST/../../../llvm/clang/lib/AST/Interp/Descriptor.cpp |
Warning: | line 145, column 24 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- Descriptor.cpp - Types for the constexpr VM ------------*- 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 | #include "Descriptor.h" |
10 | #include "Pointer.h" |
11 | #include "PrimType.h" |
12 | #include "Record.h" |
13 | |
14 | using namespace clang; |
15 | using namespace clang::interp; |
16 | |
17 | template <typename T> |
18 | static void ctorTy(Block *, char *Ptr, bool, bool, bool, Descriptor *) { |
19 | new (Ptr) T(); |
20 | } |
21 | |
22 | template <typename T> static void dtorTy(Block *, char *Ptr, Descriptor *) { |
23 | reinterpret_cast<T *>(Ptr)->~T(); |
24 | } |
25 | |
26 | template <typename T> |
27 | static void moveTy(Block *, char *Src, char *Dst, Descriptor *) { |
28 | auto *SrcPtr = reinterpret_cast<T *>(Src); |
29 | auto *DstPtr = reinterpret_cast<T *>(Dst); |
30 | new (DstPtr) T(std::move(*SrcPtr)); |
31 | } |
32 | |
33 | template <typename T> |
34 | static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) { |
35 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
36 | new (&reinterpret_cast<T *>(Ptr)[I]) T(); |
37 | } |
38 | } |
39 | |
40 | template <typename T> |
41 | static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) { |
42 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
43 | reinterpret_cast<T *>(Ptr)[I].~T(); |
44 | } |
45 | } |
46 | |
47 | template <typename T> |
48 | static void moveArrayTy(Block *, char *Src, char *Dst, Descriptor *D) { |
49 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
50 | auto *SrcPtr = &reinterpret_cast<T *>(Src)[I]; |
51 | auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; |
52 | new (DstPtr) T(std::move(*SrcPtr)); |
53 | } |
54 | } |
55 | |
56 | static void ctorArrayDesc(Block *B, char *Ptr, bool IsConst, bool IsMutable, |
57 | bool IsActive, Descriptor *D) { |
58 | const unsigned NumElems = D->getNumElems(); |
59 | const unsigned ElemSize = |
60 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
61 | |
62 | unsigned ElemOffset = 0; |
63 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
64 | auto *ElemPtr = Ptr + ElemOffset; |
65 | auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); |
66 | auto *ElemLoc = reinterpret_cast<char *>(Desc + 1); |
67 | auto *SD = D->ElemDesc; |
68 | |
69 | Desc->Offset = ElemOffset + sizeof(InlineDescriptor); |
70 | Desc->Desc = SD; |
71 | Desc->IsInitialized = true; |
72 | Desc->IsBase = false; |
73 | Desc->IsActive = IsActive; |
74 | Desc->IsConst = IsConst || D->IsConst; |
75 | Desc->IsMutable = IsMutable || D->IsMutable; |
76 | if (auto Fn = D->ElemDesc->CtorFn) |
77 | Fn(B, ElemLoc, Desc->IsConst, Desc->IsMutable, IsActive, D->ElemDesc); |
78 | } |
79 | } |
80 | |
81 | static void dtorArrayDesc(Block *B, char *Ptr, Descriptor *D) { |
82 | const unsigned NumElems = D->getNumElems(); |
83 | const unsigned ElemSize = |
84 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
85 | |
86 | unsigned ElemOffset = 0; |
87 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
88 | auto *ElemPtr = Ptr + ElemOffset; |
89 | auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); |
90 | auto *ElemLoc = reinterpret_cast<char *>(Desc + 1); |
91 | if (auto Fn = D->ElemDesc->DtorFn) |
92 | Fn(B, ElemLoc, D->ElemDesc); |
93 | } |
94 | } |
95 | |
96 | static void moveArrayDesc(Block *B, char *Src, char *Dst, Descriptor *D) { |
97 | const unsigned NumElems = D->getNumElems(); |
98 | const unsigned ElemSize = |
99 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
100 | |
101 | unsigned ElemOffset = 0; |
102 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
103 | auto *SrcPtr = Src + ElemOffset; |
104 | auto *DstPtr = Dst + ElemOffset; |
105 | |
106 | auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr); |
107 | auto *SrcElemLoc = reinterpret_cast<char *>(SrcDesc + 1); |
108 | auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr); |
109 | auto *DstElemLoc = reinterpret_cast<char *>(DstDesc + 1); |
110 | |
111 | *DstDesc = *SrcDesc; |
112 | if (auto Fn = D->ElemDesc->MoveFn) |
113 | Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc); |
114 | } |
115 | } |
116 | |
117 | static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable, |
118 | bool IsActive, Descriptor *D) { |
119 | const bool IsUnion = D->ElemRecord->isUnion(); |
120 | auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) { |
121 | auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1; |
122 | Desc->Offset = SubOff; |
123 | Desc->Desc = F; |
124 | Desc->IsInitialized = (B->isStatic() || F->IsArray) && !IsBase; |
125 | Desc->IsBase = IsBase; |
126 | Desc->IsActive = IsActive && !IsUnion; |
127 | Desc->IsConst = IsConst || F->IsConst; |
128 | Desc->IsMutable = IsMutable || F->IsMutable; |
129 | if (auto Fn = F->CtorFn) |
130 | Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsMutable, Desc->IsActive, F); |
131 | }; |
132 | for (const auto &B : D->ElemRecord->bases()) |
133 | CtorSub(B.Offset, B.Desc, /*isBase=*/true); |
134 | for (const auto &F : D->ElemRecord->fields()) |
135 | CtorSub(F.Offset, F.Desc, /*isBase=*/false); |
136 | for (const auto &V : D->ElemRecord->virtual_bases()) |
137 | CtorSub(V.Offset, V.Desc, /*isBase=*/true); |
138 | } |
139 | |
140 | static void dtorRecord(Block *B, char *Ptr, Descriptor *D) { |
141 | auto DtorSub = [=](unsigned SubOff, Descriptor *F) { |
142 | if (auto Fn = F->DtorFn) |
143 | Fn(B, Ptr + SubOff, F); |
144 | }; |
145 | for (const auto &F : D->ElemRecord->bases()) |
Called C++ object pointer is null | |
146 | DtorSub(F.Offset, F.Desc); |
147 | for (const auto &F : D->ElemRecord->fields()) |
148 | DtorSub(F.Offset, F.Desc); |
149 | for (const auto &F : D->ElemRecord->virtual_bases()) |
150 | DtorSub(F.Offset, F.Desc); |
151 | } |
152 | |
153 | static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) { |
154 | for (const auto &F : D->ElemRecord->fields()) { |
155 | auto FieldOff = F.Offset; |
156 | auto FieldDesc = F.Desc; |
157 | |
158 | *(reinterpret_cast<Descriptor **>(Dst + FieldOff) - 1) = FieldDesc; |
159 | if (auto Fn = FieldDesc->MoveFn) |
160 | Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc); |
161 | } |
162 | } |
163 | |
164 | static BlockCtorFn getCtorPrim(PrimType Type) { |
165 | COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return ctorTy<T>;} while(0); break; } default: do { return nullptr; } while(0); break; }; |
166 | } |
167 | |
168 | static BlockDtorFn getDtorPrim(PrimType Type) { |
169 | COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return dtorTy<T>;} while(0); break; } default: do { return nullptr; } while(0); break; }; |
170 | } |
171 | |
172 | static BlockMoveFn getMovePrim(PrimType Type) { |
173 | COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return moveTy<T>;} while(0); break; } default: do { return nullptr; } while(0); break; }; |
174 | } |
175 | |
176 | static BlockCtorFn getCtorArrayPrim(PrimType Type) { |
177 | COMPOSITE_TYPE_SWITCH(Type, return ctorArrayTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return ctorArrayTy<T>;} while(0); break; } default : do { return nullptr; } while(0); break; }; |
178 | } |
179 | |
180 | static BlockDtorFn getDtorArrayPrim(PrimType Type) { |
181 | COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return dtorArrayTy<T>;} while(0); break; } default : do { return nullptr; } while(0); break; }; |
182 | } |
183 | |
184 | static BlockMoveFn getMoveArrayPrim(PrimType Type) { |
185 | COMPOSITE_TYPE_SWITCH(Type, return moveArrayTy<T>, return nullptr)switch (Type) { case PT_Ptr: { using T = PrimConv<PT_Ptr> ::T; do {return moveArrayTy<T>;} while(0); break; } default : do { return nullptr; } while(0); break; }; |
186 | } |
187 | |
188 | Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsConst, |
189 | bool IsTemporary, bool IsMutable) |
190 | : Source(D), ElemSize(primSize(Type)), Size(ElemSize), AllocSize(Size), |
191 | IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), |
192 | CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)), |
193 | MoveFn(getMovePrim(Type)) { |
194 | assert(Source && "Missing source")((void)0); |
195 | } |
196 | |
197 | Descriptor::Descriptor(const DeclTy &D, PrimType Type, size_t NumElems, |
198 | bool IsConst, bool IsTemporary, bool IsMutable) |
199 | : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems), |
200 | AllocSize(align(Size) + sizeof(InitMap *)), IsConst(IsConst), |
201 | IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true), |
202 | CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), |
203 | MoveFn(getMoveArrayPrim(Type)) { |
204 | assert(Source && "Missing source")((void)0); |
205 | } |
206 | |
207 | Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsTemporary, |
208 | UnknownSize) |
209 | : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark), |
210 | AllocSize(alignof(void *)), IsConst(true), IsMutable(false), |
211 | IsTemporary(IsTemporary), IsArray(true), CtorFn(getCtorArrayPrim(Type)), |
212 | DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) { |
213 | assert(Source && "Missing source")((void)0); |
214 | } |
215 | |
216 | Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, unsigned NumElems, |
217 | bool IsConst, bool IsTemporary, bool IsMutable) |
218 | : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), |
219 | Size(ElemSize * NumElems), |
220 | AllocSize(std::max<size_t>(alignof(void *), Size)), ElemDesc(Elem), |
221 | IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), |
222 | IsArray(true), CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), |
223 | MoveFn(moveArrayDesc) { |
224 | assert(Source && "Missing source")((void)0); |
225 | } |
226 | |
227 | Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary, |
228 | UnknownSize) |
229 | : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), |
230 | Size(UnknownSizeMark), AllocSize(alignof(void *)), ElemDesc(Elem), |
231 | IsConst(true), IsMutable(false), IsTemporary(IsTemporary), IsArray(true), |
232 | CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { |
233 | assert(Source && "Missing source")((void)0); |
234 | } |
235 | |
236 | Descriptor::Descriptor(const DeclTy &D, Record *R, bool IsConst, |
237 | bool IsTemporary, bool IsMutable) |
238 | : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())), |
239 | Size(ElemSize), AllocSize(Size), ElemRecord(R), IsConst(IsConst), |
240 | IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(ctorRecord), |
241 | DtorFn(dtorRecord), MoveFn(moveRecord) { |
242 | assert(Source && "Missing source")((void)0); |
243 | } |
244 | |
245 | QualType Descriptor::getType() const { |
246 | if (auto *E = asExpr()) |
247 | return E->getType(); |
248 | if (auto *D = asValueDecl()) |
249 | return D->getType(); |
250 | llvm_unreachable("Invalid descriptor type")__builtin_unreachable(); |
251 | } |
252 | |
253 | SourceLocation Descriptor::getLocation() const { |
254 | if (auto *D = Source.dyn_cast<const Decl *>()) |
255 | return D->getLocation(); |
256 | if (auto *E = Source.dyn_cast<const Expr *>()) |
257 | return E->getExprLoc(); |
258 | llvm_unreachable("Invalid descriptor type")__builtin_unreachable(); |
259 | } |
260 | |
261 | InitMap::InitMap(unsigned N) : UninitFields(N) { |
262 | for (unsigned I = 0; I < N / PER_FIELD; ++I) { |
263 | data()[I] = 0; |
264 | } |
265 | } |
266 | |
267 | InitMap::T *InitMap::data() { |
268 | auto *Start = reinterpret_cast<char *>(this) + align(sizeof(InitMap)); |
269 | return reinterpret_cast<T *>(Start); |
270 | } |
271 | |
272 | bool InitMap::initialize(unsigned I) { |
273 | unsigned Bucket = I / PER_FIELD; |
274 | unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD); |
275 | if (!(data()[Bucket] & Mask)) { |
276 | data()[Bucket] |= Mask; |
277 | UninitFields -= 1; |
278 | } |
279 | return UninitFields == 0; |
280 | } |
281 | |
282 | bool InitMap::isInitialized(unsigned I) { |
283 | unsigned Bucket = I / PER_FIELD; |
284 | unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD); |
285 | return data()[Bucket] & Mask; |
286 | } |
287 | |
288 | InitMap *InitMap::allocate(unsigned N) { |
289 | const size_t NumFields = ((N + PER_FIELD - 1) / PER_FIELD); |
290 | const size_t Size = align(sizeof(InitMap)) + NumFields * PER_FIELD; |
291 | return new (malloc(Size)) InitMap(N); |
292 | } |