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