1//===--- Context.cpp - Context 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 "Context.h"
10#include "Boolean.h"
11#include "ByteCodeEmitter.h"
12#include "Compiler.h"
13#include "EvalEmitter.h"
14#include "Integral.h"
15#include "InterpFrame.h"
16#include "InterpHelpers.h"
17#include "InterpStack.h"
18#include "Pointer.h"
19#include "PrimType.h"
20#include "Program.h"
21#include "clang/AST/ASTLambda.h"
22#include "clang/AST/Expr.h"
23#include "clang/Basic/TargetInfo.h"
24
25using namespace clang;
26using namespace clang::interp;
27
28Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {
29 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
30 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
31 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
32 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
33 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
34 "We're assuming 8 bit chars");
35}
36
37Context::~Context() {}
38
39bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
40 assert(Stk.empty());
41
42 // Get a function handle.
43 const Function *Func = getOrCreateFunction(FuncDecl: FD);
44 if (!Func)
45 return false;
46
47 // Compile the function.
48 Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
49 FuncDecl: FD, Func: const_cast<Function *>(Func));
50
51 if (!Func->isValid())
52 return false;
53
54 ++EvalID;
55 // And run it.
56 return Run(Parent, Func);
57}
58
59void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
60 const FunctionDecl *FD) {
61 assert(Stk.empty());
62 ++EvalID;
63 size_t StackSizeBefore = Stk.size();
64 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
65
66 if (!C.interpretCall(FD, E)) {
67 C.cleanup();
68 Stk.clearTo(NewSize: StackSizeBefore);
69 }
70}
71
72bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
73 ++EvalID;
74 bool Recursing = !Stk.empty();
75 size_t StackSizeBefore = Stk.size();
76 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
77
78 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
79
80 if (Res.isInvalid()) {
81 C.cleanup();
82 Stk.clearTo(NewSize: StackSizeBefore);
83 return false;
84 }
85
86 if (!Recursing) {
87 // We *can* actually get here with a non-empty stack, since
88 // things like InterpState::noteSideEffect() exist.
89 C.cleanup();
90#ifndef NDEBUG
91 // Make sure we don't rely on some value being still alive in
92 // InterpStack memory.
93 Stk.clearTo(StackSizeBefore);
94#endif
95 }
96
97 Result = Res.stealAPValue();
98
99 return true;
100}
101
102bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
103 ConstantExprKind Kind) {
104 ++EvalID;
105 bool Recursing = !Stk.empty();
106 size_t StackSizeBefore = Stk.size();
107 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
108
109 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
110 /*DestroyToplevelScope=*/true);
111 if (Res.isInvalid()) {
112 C.cleanup();
113 Stk.clearTo(NewSize: StackSizeBefore);
114 return false;
115 }
116
117 if (!Recursing) {
118 assert(Stk.empty());
119 C.cleanup();
120#ifndef NDEBUG
121 // Make sure we don't rely on some value being still alive in
122 // InterpStack memory.
123 Stk.clearTo(StackSizeBefore);
124#endif
125 }
126
127 Result = Res.stealAPValue();
128 return true;
129}
130
131bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
132 const Expr *Init, APValue &Result) {
133 ++EvalID;
134 bool Recursing = !Stk.empty();
135 size_t StackSizeBefore = Stk.size();
136 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
137
138 bool CheckGlobalInitialized =
139 shouldBeGloballyIndexed(VD) &&
140 (VD->getType()->isRecordType() || VD->getType()->isArrayType());
141 auto Res = C.interpretDecl(VD, Init, CheckFullyInitialized: CheckGlobalInitialized);
142 if (Res.isInvalid()) {
143 C.cleanup();
144 Stk.clearTo(NewSize: StackSizeBefore);
145
146 return false;
147 }
148
149 if (!Recursing) {
150 assert(Stk.empty());
151 C.cleanup();
152#ifndef NDEBUG
153 // Make sure we don't rely on some value being still alive in
154 // InterpStack memory.
155 Stk.clearTo(StackSizeBefore);
156#endif
157 }
158
159 Result = Res.stealAPValue();
160 return true;
161}
162
163template <typename ResultT>
164bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
165 const Expr *PtrExpr, ResultT &Result) {
166 assert(Stk.empty());
167 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
168
169 // Evaluate size value.
170 APValue SizeValue;
171 if (!evaluateAsRValue(Parent, E: SizeExpr, Result&: SizeValue))
172 return false;
173
174 if (!SizeValue.isInt())
175 return false;
176 uint64_t Size = SizeValue.getInt().getZExtValue();
177
178 auto PtrRes = C.interpretAsPointer(E: PtrExpr, PtrCB: [&](const Pointer &Ptr) {
179 if (Size == 0) {
180 if constexpr (std::is_same_v<ResultT, APValue>)
181 Result = APValue(APValue::UninitArray{}, 0, 0);
182 return true;
183 }
184
185 if (!Ptr.isLive() || !Ptr.getFieldDesc()->isPrimitiveArray())
186 return false;
187
188 // Must be char.
189 if (Ptr.getFieldDesc()->getElemSize() != 1 /*bytes*/)
190 return false;
191
192 if (Size > Ptr.getNumElems()) {
193 Parent.FFDiag(E: SizeExpr, DiagId: diag::note_constexpr_access_past_end) << AK_Read;
194 Size = Ptr.getNumElems();
195 }
196
197 if constexpr (std::is_same_v<ResultT, APValue>) {
198 QualType CharTy = PtrExpr->getType()->getPointeeType();
199 Result = APValue(APValue::UninitArray{}, Size, Size);
200 for (uint64_t I = 0; I != Size; ++I) {
201 if (std::optional<APValue> ElemVal =
202 Ptr.atIndex(Idx: I).toRValue(Ctx: *this, ResultType: CharTy))
203 Result.getArrayInitializedElt(I) = *ElemVal;
204 else
205 return false;
206 }
207 } else {
208 assert((std::is_same_v<ResultT, std::string>));
209 if (Size < Result.max_size())
210 Result.resize(Size);
211 Result.assign(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
212 }
213
214 return true;
215 });
216
217 if (PtrRes.isInvalid()) {
218 C.cleanup();
219 Stk.clear();
220 return false;
221 }
222
223 return true;
224}
225
226bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
227 const Expr *PtrExpr, APValue &Result) {
228 assert(SizeExpr);
229 assert(PtrExpr);
230
231 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
232}
233
234bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
235 const Expr *PtrExpr, std::string &Result) {
236 assert(SizeExpr);
237 assert(PtrExpr);
238
239 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
240}
241
242bool Context::evaluateString(State &Parent, const Expr *E,
243 std::string &Result) {
244 assert(Stk.empty());
245 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
246
247 auto PtrRes = C.interpretAsPointer(E, PtrCB: [&](const Pointer &Ptr) {
248 if (!Ptr.isBlockPointer())
249 return false;
250
251 const Descriptor *FieldDesc = Ptr.getFieldDesc();
252 if (!FieldDesc->isPrimitiveArray())
253 return false;
254
255 if (!Ptr.isConst())
256 return false;
257
258 unsigned N = Ptr.getNumElems();
259
260 if (Ptr.elemSize() == 1 /* bytes */) {
261 const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
262 unsigned Length = strnlen(string: Chars, maxlen: N);
263 // Wasn't null terminated.
264 if (N == Length)
265 return false;
266 Result.assign(s: Chars, n: Length);
267 return true;
268 }
269
270 PrimType ElemT = FieldDesc->getPrimType();
271 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
272 INT_TYPE_SWITCH(ElemT, {
273 auto Elem = Ptr.elem<T>(I);
274 if (Elem.isZero())
275 return true;
276 Result.push_back(static_cast<char>(Elem));
277 });
278 }
279 // We didn't find a 0 byte.
280 return false;
281 });
282
283 if (PtrRes.isInvalid()) {
284 C.cleanup();
285 Stk.clear();
286 return false;
287 }
288 return true;
289}
290
291std::optional<uint64_t> Context::evaluateStrlen(State &Parent, const Expr *E) {
292 assert(Stk.empty());
293 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
294
295 std::optional<uint64_t> Result;
296 auto PtrRes = C.interpretAsPointer(E, PtrCB: [&](const Pointer &Ptr) {
297 if (!Ptr.isBlockPointer())
298 return false;
299
300 const Descriptor *FieldDesc = Ptr.getFieldDesc();
301 if (!FieldDesc->isPrimitiveArray())
302 return false;
303
304 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
305 return false;
306
307 PrimType ElemT = FieldDesc->getPrimType();
308 if (!isIntegerType(T: ElemT))
309 return false;
310
311 unsigned N = Ptr.getNumElems();
312 if (Ptr.elemSize() == 1) {
313 unsigned Size = N - Ptr.getIndex();
314 Result =
315 strnlen(string: reinterpret_cast<const char *>(Ptr.getRawAddress()), maxlen: Size);
316 return Result != Size;
317 }
318
319 Result = 0;
320 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
321 INT_TYPE_SWITCH(ElemT, {
322 auto Elem = Ptr.elem<T>(I);
323 if (Elem.isZero())
324 return true;
325 ++(*Result);
326 });
327 }
328 // We didn't find a 0 byte.
329 return false;
330 });
331
332 if (PtrRes.isInvalid()) {
333 C.cleanup();
334 Stk.clear();
335 return std::nullopt;
336 }
337 return Result;
338}
339
340std::optional<uint64_t>
341Context::tryEvaluateObjectSize(State &Parent, const Expr *E, unsigned Kind) {
342 assert(Stk.empty());
343 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
344
345 std::optional<uint64_t> Result;
346
347 auto PtrRes = C.interpretAsPointer(E, PtrCB: [&](const Pointer &Ptr) {
348 const Descriptor *DeclDesc = Ptr.getDeclDesc();
349 if (!DeclDesc)
350 return false;
351
352 QualType T = DeclDesc->getType().getNonReferenceType();
353 if (T->isIncompleteType() || T->isFunctionType() ||
354 !T->isConstantSizeType())
355 return false;
356
357 Pointer P = Ptr;
358 if (auto ObjectSize = evaluateBuiltinObjectSize(ASTCtx: getASTContext(), Kind, Ptr&: P)) {
359 Result = *ObjectSize;
360 return true;
361 }
362 return false;
363 });
364
365 if (PtrRes.isInvalid()) {
366 C.cleanup();
367 Stk.clear();
368 return std::nullopt;
369 }
370 return Result;
371}
372
373const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
374
375static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
376 switch (BitWidth) {
377 case 64:
378 return PT_Sint64;
379 case 32:
380 return PT_Sint32;
381 case 16:
382 return PT_Sint16;
383 case 8:
384 return PT_Sint8;
385 default:
386 return PT_IntAPS;
387 }
388 llvm_unreachable("Unhandled BitWidth");
389}
390
391static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
392 switch (BitWidth) {
393 case 64:
394 return PT_Uint64;
395 case 32:
396 return PT_Uint32;
397 case 16:
398 return PT_Uint16;
399 case 8:
400 return PT_Uint8;
401 default:
402 return PT_IntAP;
403 }
404 llvm_unreachable("Unhandled BitWidth");
405}
406
407OptPrimType Context::classify(QualType T) const {
408
409 if (const auto *BT = dyn_cast<BuiltinType>(Val: T.getCanonicalType())) {
410 auto Kind = BT->getKind();
411 if (Kind == BuiltinType::Bool)
412 return PT_Bool;
413 if (Kind == BuiltinType::NullPtr)
414 return PT_Ptr;
415 if (Kind == BuiltinType::BoundMember)
416 return PT_MemberPtr;
417
418 // Just trying to avoid the ASTContext::getIntWidth call below.
419 if (Kind == BuiltinType::Short)
420 return integralTypeToPrimTypeS(BitWidth: this->ShortWidth);
421 if (Kind == BuiltinType::UShort)
422 return integralTypeToPrimTypeU(BitWidth: this->ShortWidth);
423
424 if (Kind == BuiltinType::Int)
425 return integralTypeToPrimTypeS(BitWidth: this->IntWidth);
426 if (Kind == BuiltinType::UInt)
427 return integralTypeToPrimTypeU(BitWidth: this->IntWidth);
428 if (Kind == BuiltinType::Long)
429 return integralTypeToPrimTypeS(BitWidth: this->LongWidth);
430 if (Kind == BuiltinType::ULong)
431 return integralTypeToPrimTypeU(BitWidth: this->LongWidth);
432 if (Kind == BuiltinType::LongLong)
433 return integralTypeToPrimTypeS(BitWidth: this->LongLongWidth);
434 if (Kind == BuiltinType::ULongLong)
435 return integralTypeToPrimTypeU(BitWidth: this->LongLongWidth);
436
437 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
438 return integralTypeToPrimTypeS(BitWidth: 8);
439 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
440 Kind == BuiltinType::Char8)
441 return integralTypeToPrimTypeU(BitWidth: 8);
442
443 if (BT->isSignedInteger())
444 return integralTypeToPrimTypeS(BitWidth: Ctx.getIntWidth(T));
445 if (BT->isUnsignedInteger())
446 return integralTypeToPrimTypeU(BitWidth: Ctx.getIntWidth(T));
447
448 if (BT->isFloatingPoint())
449 return PT_Float;
450 }
451
452 if (T->isPointerOrReferenceType())
453 return PT_Ptr;
454
455 if (T->isMemberPointerType())
456 return PT_MemberPtr;
457
458 if (const auto *BT = T->getAs<BitIntType>()) {
459 if (BT->isSigned())
460 return integralTypeToPrimTypeS(BitWidth: BT->getNumBits());
461 return integralTypeToPrimTypeU(BitWidth: BT->getNumBits());
462 }
463
464 if (const auto *D = T->getAsEnumDecl()) {
465 if (!D->isComplete())
466 return std::nullopt;
467 return classify(T: D->getIntegerType());
468 }
469
470 if (const auto *AT = T->getAs<AtomicType>())
471 return classify(T: AT->getValueType());
472
473 if (const auto *DT = dyn_cast<DecltypeType>(Val&: T))
474 return classify(T: DT->getUnderlyingType());
475
476 if (const auto *OBT = T.getCanonicalType()->getAs<OverflowBehaviorType>())
477 return classify(T: OBT->getUnderlyingType());
478
479 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
480 return PT_Ptr;
481
482 if (T->isFixedPointType())
483 return PT_FixedPoint;
484
485 // Vector and complex types get here.
486 return std::nullopt;
487}
488
489unsigned Context::getCharBit() const {
490 return Ctx.getTargetInfo().getCharWidth();
491}
492
493/// Simple wrapper around getFloatTypeSemantics() to make code a
494/// little shorter.
495const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
496 return Ctx.getFloatTypeSemantics(T);
497}
498
499bool Context::Run(State &Parent, const Function *Func) {
500 InterpState State(Parent, *P, Stk, *this, Func);
501 auto Memory = std::make_unique<char[]>(num: InterpFrame::allocSize(F: Func));
502 InterpFrame *Frame = new (Memory.get()) InterpFrame(
503 State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
504 State.Current = Frame;
505
506 if (Interpret(S&: State)) {
507 assert(Stk.empty());
508 return true;
509 }
510
511 Stk.clear();
512 Frame->~InterpFrame();
513 State.Current = &State.BottomFrame;
514 return false;
515}
516
517// TODO: Virtual bases?
518const CXXMethodDecl *
519Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
520 const CXXRecordDecl *StaticDecl,
521 const CXXMethodDecl *InitialFunction) const {
522 assert(DynamicDecl);
523 assert(StaticDecl);
524 assert(InitialFunction);
525
526 const CXXRecordDecl *CurRecord = DynamicDecl;
527 const CXXMethodDecl *FoundFunction = InitialFunction;
528 for (;;) {
529 const CXXMethodDecl *Overrider =
530 FoundFunction->getCorrespondingMethodDeclaredInClass(RD: CurRecord, MayBeBase: false);
531 if (Overrider)
532 return Overrider;
533
534 // Common case of only one base class.
535 if (CurRecord->getNumBases() == 1) {
536 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
537 continue;
538 }
539
540 // Otherwise, go to the base class that will lead to the StaticDecl.
541 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
542 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
543 if (Base == StaticDecl || Base->isDerivedFrom(Base: StaticDecl)) {
544 CurRecord = Base;
545 break;
546 }
547 }
548 }
549
550 llvm_unreachable(
551 "Couldn't find an overriding function in the class hierarchy?");
552 return nullptr;
553}
554
555const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
556 assert(FuncDecl);
557 if (const Function *Func = P->getFunction(F: FuncDecl))
558 return Func;
559
560 // Manually created functions that haven't been assigned proper
561 // parameters yet.
562 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
563 return nullptr;
564
565 bool IsLambdaStaticInvoker = false;
566 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl);
567 MD && MD->isLambdaStaticInvoker()) {
568 // For a lambda static invoker, we might have to pick a specialized
569 // version if the lambda is generic. In that case, the picked function
570 // will *NOT* be a static invoker anymore. However, it will still
571 // be a non-static member function, this (usually) requiring an
572 // instance pointer. We suppress that later in this function.
573 IsLambdaStaticInvoker = true;
574 }
575 // Set up argument indices.
576 unsigned ParamOffset = 0;
577 llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
578
579 // If the return is not a primitive, a pointer to the storage where the
580 // value is initialized in is passed as the first argument. See 'RVO'
581 // elsewhere in the code.
582 QualType Ty = FuncDecl->getReturnType();
583 bool HasRVO = false;
584 if (!Ty->isVoidType() && !canClassify(T: Ty)) {
585 HasRVO = true;
586 ParamOffset += align(Size: primSize(Type: PT_Ptr));
587 }
588
589 // If the function decl is a member decl, the next parameter is
590 // the 'this' pointer. This parameter is pop()ed from the
591 // InterpStack when calling the function.
592 bool HasThisPointer = false;
593 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl)) {
594 if (!IsLambdaStaticInvoker) {
595 HasThisPointer = MD->isInstance();
596 if (MD->isImplicitObjectMemberFunction())
597 ParamOffset += align(Size: primSize(Type: PT_Ptr));
598 }
599
600 if (isLambdaCallOperator(MD)) {
601 // The parent record needs to be complete, we need to know about all
602 // the lambda captures.
603 if (!MD->getParent()->isCompleteDefinition())
604 return nullptr;
605 if (MD->isStatic()) {
606 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
607 FieldDecl *LTC;
608
609 MD->getParent()->getCaptureFields(Captures&: LC, ThisCapture&: LTC);
610 // Static lambdas cannot have any captures. If this one does,
611 // it has already been diagnosed and we can only ignore it.
612 if (!LC.empty())
613 return nullptr;
614 }
615 }
616 }
617
618 // Assign descriptors to all parameters.
619 // Composite objects are lowered to pointers.
620 const auto *FuncProto = FuncDecl->getType()->getAs<FunctionProtoType>();
621 unsigned BlockOffset = 0;
622 for (auto [ParamIndex, PD] : llvm::enumerate(First: FuncDecl->parameters())) {
623 bool IsConst = PD->getType().isConstQualified();
624 bool IsVolatile = PD->getType().isVolatileQualified();
625
626 if (!getASTContext().hasSameType(T1: PD->getType(),
627 T2: FuncProto->getParamType(i: ParamIndex)))
628 return nullptr;
629
630 OptPrimType T = classify(T: PD->getType());
631 PrimType PT = T.value_or(PT: PT_Ptr);
632 Descriptor *Desc = P->createDescriptor(D: PD, T: PT, SourceTy: nullptr, MDSize: std::nullopt,
633 IsConst, /*IsTemporary=*/false,
634 /*IsMutable=*/false, IsVolatile);
635 unsigned PrimTSize = align(Size: primSize(Type: PT));
636 ParamDescriptors.emplace_back(Args&: Desc, Args&: ParamOffset, Args&: BlockOffset, Args&: PT);
637 ParamOffset += PrimTSize;
638 BlockOffset += sizeof(Block) + PrimTSize;
639 }
640
641 // Create a handle over the emitted code.
642 assert(!P->getFunction(FuncDecl));
643 const Function *Func =
644 P->createFunction(Def: FuncDecl, Args&: ParamOffset, Args: std::move(ParamDescriptors),
645 Args&: HasThisPointer, Args&: HasRVO, Args&: IsLambdaStaticInvoker);
646 return Func;
647}
648
649const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) {
650 const BlockDecl *BD = E->getBlockDecl();
651 // Set up argument indices.
652 unsigned ParamOffset = 0;
653 llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
654
655 // Assign descriptors to all parameters.
656 // Composite objects are lowered to pointers.
657 for (const ParmVarDecl *PD : BD->parameters()) {
658 bool IsConst = PD->getType().isConstQualified();
659 bool IsVolatile = PD->getType().isVolatileQualified();
660
661 OptPrimType T = classify(T: PD->getType());
662 PrimType PT = T.value_or(PT: PT_Ptr);
663 Descriptor *Desc = P->createDescriptor(D: PD, T: PT, SourceTy: nullptr, MDSize: std::nullopt,
664 IsConst, /*IsTemporary=*/false,
665 /*IsMutable=*/false, IsVolatile);
666 ParamDescriptors.emplace_back(Args&: Desc, Args&: ParamOffset, Args: ~0u, Args&: PT);
667 ParamOffset += align(Size: primSize(Type: PT));
668 }
669
670 if (BD->hasCaptures())
671 return nullptr;
672
673 // Create a handle over the emitted code.
674 Function *Func =
675 P->createFunction(Args&: E, Args&: ParamOffset, Args: std::move(ParamDescriptors),
676 /*HasThisPointer=*/Args: false, /*HasRVO=*/Args: false,
677 /*IsLambdaStaticInvoker=*/Args: false);
678
679 assert(Func);
680 Func->setDefined(true);
681 // We don't compile the BlockDecl code at all right now.
682 Func->setIsFullyCompiled(true);
683
684 return Func;
685}
686
687unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
688 const RecordDecl *DerivedDecl) const {
689 assert(BaseDecl);
690 assert(DerivedDecl);
691 const auto *FinalDecl = cast<CXXRecordDecl>(Val: BaseDecl);
692 const RecordDecl *CurDecl = DerivedDecl;
693 const Record *CurRecord = P->getOrCreateRecord(RD: CurDecl);
694 assert(CurDecl && FinalDecl);
695
696 unsigned OffsetSum = 0;
697 for (;;) {
698 assert(CurRecord->getNumBases() > 0);
699 // One level up
700 for (const Record::Base &B : CurRecord->bases()) {
701 const auto *BaseDecl = cast<CXXRecordDecl>(Val: B.Decl);
702
703 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(Base: FinalDecl)) {
704 OffsetSum += B.Offset;
705 CurRecord = B.R;
706 CurDecl = BaseDecl;
707 break;
708 }
709 }
710 if (CurDecl == FinalDecl)
711 break;
712 }
713
714 assert(OffsetSum > 0);
715 return OffsetSum;
716}
717
718const Record *Context::getRecord(const RecordDecl *D) const {
719 return P->getOrCreateRecord(RD: D);
720}
721
722bool Context::isUnevaluatedBuiltin(unsigned ID) {
723 return ID == Builtin::BI__builtin_classify_type ||
724 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
725 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
726}
727