xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp (revision 297eecfb02bb25902531dbb5c3b9a88caf8adf29)
1a7dea167SDimitry Andric //===--- Program.cpp - Bytecode for the constexpr VM ------------*- C++ -*-===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric 
9a7dea167SDimitry Andric #include "Program.h"
10a7dea167SDimitry Andric #include "ByteCodeStmtGen.h"
11a7dea167SDimitry Andric #include "Context.h"
12a7dea167SDimitry Andric #include "Function.h"
1306c3fb27SDimitry Andric #include "Integral.h"
14a7dea167SDimitry Andric #include "Opcode.h"
15a7dea167SDimitry Andric #include "PrimType.h"
16a7dea167SDimitry Andric #include "clang/AST/Decl.h"
17a7dea167SDimitry Andric #include "clang/AST/DeclCXX.h"
18a7dea167SDimitry Andric 
19a7dea167SDimitry Andric using namespace clang;
20a7dea167SDimitry Andric using namespace clang::interp;
21a7dea167SDimitry Andric 
22349cc55cSDimitry Andric unsigned Program::getOrCreateNativePointer(const void *Ptr) {
23349cc55cSDimitry Andric   auto It = NativePointerIndices.find(Ptr);
24349cc55cSDimitry Andric   if (It != NativePointerIndices.end())
25349cc55cSDimitry Andric     return It->second;
26349cc55cSDimitry Andric 
27349cc55cSDimitry Andric   unsigned Idx = NativePointers.size();
28349cc55cSDimitry Andric   NativePointers.push_back(Ptr);
29349cc55cSDimitry Andric   NativePointerIndices[Ptr] = Idx;
30349cc55cSDimitry Andric   return Idx;
31349cc55cSDimitry Andric }
32349cc55cSDimitry Andric 
33349cc55cSDimitry Andric const void *Program::getNativePointer(unsigned Idx) {
34349cc55cSDimitry Andric   return NativePointers[Idx];
35349cc55cSDimitry Andric }
36349cc55cSDimitry Andric 
37a7dea167SDimitry Andric unsigned Program::createGlobalString(const StringLiteral *S) {
38a7dea167SDimitry Andric   const size_t CharWidth = S->getCharByteWidth();
39a7dea167SDimitry Andric   const size_t BitWidth = CharWidth * Ctx.getCharBit();
40a7dea167SDimitry Andric 
41a7dea167SDimitry Andric   PrimType CharType;
42a7dea167SDimitry Andric   switch (CharWidth) {
43a7dea167SDimitry Andric   case 1:
44a7dea167SDimitry Andric     CharType = PT_Sint8;
45a7dea167SDimitry Andric     break;
46a7dea167SDimitry Andric   case 2:
47a7dea167SDimitry Andric     CharType = PT_Uint16;
48a7dea167SDimitry Andric     break;
49a7dea167SDimitry Andric   case 4:
50a7dea167SDimitry Andric     CharType = PT_Uint32;
51a7dea167SDimitry Andric     break;
52a7dea167SDimitry Andric   default:
53a7dea167SDimitry Andric     llvm_unreachable("unsupported character width");
54a7dea167SDimitry Andric   }
55a7dea167SDimitry Andric 
56a7dea167SDimitry Andric   // Create a descriptor for the string.
57bdd1243dSDimitry Andric   Descriptor *Desc =
58bdd1243dSDimitry Andric       allocateDescriptor(S, CharType, std::nullopt, S->getLength() + 1,
59a7dea167SDimitry Andric                          /*isConst=*/true,
60a7dea167SDimitry Andric                          /*isTemporary=*/false,
61a7dea167SDimitry Andric                          /*isMutable=*/false);
62a7dea167SDimitry Andric 
63a7dea167SDimitry Andric   // Allocate storage for the string.
64a7dea167SDimitry Andric   // The byte length does not include the null terminator.
65a7dea167SDimitry Andric   unsigned I = Globals.size();
66a7dea167SDimitry Andric   unsigned Sz = Desc->getAllocSize();
67a7dea167SDimitry Andric   auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
68a7dea167SDimitry Andric                                        /*isExtern=*/false);
69bdd1243dSDimitry Andric   G->block()->invokeCtor();
70a7dea167SDimitry Andric   Globals.push_back(G);
71a7dea167SDimitry Andric 
72a7dea167SDimitry Andric   // Construct the string in storage.
73a7dea167SDimitry Andric   const Pointer Ptr(G->block());
74a7dea167SDimitry Andric   for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {
75a7dea167SDimitry Andric     Pointer Field = Ptr.atIndex(I).narrow();
76a7dea167SDimitry Andric     const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);
77a7dea167SDimitry Andric     switch (CharType) {
78a7dea167SDimitry Andric       case PT_Sint8: {
79a7dea167SDimitry Andric         using T = PrimConv<PT_Sint8>::T;
80a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
81a7dea167SDimitry Andric         break;
82a7dea167SDimitry Andric       }
83a7dea167SDimitry Andric       case PT_Uint16: {
84a7dea167SDimitry Andric         using T = PrimConv<PT_Uint16>::T;
85a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
86a7dea167SDimitry Andric         break;
87a7dea167SDimitry Andric       }
88a7dea167SDimitry Andric       case PT_Uint32: {
89a7dea167SDimitry Andric         using T = PrimConv<PT_Uint32>::T;
90a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
91a7dea167SDimitry Andric         break;
92a7dea167SDimitry Andric       }
93a7dea167SDimitry Andric       default:
94a7dea167SDimitry Andric         llvm_unreachable("unsupported character type");
95a7dea167SDimitry Andric     }
96a7dea167SDimitry Andric   }
97a7dea167SDimitry Andric   return I;
98a7dea167SDimitry Andric }
99a7dea167SDimitry Andric 
100a7dea167SDimitry Andric Pointer Program::getPtrGlobal(unsigned Idx) {
101a7dea167SDimitry Andric   assert(Idx < Globals.size());
102a7dea167SDimitry Andric   return Pointer(Globals[Idx]->block());
103a7dea167SDimitry Andric }
104a7dea167SDimitry Andric 
105bdd1243dSDimitry Andric std::optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
106a7dea167SDimitry Andric   auto It = GlobalIndices.find(VD);
107a7dea167SDimitry Andric   if (It != GlobalIndices.end())
108a7dea167SDimitry Andric     return It->second;
109a7dea167SDimitry Andric 
110349cc55cSDimitry Andric   // Find any previous declarations which were already evaluated.
111bdd1243dSDimitry Andric   std::optional<unsigned> Index;
112a7dea167SDimitry Andric   for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
113a7dea167SDimitry Andric     auto It = GlobalIndices.find(P);
114a7dea167SDimitry Andric     if (It != GlobalIndices.end()) {
115a7dea167SDimitry Andric       Index = It->second;
116a7dea167SDimitry Andric       break;
117a7dea167SDimitry Andric     }
118a7dea167SDimitry Andric   }
119a7dea167SDimitry Andric 
120a7dea167SDimitry Andric   // Map the decl to the existing index.
121a7dea167SDimitry Andric   if (Index) {
122a7dea167SDimitry Andric     GlobalIndices[VD] = *Index;
12306c3fb27SDimitry Andric     return std::nullopt;
124a7dea167SDimitry Andric   }
125a7dea167SDimitry Andric 
126a7dea167SDimitry Andric   return Index;
127a7dea167SDimitry Andric }
128a7dea167SDimitry Andric 
129bdd1243dSDimitry Andric std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
130bdd1243dSDimitry Andric                                                    const Expr *Init) {
131a7dea167SDimitry Andric   if (auto Idx = getGlobal(VD))
132a7dea167SDimitry Andric     return Idx;
133a7dea167SDimitry Andric 
134bdd1243dSDimitry Andric   if (auto Idx = createGlobal(VD, Init)) {
135a7dea167SDimitry Andric     GlobalIndices[VD] = *Idx;
136a7dea167SDimitry Andric     return Idx;
137a7dea167SDimitry Andric   }
13806c3fb27SDimitry Andric   return std::nullopt;
139a7dea167SDimitry Andric }
140a7dea167SDimitry Andric 
1415f757f3fSDimitry Andric std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {
14206c3fb27SDimitry Andric   // Dedup blocks since they are immutable and pointers cannot be compared.
1435f757f3fSDimitry Andric   if (auto It = DummyParams.find(VD); It != DummyParams.end())
14406c3fb27SDimitry Andric     return It->second;
14506c3fb27SDimitry Andric 
1465f757f3fSDimitry Andric   // Create dummy descriptor.
1475f757f3fSDimitry Andric   Descriptor *Desc = allocateDescriptor(VD, std::nullopt);
1485f757f3fSDimitry Andric   // Allocate a block for storage.
1495f757f3fSDimitry Andric   unsigned I = Globals.size();
150a7dea167SDimitry Andric 
1515f757f3fSDimitry Andric   auto *G = new (Allocator, Desc->getAllocSize())
1525f757f3fSDimitry Andric       Global(getCurrentDecl(), Desc, /*IsStatic=*/true, /*IsExtern=*/false);
1535f757f3fSDimitry Andric   G->block()->invokeCtor();
1545f757f3fSDimitry Andric 
1555f757f3fSDimitry Andric   Globals.push_back(G);
1565f757f3fSDimitry Andric   DummyParams[VD] = I;
1575f757f3fSDimitry Andric   return I;
158a7dea167SDimitry Andric }
159a7dea167SDimitry Andric 
160bdd1243dSDimitry Andric std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
161bdd1243dSDimitry Andric                                               const Expr *Init) {
162bdd1243dSDimitry Andric   assert(!getGlobal(VD));
163a7dea167SDimitry Andric   bool IsStatic, IsExtern;
1645f757f3fSDimitry Andric   if (const auto *Var = dyn_cast<VarDecl>(VD)) {
16506c3fb27SDimitry Andric     IsStatic = Context::shouldBeGloballyIndexed(VD);
166a7dea167SDimitry Andric     IsExtern = !Var->getAnyInitializer();
1675f757f3fSDimitry Andric   } else if (isa<UnnamedGlobalConstantDecl>(VD)) {
1685f757f3fSDimitry Andric     IsStatic = true;
1695f757f3fSDimitry Andric     IsExtern = false;
170a7dea167SDimitry Andric   } else {
171a7dea167SDimitry Andric     IsStatic = false;
172a7dea167SDimitry Andric     IsExtern = true;
173a7dea167SDimitry Andric   }
174bdd1243dSDimitry Andric   if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern, Init)) {
175a7dea167SDimitry Andric     for (const Decl *P = VD; P; P = P->getPreviousDecl())
176a7dea167SDimitry Andric       GlobalIndices[P] = *Idx;
177a7dea167SDimitry Andric     return *Idx;
178a7dea167SDimitry Andric   }
17906c3fb27SDimitry Andric   return std::nullopt;
180a7dea167SDimitry Andric }
181a7dea167SDimitry Andric 
182bdd1243dSDimitry Andric std::optional<unsigned> Program::createGlobal(const Expr *E) {
183a7dea167SDimitry Andric   return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
184a7dea167SDimitry Andric }
185a7dea167SDimitry Andric 
186bdd1243dSDimitry Andric std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
187bdd1243dSDimitry Andric                                               bool IsStatic, bool IsExtern,
188bdd1243dSDimitry Andric                                               const Expr *Init) {
189a7dea167SDimitry Andric   // Create a descriptor for the global.
190a7dea167SDimitry Andric   Descriptor *Desc;
191a7dea167SDimitry Andric   const bool IsConst = Ty.isConstQualified();
192a7dea167SDimitry Andric   const bool IsTemporary = D.dyn_cast<const Expr *>();
193a7dea167SDimitry Andric   if (auto T = Ctx.classify(Ty)) {
194bdd1243dSDimitry Andric     Desc = createDescriptor(D, *T, std::nullopt, IsConst, IsTemporary);
195a7dea167SDimitry Andric   } else {
196bdd1243dSDimitry Andric     Desc = createDescriptor(D, Ty.getTypePtr(), std::nullopt, IsConst,
197bdd1243dSDimitry Andric                             IsTemporary);
198a7dea167SDimitry Andric   }
199a7dea167SDimitry Andric   if (!Desc)
20006c3fb27SDimitry Andric     return std::nullopt;
201a7dea167SDimitry Andric 
202a7dea167SDimitry Andric   // Allocate a block for storage.
203a7dea167SDimitry Andric   unsigned I = Globals.size();
204a7dea167SDimitry Andric 
205a7dea167SDimitry Andric   auto *G = new (Allocator, Desc->getAllocSize())
206a7dea167SDimitry Andric       Global(getCurrentDecl(), Desc, IsStatic, IsExtern);
207a7dea167SDimitry Andric   G->block()->invokeCtor();
208a7dea167SDimitry Andric 
209a7dea167SDimitry Andric   Globals.push_back(G);
210a7dea167SDimitry Andric 
211a7dea167SDimitry Andric   return I;
212a7dea167SDimitry Andric }
213a7dea167SDimitry Andric 
214a7dea167SDimitry Andric Function *Program::getFunction(const FunctionDecl *F) {
215bdd1243dSDimitry Andric   F = F->getCanonicalDecl();
216bdd1243dSDimitry Andric   assert(F);
217a7dea167SDimitry Andric   auto It = Funcs.find(F);
218a7dea167SDimitry Andric   return It == Funcs.end() ? nullptr : It->second.get();
219a7dea167SDimitry Andric }
220a7dea167SDimitry Andric 
221a7dea167SDimitry Andric Record *Program::getOrCreateRecord(const RecordDecl *RD) {
222a7dea167SDimitry Andric   // Use the actual definition as a key.
223a7dea167SDimitry Andric   RD = RD->getDefinition();
224a7dea167SDimitry Andric   if (!RD)
225a7dea167SDimitry Andric     return nullptr;
226a7dea167SDimitry Andric 
227a7dea167SDimitry Andric   // Deduplicate records.
22806c3fb27SDimitry Andric   if (auto It = Records.find(RD); It != Records.end())
229a7dea167SDimitry Andric     return It->second;
230a7dea167SDimitry Andric 
231bdd1243dSDimitry Andric   // We insert nullptr now and replace that later, so recursive calls
232bdd1243dSDimitry Andric   // to this function with the same RecordDecl don't run into
233bdd1243dSDimitry Andric   // infinite recursion.
234bdd1243dSDimitry Andric   Records.insert({RD, nullptr});
235bdd1243dSDimitry Andric 
236a7dea167SDimitry Andric   // Number of bytes required by fields and base classes.
237bdd1243dSDimitry Andric   unsigned BaseSize = 0;
238a7dea167SDimitry Andric   // Number of bytes required by virtual base.
239a7dea167SDimitry Andric   unsigned VirtSize = 0;
240a7dea167SDimitry Andric 
241a7dea167SDimitry Andric   // Helper to get a base descriptor.
242a7dea167SDimitry Andric   auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
243a7dea167SDimitry Andric     if (!BR)
244a7dea167SDimitry Andric       return nullptr;
245bdd1243dSDimitry Andric     return allocateDescriptor(BD, BR, std::nullopt, /*isConst=*/false,
246a7dea167SDimitry Andric                               /*isTemporary=*/false,
247a7dea167SDimitry Andric                               /*isMutable=*/false);
248a7dea167SDimitry Andric   };
249a7dea167SDimitry Andric 
250a7dea167SDimitry Andric   // Reserve space for base classes.
251a7dea167SDimitry Andric   Record::BaseList Bases;
252a7dea167SDimitry Andric   Record::VirtualBaseList VirtBases;
253a7dea167SDimitry Andric   if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
254a7dea167SDimitry Andric     for (const CXXBaseSpecifier &Spec : CD->bases()) {
255a7dea167SDimitry Andric       if (Spec.isVirtual())
256a7dea167SDimitry Andric         continue;
257a7dea167SDimitry Andric 
258a7dea167SDimitry Andric       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
259a7dea167SDimitry Andric       Record *BR = getOrCreateRecord(BD);
260a7dea167SDimitry Andric       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
261bdd1243dSDimitry Andric         BaseSize += align(sizeof(InlineDescriptor));
262bdd1243dSDimitry Andric         Bases.push_back({BD, BaseSize, Desc, BR});
263bdd1243dSDimitry Andric         BaseSize += align(BR->getSize());
264a7dea167SDimitry Andric         continue;
265a7dea167SDimitry Andric       }
266a7dea167SDimitry Andric       return nullptr;
267a7dea167SDimitry Andric     }
268a7dea167SDimitry Andric 
269a7dea167SDimitry Andric     for (const CXXBaseSpecifier &Spec : CD->vbases()) {
270a7dea167SDimitry Andric       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
271a7dea167SDimitry Andric       Record *BR = getOrCreateRecord(BD);
272a7dea167SDimitry Andric 
273a7dea167SDimitry Andric       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
274a7dea167SDimitry Andric         VirtSize += align(sizeof(InlineDescriptor));
275a7dea167SDimitry Andric         VirtBases.push_back({BD, VirtSize, Desc, BR});
276a7dea167SDimitry Andric         VirtSize += align(BR->getSize());
277a7dea167SDimitry Andric         continue;
278a7dea167SDimitry Andric       }
279a7dea167SDimitry Andric       return nullptr;
280a7dea167SDimitry Andric     }
281a7dea167SDimitry Andric   }
282a7dea167SDimitry Andric 
283a7dea167SDimitry Andric   // Reserve space for fields.
284a7dea167SDimitry Andric   Record::FieldList Fields;
285a7dea167SDimitry Andric   for (const FieldDecl *FD : RD->fields()) {
286a7dea167SDimitry Andric     // Reserve space for the field's descriptor and the offset.
287bdd1243dSDimitry Andric     BaseSize += align(sizeof(InlineDescriptor));
288a7dea167SDimitry Andric 
289a7dea167SDimitry Andric     // Classify the field and add its metadata.
290a7dea167SDimitry Andric     QualType FT = FD->getType();
291a7dea167SDimitry Andric     const bool IsConst = FT.isConstQualified();
292a7dea167SDimitry Andric     const bool IsMutable = FD->isMutable();
293a7dea167SDimitry Andric     Descriptor *Desc;
294bdd1243dSDimitry Andric     if (std::optional<PrimType> T = Ctx.classify(FT)) {
295bdd1243dSDimitry Andric       Desc = createDescriptor(FD, *T, std::nullopt, IsConst,
296bdd1243dSDimitry Andric                               /*isTemporary=*/false, IsMutable);
297a7dea167SDimitry Andric     } else {
298bdd1243dSDimitry Andric       Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst,
299a7dea167SDimitry Andric                               /*isTemporary=*/false, IsMutable);
300a7dea167SDimitry Andric     }
301a7dea167SDimitry Andric     if (!Desc)
302a7dea167SDimitry Andric       return nullptr;
303bdd1243dSDimitry Andric     Fields.push_back({FD, BaseSize, Desc});
304bdd1243dSDimitry Andric     BaseSize += align(Desc->getAllocSize());
305a7dea167SDimitry Andric   }
306a7dea167SDimitry Andric 
307a7dea167SDimitry Andric   Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
308bdd1243dSDimitry Andric                                      std::move(VirtBases), VirtSize, BaseSize);
309bdd1243dSDimitry Andric   Records[RD] = R;
310a7dea167SDimitry Andric   return R;
311a7dea167SDimitry Andric }
312a7dea167SDimitry Andric 
313a7dea167SDimitry Andric Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
314bdd1243dSDimitry Andric                                       Descriptor::MetadataSize MDSize,
315a7dea167SDimitry Andric                                       bool IsConst, bool IsTemporary,
316bdd1243dSDimitry Andric                                       bool IsMutable, const Expr *Init) {
317a7dea167SDimitry Andric   // Classes and structures.
318*297eecfbSDimitry Andric   if (const auto *RT = Ty->getAs<RecordType>()) {
319*297eecfbSDimitry Andric     if (const auto *Record = getOrCreateRecord(RT->getDecl()))
320bdd1243dSDimitry Andric       return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary,
321bdd1243dSDimitry Andric                                 IsMutable);
322a7dea167SDimitry Andric   }
323a7dea167SDimitry Andric 
324a7dea167SDimitry Andric   // Arrays.
325*297eecfbSDimitry Andric   if (const auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
326a7dea167SDimitry Andric     QualType ElemTy = ArrayType->getElementType();
327a7dea167SDimitry Andric     // Array of well-known bounds.
328a7dea167SDimitry Andric     if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
329a7dea167SDimitry Andric       size_t NumElems = CAT->getSize().getZExtValue();
330bdd1243dSDimitry Andric       if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
331a7dea167SDimitry Andric         // Arrays of primitives.
332a7dea167SDimitry Andric         unsigned ElemSize = primSize(*T);
333a7dea167SDimitry Andric         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
334a7dea167SDimitry Andric           return {};
335a7dea167SDimitry Andric         }
336bdd1243dSDimitry Andric         return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary,
337a7dea167SDimitry Andric                                   IsMutable);
338a7dea167SDimitry Andric       } else {
339a7dea167SDimitry Andric         // Arrays of composites. In this case, the array is a list of pointers,
340a7dea167SDimitry Andric         // followed by the actual elements.
341*297eecfbSDimitry Andric         const Descriptor *ElemDesc = createDescriptor(
342bdd1243dSDimitry Andric             D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);
343bdd1243dSDimitry Andric         if (!ElemDesc)
344a7dea167SDimitry Andric           return nullptr;
34506c3fb27SDimitry Andric         unsigned ElemSize =
346bdd1243dSDimitry Andric             ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
347a7dea167SDimitry Andric         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
348a7dea167SDimitry Andric           return {};
349bdd1243dSDimitry Andric         return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst,
350bdd1243dSDimitry Andric                                   IsTemporary, IsMutable);
351a7dea167SDimitry Andric       }
352a7dea167SDimitry Andric     }
353a7dea167SDimitry Andric 
354a7dea167SDimitry Andric     // Array of unknown bounds - cannot be accessed and pointer arithmetic
355a7dea167SDimitry Andric     // is forbidden on pointers to such objects.
356a7dea167SDimitry Andric     if (isa<IncompleteArrayType>(ArrayType)) {
357bdd1243dSDimitry Andric       if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
358a7dea167SDimitry Andric         return allocateDescriptor(D, *T, IsTemporary,
359a7dea167SDimitry Andric                                   Descriptor::UnknownSize{});
360a7dea167SDimitry Andric       } else {
361*297eecfbSDimitry Andric         const Descriptor *Desc = createDescriptor(D, ElemTy.getTypePtr(),
362*297eecfbSDimitry Andric                                                   MDSize, IsConst, IsTemporary);
363a7dea167SDimitry Andric         if (!Desc)
364a7dea167SDimitry Andric           return nullptr;
365a7dea167SDimitry Andric         return allocateDescriptor(D, Desc, IsTemporary,
366a7dea167SDimitry Andric                                   Descriptor::UnknownSize{});
367a7dea167SDimitry Andric       }
368a7dea167SDimitry Andric     }
369a7dea167SDimitry Andric   }
370a7dea167SDimitry Andric 
371a7dea167SDimitry Andric   // Atomic types.
372*297eecfbSDimitry Andric   if (const auto *AT = Ty->getAs<AtomicType>()) {
373a7dea167SDimitry Andric     const Type *InnerTy = AT->getValueType().getTypePtr();
374bdd1243dSDimitry Andric     return createDescriptor(D, InnerTy, MDSize, IsConst, IsTemporary,
375bdd1243dSDimitry Andric                             IsMutable);
376a7dea167SDimitry Andric   }
377a7dea167SDimitry Andric 
378a7dea167SDimitry Andric   // Complex types - represented as arrays of elements.
379*297eecfbSDimitry Andric   if (const auto *CT = Ty->getAs<ComplexType>()) {
380a7dea167SDimitry Andric     PrimType ElemTy = *Ctx.classify(CT->getElementType());
381bdd1243dSDimitry Andric     return allocateDescriptor(D, ElemTy, MDSize, 2, IsConst, IsTemporary,
382bdd1243dSDimitry Andric                               IsMutable);
383a7dea167SDimitry Andric   }
384a7dea167SDimitry Andric 
385a7dea167SDimitry Andric   return nullptr;
386a7dea167SDimitry Andric }
387