clang 24.0.0git
Context.cpp
Go to the documentation of this file.
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 "Char.h"
13#include "Compiler.h"
14#include "EvalEmitter.h"
15#include "Integral.h"
16#include "InterpFrame.h"
17#include "InterpHelpers.h"
18#include "InterpStack.h"
19#include "Pointer.h"
20#include "PrimType.h"
21#include "Program.h"
22#include "clang/AST/ASTLambda.h"
23#include "clang/AST/Expr.h"
25
26using namespace clang;
27using namespace clang::interp;
28
29Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {
30 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
31 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
32 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
33 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
34 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
35 "We're assuming 8 bit chars");
36}
37
38Context::~Context() = default;
39
41 assert(Stk.empty());
42
43 // Get a function handle.
45 if (!Func)
46 return false;
47
48 // Compile the function.
49 Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
50 FD, const_cast<Function *>(Func));
51
52 if (!Func->isValid())
53 return false;
54
55 ++EvalID;
56 // And run it.
57 return Run(Parent, Func);
58}
59
61 const FunctionDecl *FD) {
62 assert(Stk.empty());
63 ++EvalID;
64 size_t StackSizeBefore = Stk.size();
65 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
66
67 if (!C.interpretCall(FD, E)) {
68 C.cleanup();
69 Stk.clearTo(StackSizeBefore);
70 }
71}
72
74 ++EvalID;
75 bool Recursing = !Stk.empty();
76 size_t StackSizeBefore = Stk.size();
77 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
78
79 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
80
81 if (Res.isInvalid()) {
82 C.cleanup();
83 Stk.clearTo(StackSizeBefore);
84 return false;
85 }
86
87 if (!Recursing) {
88 // We *can* actually get here with a non-empty stack, since
89 // things like InterpState::noteSideEffect() exist.
90 C.cleanup();
91#ifndef NDEBUG
92 // Make sure we don't rely on some value being still alive in
93 // InterpStack memory.
94 Stk.clearTo(StackSizeBefore);
95#endif
96 }
97
98 Result = Res.stealAPValue();
99
100 return true;
101}
102
103bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
104 ConstantExprKind Kind) {
105 ++EvalID;
106 bool Recursing = !Stk.empty();
107 size_t StackSizeBefore = Stk.size();
108 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
109
110 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
111 /*DestroyToplevelScope=*/true);
112 if (Res.isInvalid()) {
113 C.cleanup();
114 Stk.clearTo(StackSizeBefore);
115 return false;
116 }
117
118 if (!Recursing) {
119 assert(Stk.empty());
120 C.cleanup();
121#ifndef NDEBUG
122 // Make sure we don't rely on some value being still alive in
123 // InterpStack memory.
124 Stk.clearTo(StackSizeBefore);
125#endif
126 }
127
128 Result = Res.stealAPValue();
129 return true;
130}
131
133 const Expr *Init, APValue &Result) {
134 ++EvalID;
135 bool Recursing = !Stk.empty();
136 size_t StackSizeBefore = Stk.size();
137 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
138
139 bool CheckGlobalInitialized =
141 (VD->getType()->isRecordType() || VD->getType()->isArrayType());
142 auto Res = C.interpretDecl(VD, Init, CheckGlobalInitialized);
143 if (Res.isInvalid()) {
144 C.cleanup();
145 Stk.clearTo(StackSizeBefore);
146
147 return false;
148 }
149
150 if (!Recursing) {
151 assert(Stk.empty());
152 C.cleanup();
153#ifndef NDEBUG
154 // Make sure we don't rely on some value being still alive in
155 // InterpStack memory.
156 Stk.clearTo(StackSizeBefore);
157#endif
158 }
159
160 Result = Res.stealAPValue();
161 return true;
162}
163
165 APValue Value) {
166 assert(Stk.empty());
167 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
168
169 auto Res = C.interpretDestructor(VD, Value);
170
171 if (Res.isInvalid()) {
172 C.cleanup();
173 Stk.clear();
174 return false;
175 }
176
177 assert(Stk.empty());
178
179 return true;
180}
181
182template <typename ResultT>
183bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
184 const Expr *PtrExpr, ResultT &Result) {
185 assert(Stk.empty());
186 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
187
188 // Evaluate size value.
189 APValue SizeValue;
190 if (!evaluateAsRValue(Parent, SizeExpr, SizeValue))
191 return false;
192
193 if (!SizeValue.isInt())
194 return false;
195 uint64_t Size = SizeValue.getInt().getZExtValue();
196
197 auto PtrRes = C.interpretAsPointer(PtrExpr, [&](InterpState &S, CodePtr OpPC,
198 const Pointer &Ptr) {
199 if (Size == 0) {
200 if constexpr (std::is_same_v<ResultT, APValue>)
202 return true;
203 }
204
205 if (Ptr.isZero()) {
206 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
207 << AK_Read;
208 return false;
209 }
210
211 if (!Ptr.isLive() || !Ptr.isInitialized() || Ptr.isUnknownSizeArray() ||
213 return false;
214
215 // Must be char.
216 if (Ptr.getFieldDesc()->getElemDataSize() != 1 /*bytes*/)
217 return false;
218
219 if (Size > Ptr.getNumElems()) {
220 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
221 << AK_Read;
222 Size = Ptr.getNumElems();
223 }
224
225 if constexpr (std::is_same_v<ResultT, APValue>) {
226 QualType CharTy = PtrExpr->getType()->getPointeeType();
227 Result = APValue(APValue::UninitArray{}, Size, Size);
228 for (uint64_t I = 0; I != Size; ++I) {
229 if (std::optional<APValue> ElemVal =
230 Ptr.atIndex(I).toRValue(*this, CharTy))
231 Result.getArrayInitializedElt(I) = *ElemVal;
232 else
233 return false;
234 }
235 } else {
236 assert((std::is_same_v<ResultT, std::string>));
237 if (Size < Result.max_size())
238 Result.resize(Size);
239 Result.assign(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
240 }
241
242 return true;
243 });
244
245 if (PtrRes.isInvalid()) {
246 C.cleanup();
247 Stk.clear();
248 return false;
249 }
250
251 return true;
252}
253
254bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
255 const Expr *PtrExpr, APValue &Result) {
256 assert(SizeExpr);
257 assert(PtrExpr);
258
259 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
260}
261
262bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
263 const Expr *PtrExpr, std::string &Result) {
264 assert(SizeExpr);
265 assert(PtrExpr);
266
267 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
268}
269
270bool Context::evaluateString(State &Parent, const Expr *E,
271 std::string &Result) {
272 assert(Stk.empty());
273 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
274
275 auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
276 const Pointer &Ptr) {
277 if (!Ptr.isBlockPointer())
278 return false;
279
280 const Descriptor *FieldDesc = Ptr.getFieldDesc();
281 if (!FieldDesc->isPrimitiveArray())
282 return false;
283
284 if (!Ptr.isConst())
285 return false;
286
287 unsigned N = Ptr.getNumElems();
288
289 if (Ptr.elemSize() == 1 /* bytes */) {
290 const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
291 unsigned Length = strnlen(Chars, N);
292 // Wasn't null terminated.
293 if (N == Length)
294 return false;
295 Result.assign(Chars, Length);
296 return true;
297 }
298
299 PrimType ElemT = FieldDesc->getPrimType();
300 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
301 INT_TYPE_SWITCH(ElemT, {
302 auto Elem = Ptr.elem<T>(I);
303 if (Elem.isZero())
304 return true;
305 Result.push_back(static_cast<char>(Elem));
306 });
307 }
308 // We didn't find a 0 byte.
309 return false;
310 });
311
312 if (PtrRes.isInvalid()) {
313 C.cleanup();
314 Stk.clear();
315 return false;
316 }
317 return true;
318}
319
320std::optional<uint64_t> Context::evaluateStrlen(State &Parent, const Expr *E) {
321 assert(Stk.empty());
322 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
323
324 std::optional<uint64_t> Result;
325 auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
326 const Pointer &Ptr) {
327 if (!Ptr.isBlockPointer())
328 return false;
329
330 const Descriptor *FieldDesc = Ptr.getFieldDesc();
331 if (!FieldDesc->isPrimitiveArray())
332 return false;
333
334 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
335 return false;
336
337 PrimType ElemT = FieldDesc->getPrimType();
338 if (!isIntegerType(ElemT))
339 return false;
340
341 unsigned N = Ptr.getNumElems();
342 if (Ptr.elemSize() == 1) {
343 unsigned Size = N - Ptr.getIndex();
344 Result =
345 strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
346 return Result != Size;
347 }
348
349 Result = 0;
350 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
351 INT_TYPE_SWITCH(ElemT, {
352 auto Elem = Ptr.elem<T>(I);
353 if (Elem.isZero())
354 return true;
355 ++(*Result);
356 });
357 }
358 // We didn't find a 0 byte.
359 return false;
360 });
361
362 if (PtrRes.isInvalid()) {
363 C.cleanup();
364 Stk.clear();
365 return std::nullopt;
366 }
367 return Result;
368}
369
370std::optional<uint64_t>
371Context::tryEvaluateObjectSize(State &Parent, const Expr *E, unsigned Kind) {
372 assert(Stk.empty());
373 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
374
375 std::optional<uint64_t> Result;
376
377 auto PtrRes = C.interpretAsLValuePointer(E, [&](InterpState &S, CodePtr OpPC,
378 const Pointer &Ptr) {
379 const Descriptor *DeclDesc = Ptr.getDeclDesc();
380 if (!DeclDesc)
381 return false;
382
383 QualType T = DeclDesc->getType().getNonReferenceType();
384 if (T->isIncompleteType() || T->isFunctionType() ||
385 !T->isConstantSizeType())
386 return false;
387
388 Pointer P = Ptr;
389 if (auto ObjectSize = evaluateBuiltinObjectSize(getASTContext(), Kind, P)) {
390 Result = *ObjectSize;
391 return true;
392 }
393 return false;
394 });
395
396 if (PtrRes.isInvalid()) {
397 C.cleanup();
398 Stk.clear();
399 return std::nullopt;
400 }
401 return Result;
402}
403
404std::optional<bool>
406 ArrayRef<const Expr *> Args, const Expr *This,
407 const Expr *Condition) {
408 if (OptPrimType ConditionT = classify(Condition);
409 !ConditionT || ConditionT != PT_Bool) {
410 return std::nullopt;
411 }
412
413 assert(Stk.empty());
414 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
415 std::optional<bool> Result =
416 C.interpretWithSubstitutions(Callee, Args, This, Condition);
417
418 // This is somewhat of a special case here. We don't allow
419 // evaluateWithSubstitution to recurse (see the Stk.empty() assertion above),
420 // BUT we allow the args to fail evaluation, which means they can leave some
421 // garbage on the stack. So we always clear() here, not only if the evaluation
422 // failed.
423 Stk.clear();
424 if (!Result) {
425 C.cleanup();
426 return std::nullopt;
427 }
428 return Result;
429}
430
431const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
432
433static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
434 switch (BitWidth) {
435 case 64:
436 return PT_Sint64;
437 case 32:
438 return PT_Sint32;
439 case 16:
440 return PT_Sint16;
441 case 8:
442 return PT_Sint8;
443 default:
444 return PT_IntAPS;
445 }
446 llvm_unreachable("Unhandled BitWidth");
447}
448
449static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
450 switch (BitWidth) {
451 case 64:
452 return PT_Uint64;
453 case 32:
454 return PT_Uint32;
455 case 16:
456 return PT_Uint16;
457 case 8:
458 return PT_Uint8;
459 default:
460 return PT_IntAP;
461 }
462 llvm_unreachable("Unhandled BitWidth");
463}
464
466
467 if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
468 auto Kind = BT->getKind();
469 if (Kind == BuiltinType::Bool)
470 return PT_Bool;
471 if (Kind == BuiltinType::NullPtr)
472 return PT_Ptr;
473 if (Kind == BuiltinType::BoundMember)
474 return PT_MemberPtr;
475
476 // Just trying to avoid the ASTContext::getIntWidth call below.
477 if (Kind == BuiltinType::Short)
478 return integralTypeToPrimTypeS(this->ShortWidth);
479 if (Kind == BuiltinType::UShort)
480 return integralTypeToPrimTypeU(this->ShortWidth);
481
482 if (Kind == BuiltinType::Int)
483 return integralTypeToPrimTypeS(this->IntWidth);
484 if (Kind == BuiltinType::UInt)
485 return integralTypeToPrimTypeU(this->IntWidth);
486 if (Kind == BuiltinType::Long)
487 return integralTypeToPrimTypeS(this->LongWidth);
488 if (Kind == BuiltinType::ULong)
489 return integralTypeToPrimTypeU(this->LongWidth);
490 if (Kind == BuiltinType::LongLong)
491 return integralTypeToPrimTypeS(this->LongLongWidth);
492 if (Kind == BuiltinType::ULongLong)
493 return integralTypeToPrimTypeU(this->LongLongWidth);
494
495 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
496 return integralTypeToPrimTypeS(8);
497 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
498 Kind == BuiltinType::Char8)
499 return integralTypeToPrimTypeU(8);
500
501 if (BT->isSignedInteger())
502 return integralTypeToPrimTypeS(Ctx.getIntWidth(T));
503 if (BT->isUnsignedInteger())
504 return integralTypeToPrimTypeU(Ctx.getIntWidth(T));
505
506 if (BT->isFloatingPoint())
507 return PT_Float;
508 }
509
510 if (T->isPointerOrReferenceType())
511 return PT_Ptr;
512
513 if (T->isMemberPointerType())
514 return PT_MemberPtr;
515
516 if (const auto *BT = T->getAs<BitIntType>()) {
517 if (BT->isSigned())
518 return integralTypeToPrimTypeS(BT->getNumBits());
519 return integralTypeToPrimTypeU(BT->getNumBits());
520 }
521
522 if (const auto *D = T->getAsEnumDecl()) {
523 if (!D->isComplete())
524 return std::nullopt;
525 return classify(D->getIntegerType());
526 }
527
528 if (const auto *AT = T->getAs<AtomicType>())
529 return classify(AT->getValueType());
530
531 if (const auto *DT = dyn_cast<DecltypeType>(T))
532 return classify(DT->getUnderlyingType());
533
534 if (const auto *OBT = T.getCanonicalType()->getAs<OverflowBehaviorType>())
535 return classify(OBT->getUnderlyingType());
536
537 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
538 return PT_Ptr;
539
540 if (T->isFixedPointType())
541 return PT_FixedPoint;
542
543 // Vector and complex types get here.
544 return std::nullopt;
545}
546
547unsigned Context::getCharBit() const {
548 return Ctx.getTargetInfo().getCharWidth();
549}
550
551/// Simple wrapper around getFloatTypeSemantics() to make code a
552/// little shorter.
553const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
554 return Ctx.getFloatTypeSemantics(T);
555}
556
557bool Context::Run(State &Parent, const Function *Func) {
558 InterpState State(Parent, *P, Stk, *this, Func);
559 auto Memory = std::make_unique<char[]>(InterpFrame::allocSize(Func));
560 InterpFrame *Frame = new (Memory.get()) InterpFrame(
561 State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
562 State.Current = Frame;
563
564 if (Interpret(State)) {
565 assert(Stk.empty());
566 return true;
567 }
568
569 Stk.clear();
570 Frame->~InterpFrame();
571 State.Current = &State.BottomFrame;
572 return false;
573}
574
575const CXXMethodDecl *
577 const CXXRecordDecl *StaticDecl,
578 const CXXMethodDecl *InitialFunction) const {
579 assert(DynamicDecl);
580 assert(StaticDecl);
581 assert(InitialFunction);
582
583 const CXXRecordDecl *CurRecord = DynamicDecl;
584 const CXXMethodDecl *FoundFunction = InitialFunction;
585 for (;;) {
586 const CXXMethodDecl *Overrider =
587 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
588 if (Overrider)
589 return Overrider;
590
591 // Common case of only one base class.
592 if (CurRecord->getNumBases() == 1) {
593 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
594 continue;
595 }
596
597 // Otherwise, go to the base class that will lead to the StaticDecl.
598 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
599 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
600 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
601 CurRecord = Base;
602 break;
603 }
604 }
605 }
606
607 llvm_unreachable(
608 "Couldn't find an overriding function in the class hierarchy?");
609 return nullptr;
610}
611
613 assert(FuncDecl);
614 if (const Function *Func = P->getFunction(FuncDecl))
615 return Func;
616
617 // Manually created functions that haven't been assigned proper
618 // parameters yet.
619 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
620 return nullptr;
621
622 bool IsLambdaStaticInvoker = false;
623 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
624 MD && MD->isLambdaStaticInvoker()) {
625 // For a lambda static invoker, we might have to pick a specialized
626 // version if the lambda is generic. In that case, the picked function
627 // will *NOT* be a static invoker anymore. However, it will still
628 // be a non-static member function, this (usually) requiring an
629 // instance pointer. We suppress that later in this function.
630 IsLambdaStaticInvoker = true;
631 }
632 // Set up argument indices.
633 unsigned ParamOffset = 0;
635
636 // If the return is not a primitive, a pointer to the storage where the
637 // value is initialized in is passed as the first argument. See 'RVO'
638 // elsewhere in the code.
639 QualType Ty = FuncDecl->getReturnType();
640 bool HasRVO = false;
641 if (!Ty->isVoidType() && !canClassify(Ty)) {
642 HasRVO = true;
644 }
645
646 // If the function decl is a member decl, the next parameter is
647 // the 'this' pointer. This parameter is pop()ed from the
648 // InterpStack when calling the function.
649 bool HasThisPointer = false;
650 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
651 if (!IsLambdaStaticInvoker) {
652 HasThisPointer = MD->isInstance();
653 if (MD->isImplicitObjectMemberFunction())
655 }
656
657 if (isLambdaCallOperator(MD)) {
658 // The parent record needs to be complete, we need to know about all
659 // the lambda captures.
660 if (!MD->getParent()->isCompleteDefinition())
661 return nullptr;
662 if (MD->isStatic()) {
663 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
664 FieldDecl *LTC;
665
666 MD->getParent()->getCaptureFields(LC, LTC);
667 // Static lambdas cannot have any captures. If this one does,
668 // it has already been diagnosed and we can only ignore it.
669 if (!LC.empty())
670 return nullptr;
671 }
672 }
673 }
674
675 // Assign descriptors to all parameters.
676 // Composite objects are lowered to pointers.
677 const auto *FuncProto = FuncDecl->getType()->getAs<FunctionProtoType>();
678 unsigned BlockOffset = 0;
679 for (auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->parameters())) {
680 bool IsConst = PD->getType().isConstQualified();
681 bool IsVolatile = PD->getType().isVolatileQualified();
682
683 if (PD->isInvalidDecl() ||
684 !getASTContext().hasSameType(PD->getType(),
685 FuncProto->getParamType(ParamIndex)))
686 return nullptr;
687
688 OptPrimType T = classify(PD->getType());
689 PrimType PT = T.value_or(PT_Ptr);
690 Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, std::nullopt,
691 IsConst, /*IsTemporary=*/false,
692 /*IsMutable=*/false, IsVolatile);
693 unsigned PrimTSize = align(primSize(PT));
694 ParamDescriptors.emplace_back(Desc, ParamOffset, BlockOffset, PT);
695 ParamOffset += PrimTSize;
696 BlockOffset += sizeof(Block) + PrimTSize;
697 }
698
699 // Create a handle over the emitted code.
700 assert(!P->getFunction(FuncDecl));
701 const Function *Func =
702 P->createFunction(FuncDecl, ParamOffset, std::move(ParamDescriptors),
703 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
704 return Func;
705}
706
708 const BlockDecl *BD = E->getBlockDecl();
709 // Set up argument indices.
710 unsigned ParamOffset = 0;
712
713 // Assign descriptors to all parameters.
714 // Composite objects are lowered to pointers.
715 for (const ParmVarDecl *PD : BD->parameters()) {
716 bool IsConst = PD->getType().isConstQualified();
717 bool IsVolatile = PD->getType().isVolatileQualified();
718
719 OptPrimType T = classify(PD->getType());
720 PrimType PT = T.value_or(PT_Ptr);
721 Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, std::nullopt,
722 IsConst, /*IsTemporary=*/false,
723 /*IsMutable=*/false, IsVolatile);
724 ParamDescriptors.emplace_back(Desc, ParamOffset, ~0u, PT);
725 ParamOffset += align(primSize(PT));
726 }
727
728 if (BD->hasCaptures())
729 return nullptr;
730
731 // Create a handle over the emitted code.
732 Function *Func =
733 P->createFunction(E, ParamOffset, std::move(ParamDescriptors),
734 /*HasThisPointer=*/false, /*HasRVO=*/false,
735 /*IsLambdaStaticInvoker=*/false);
736
737 assert(Func);
738 Func->setDefined(true);
739 // We don't compile the BlockDecl code at all right now.
740 Func->setIsFullyCompiled(true);
741
742 return Func;
743}
744
745unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
746 const RecordDecl *DerivedDecl) const {
747 assert(BaseDecl);
748 assert(DerivedDecl);
749 const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
750 const RecordDecl *CurDecl = DerivedDecl;
751 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
752 assert(CurDecl && FinalDecl);
753
754 unsigned OffsetSum = 0;
755 for (;;) {
756 assert(CurRecord->getNumBases() > 0);
757 // One level up
758 for (const Record::Base &B : CurRecord->bases()) {
759 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
760
761 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
762 OffsetSum += B.Offset;
763 CurRecord = B.R;
764 CurDecl = BaseDecl;
765 break;
766 }
767 }
768 if (CurDecl == FinalDecl)
769 break;
770 }
771
772 assert(OffsetSum > 0);
773 return OffsetSum;
774}
775
776const Record *Context::getRecord(const RecordDecl *D) const {
777 return P->getOrCreateRecord(D);
778}
779
781 return ID == Builtin::BI__builtin_classify_type ||
782 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
783 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
784}
This file provides some common utility functions for processing Lambda related AST Constructs.
static PrimType integralTypeToPrimTypeS(unsigned BitWidth)
Definition Context.cpp:433
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
Definition Context.cpp:449
#define INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:244
static bool isRecordType(QualType T)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
APSInt & getInt()
Definition APValue.h:511
bool isInt() const
Definition APValue.h:488
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
A fixed int type of a specified bitwidth.
Definition TypeBase.h:8347
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4716
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
Definition Decl.h:4835
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:4802
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6684
const BlockDecl * getBlockDecl() const
Definition Expr.h:6696
Represents a base class of a C++ class.
Definition DeclCXX.h:146
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
CXXMethodDecl * getCorrespondingMethodDeclaredInClass(const CXXRecordDecl *RD, bool MayBeBase=false)
Find if RD declares a function that overrides this function, and if so, return it.
Definition DeclCXX.cpp:2439
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
base_class_range bases()
Definition DeclCXX.h:608
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:602
base_class_iterator bases_begin()
Definition DeclCXX.h:615
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3204
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3440
Represents a function declaration or definition.
Definition Decl.h:2029
QualType getReturnType() const
Definition Decl.h:2885
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2814
param_iterator param_begin()
Definition Decl.h:2826
bool param_empty() const
Definition Decl.h:2825
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5412
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a parameter to a function.
Definition Decl.h:1819
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8680
Represents a struct/union/class.
Definition Decl.h:4369
bool isVoidType() const
Definition TypeBase.h:9098
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isArrayType() const
Definition TypeBase.h:8831
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9325
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
Pointer into the code segment.
Definition Source.h:30
Compilation context for expressions.
Definition Compiler.h:113
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:431
const Function * getOrCreateObjCBlock(const BlockExpr *E)
Definition Context.cpp:707
~Context()
Cleans up the constexpr VM.
Context(ASTContext &Ctx)
Initialises the constexpr VM.
Definition Context.cpp:29
bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
Definition Context.cpp:254
std::optional< uint64_t > evaluateStrlen(State &Parent, const Expr *E)
Evalute.
Definition Context.cpp:320
std::optional< bool > evaluateWithSubstitution(State &Parent, const FunctionDecl *Callee, ArrayRef< const Expr * > Args, const Expr *This, const Expr *Condition)
Definition Context.cpp:405
bool evaluateString(State &Parent, const Expr *E, std::string &Result)
Evaluate.
Definition Context.cpp:270
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
Definition Context.cpp:780
unsigned getCharBit() const
Returns CHAR_BIT.
Definition Context.cpp:547
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
Definition Context.cpp:553
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
Definition Context.h:165
void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, const FunctionDecl *FD)
Definition Context.cpp:60
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition Context.cpp:745
bool evaluateDestruction(State &Parent, const VarDecl *VD, APValue Value)
Evaluates the destruction of a variable.
Definition Context.cpp:164
const Record * getRecord(const RecordDecl *D) const
Definition Context.cpp:776
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
Definition Context.cpp:40
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
Definition Context.cpp:612
ASTContext & getASTContext() const
Returns the AST context.
Definition Context.h:107
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:465
bool canClassify(QualType T) const
Definition Context.h:129
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
Definition Context.cpp:73
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Definition Context.cpp:576
std::optional< uint64_t > tryEvaluateObjectSize(State &Parent, const Expr *E, unsigned Kind)
If.
Definition Context.cpp:371
bool evaluate(State &Parent, const Expr *E, APValue &Result, ConstantExprKind Kind)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
Definition Context.cpp:103
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init, APValue &Result)
Evaluates a toplevel initializer.
Definition Context.cpp:132
Base class for stack frames, shared between VM and walker.
Definition Frame.h:25
Bytecode function.
Definition Function.h:99
Frame storing local variables.
Definition InterpFrame.h:27
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
static size_t allocSize(const Function *F)
Returns the number of bytes needed to allocate an InterpFrame for the given function.
Definition InterpFrame.h:51
void clear()
Clears the stack.
bool empty() const
Returns whether the stack is empty.
Definition InterpStack.h:85
Interpreter context.
Definition InterpState.h:43
InterpFrame * Current
The current frame.
A pointer to a memory block, live or dead.
Definition Pointer.h:405
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:551
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:471
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:762
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:824
bool isConst() const
Checks if an object or a subfield is mutable.
Definition Pointer.h:769
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:808
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:636
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:522
T & elem(unsigned I) const
Dereferences the element at index I.
Definition Pointer.h:887
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:508
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:536
bool isPastEnd() const
Checks if the pointer points past the end of the object.
Definition Pointer.h:846
bool isBlockPointer() const
Definition Pointer.h:679
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
Definition Pointer.cpp:937
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:564
size_t elemSize() const
Returns the element size of the innermost field.
Definition Pointer.h:593
const std::byte * getRawAddress() const
If backed by actual data (i.e.
Definition Pointer.h:818
The program contains and links the bytecode for all functions.
Definition Program.h:37
Structure/Class descriptor.
Definition Record.h:25
unsigned getNumBases() const
Definition Record.h:109
llvm::iterator_range< const_base_iter > bases() const
Definition Record.h:105
Interface for the VM to interact with the AST walker's context.
Definition State.h:81
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:21
Defines the clang::TargetInfo interface.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:201
bool This(InterpState &S, CodePtr OpPC)
Definition Interp.h:3168
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2400
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition PrimType.cpp:24
constexpr bool isIntegerType(PrimType T)
Definition PrimType.h:53
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr)
bool Interpret(InterpState &S)
Interpreter entry point.
Definition Interp.cpp:3266
The JSON file list parser is used to communicate input to InstallAPI.
Expr::ConstantExprKind ConstantExprKind
Definition Expr.h:1048
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:906
@ AK_Read
Definition State.h:29
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
Describes a memory block created by an allocation site.
Definition Descriptor.h:122
QualType getType() const
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:263
PrimType getPrimType() const
Definition Descriptor.h:240