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