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, FrameAlloc);
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, FrameAlloc);
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, FrameAlloc);
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, FrameAlloc);
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, FrameAlloc);
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
182void Context::registerRedecl(const VarDecl *VD, const APValue &V) {
183 Expr::EvalStatus Status;
184 Compiler<EvalEmitter> C(*this, *P, Status, Stk, FrameAlloc);
185
186 C.registerRedecl(VD, V);
187}
188
189template <typename ResultT>
190bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
191 const Expr *PtrExpr, ResultT &Result) {
192 assert(Stk.empty());
193 Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
194
195 // Evaluate size value.
196 APValue SizeValue;
197 if (!evaluateAsRValue(Parent, SizeExpr, SizeValue))
198 return false;
199
200 if (!SizeValue.isInt())
201 return false;
202 uint64_t Size = SizeValue.getInt().getZExtValue();
203
204 auto PtrRes = C.interpretAsPointer(PtrExpr, [&](InterpState &S, CodePtr OpPC,
205 const Pointer &Ptr) {
206 if (Size == 0) {
207 if constexpr (std::is_same_v<ResultT, APValue>)
209 return true;
210 }
211
212 if (Ptr.isZero()) {
213 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
214 << AK_Read;
215 return false;
216 }
217
218 if (!Ptr.isLive() || !Ptr.isInitialized() || Ptr.isUnknownSizeArray() ||
219 !Ptr.inArray())
220 return false;
221
222 // Must be char.
223 if (Ptr.isBlockPointer() &&
224 Ptr.getFieldDesc()->getElemDataSize() != 1 /*bytes*/)
225 return false;
226 if (Ptr.isStringPointer() &&
227 !Ptr.asStringPointer().getLiteral()->isOrdinary())
228 return false;
229
230 bool Limited = false;
231 if (Size > Ptr.getNumElems()) {
232 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
233 << AK_Read;
234 Size = Ptr.getNumElems();
235 Limited = true;
236 }
237
238 if constexpr (std::is_same_v<ResultT, APValue>) {
239 QualType CharTy = PtrExpr->getType()->getPointeeType();
240 Result = APValue(APValue::UninitArray{}, Size, Size);
241 for (uint64_t I = 0; I != Size; ++I) {
242 if (std::optional<APValue> ElemVal =
243 Ptr.atIndex(I).toRValue(*this, CharTy))
244 Result.getArrayInitializedElt(I) = *ElemVal;
245 else
246 return false;
247 }
248 } else {
249 assert((std::is_same_v<ResultT, std::string>));
250 if (Size < Result.max_size())
251 Result.resize(Size);
252
253 const char *Addr = reinterpret_cast<const char *>(Ptr.getRawAddress());
254
255 if (Ptr.isStringPointer())
256 Result.assign(Addr, Size - static_cast<unsigned>(Limited));
257 else
258 Result.assign(Addr, Size);
259 }
260
261 return true;
262 });
263
264 if (PtrRes.isInvalid()) {
265 C.cleanup();
266 Stk.clear();
267 return false;
268 }
269
270 return true;
271}
272
273bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
274 const Expr *PtrExpr, APValue &Result) {
275 assert(SizeExpr);
276 assert(PtrExpr);
277
278 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
279}
280
281bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
282 const Expr *PtrExpr, std::string &Result) {
283 assert(SizeExpr);
284 assert(PtrExpr);
285
286 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
287}
288
289bool Context::evaluateString(State &Parent, const Expr *E,
290 std::string &Result) {
291 assert(Stk.empty());
292 Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
293
294 auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
295 const Pointer &Ptr) {
296 if (!Ptr.isReadablePointerType())
297 return false;
298
299 if (!Ptr.isConst())
300 return false;
301
302 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
303 return false;
304
305 unsigned N = Ptr.getNumElems();
306
307 if (Ptr.elemSize() == 1 /* bytes */) {
308 const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
309 if (Ptr.isStringPointer()) {
310 Result.assign(Chars, N - 1);
311 return true;
312 }
313 unsigned Length = strnlen(Chars, N);
314 // Wasn't null terminated.
315 if (N == Length)
316 return false;
317 Result.assign(Chars, Length);
318 return true;
319 }
320
321 PrimType ElemT;
322 if (Ptr.isBlockPointer()) {
323 ElemT = Ptr.getFieldDesc()->getPrimType();
324 } else {
325 // It may happen here that the string literal has not been decayed or
326 // indexed, so check the element type in that case.
327 assert(Ptr.isStringPointer());
328 if (!Ptr.asStringPointer().Decayed)
329 ElemT =
330 *classify(Ptr.getType()->getAsArrayTypeUnsafe()->getElementType());
331 else
332 ElemT = *classify(Ptr.getType());
333 }
334 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
335 INT_TYPE_SWITCH(ElemT, {
336 auto Elem = Ptr.loadElem<T>(I);
337 if (Elem.isZero())
338 return true;
339 Result.push_back(static_cast<char>(Elem));
340 });
341 }
342 // We didn't find a 0 byte.
343 return false;
344 });
345
346 if (PtrRes.isInvalid()) {
347 C.cleanup();
348 Stk.clear();
349 return false;
350 }
351 return true;
352}
353
354std::optional<uint64_t> Context::evaluateStrlen(State &Parent, const Expr *E) {
355 assert(Stk.empty());
356 Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
357
358 std::optional<uint64_t> Result;
359 auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
360 const Pointer &Ptr) {
361 if (!Ptr.isReadablePointerType())
362 return false;
363
364 if (Ptr.isPastEnd())
365 return false;
366
367 if (Ptr.isStringPointer()) {
368 const auto *Lit = Ptr.asStringPointer().getLiteral();
369 int64_t Off = Ptr.getByteOffset();
370 if (Off < 0)
371 return false;
372
373 UnsignedOrNone ZeroIndex = Lit->findZeroCodeUnit(Off);
374 if (!ZeroIndex)
375 return false;
376 Result = *ZeroIndex;
377 return true;
378 }
379
380 const Descriptor *FieldDesc = Ptr.getFieldDesc();
381 if (!FieldDesc->isPrimitiveArray())
382 return false;
383
384 if (Ptr.isDummy() || Ptr.isUnknownSizeArray())
385 return false;
386
387 PrimType ElemT = FieldDesc->getPrimType();
388 if (!isIntegerType(ElemT))
389 return false;
390
391 unsigned N = Ptr.getNumElems();
392 if (Ptr.elemSize() == 1) {
393 unsigned Size = N - Ptr.getIndex();
394 Result =
395 strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
396 return Result != Size;
397 }
398
399 Result = 0;
400 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
401 INT_TYPE_SWITCH(ElemT, {
402 auto Elem = Ptr.elem<T>(I);
403 if (Elem.isZero())
404 return true;
405 ++(*Result);
406 });
407 }
408 // We didn't find a 0 byte.
409 return false;
410 });
411
412 if (PtrRes.isInvalid()) {
413 C.cleanup();
414 Stk.clear();
415 return std::nullopt;
416 }
417 return Result;
418}
419
420std::optional<uint64_t> Context::tryEvaluateObjectSize(State &Parent,
421 const Expr *E,
422 unsigned Kind,
423 bool IsDynamic) {
424 assert(Stk.empty());
425 Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
426
427 std::optional<uint64_t> Result;
428 auto PtrRes = C.interpretAsLValuePointer(E, [&](InterpState &S, CodePtr OpPC,
429 const Pointer &Ptr) {
430 QualType T = Ptr.getType().getNonReferenceType();
431 if (T->isIncompleteType() || T->isFunctionType() ||
432 !T->isConstantSizeType())
433 return false;
434
435 Pointer P = Ptr;
436 if (auto ObjectSize =
437 evaluateBuiltinObjectSize(getASTContext(), Kind, P, E, IsDynamic)) {
438 Result = *ObjectSize;
439 return true;
440 }
441 return false;
442 });
443
444 if (PtrRes.isInvalid()) {
445 C.cleanup();
446 Stk.clear();
447 return std::nullopt;
448 }
449 return Result;
450}
451
452std::optional<bool>
454 ArrayRef<const Expr *> Args, const Expr *This,
455 const Expr *Condition) {
456 if (OptPrimType ConditionT = classify(Condition);
457 !ConditionT || ConditionT != PT_Bool) {
458 return std::nullopt;
459 }
460
461 assert(Stk.empty());
462 Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
463 std::optional<bool> Result =
464 C.interpretWithSubstitutions(Callee, Args, This, Condition);
465
466 // This is somewhat of a special case here. We don't allow
467 // evaluateWithSubstitution to recurse (see the Stk.empty() assertion above),
468 // BUT we allow the args to fail evaluation, which means they can leave some
469 // garbage on the stack. So we always clear() here, not only if the evaluation
470 // failed.
471 Stk.clear();
472 if (!Result) {
473 C.cleanup();
474 return std::nullopt;
475 }
476 return Result;
477}
478
479const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
480
481static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
482 switch (BitWidth) {
483 case 64:
484 return PT_Sint64;
485 case 32:
486 return PT_Sint32;
487 case 16:
488 return PT_Sint16;
489 case 8:
490 return PT_Sint8;
491 default:
492 return PT_IntAPS;
493 }
494 llvm_unreachable("Unhandled BitWidth");
495}
496
497static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
498 switch (BitWidth) {
499 case 64:
500 return PT_Uint64;
501 case 32:
502 return PT_Uint32;
503 case 16:
504 return PT_Uint16;
505 case 8:
506 return PT_Uint8;
507 default:
508 return PT_IntAP;
509 }
510 llvm_unreachable("Unhandled BitWidth");
511}
512
514 T = T.getCanonicalType();
515
516 if (const auto *BT = dyn_cast<BuiltinType>(T)) {
517 auto Kind = BT->getKind();
518 if (Kind == BuiltinType::Bool)
519 return PT_Bool;
520 if (Kind == BuiltinType::NullPtr)
521 return PT_Ptr;
522 if (Kind == BuiltinType::BoundMember)
523 return PT_MemberPtr;
524
525 // Just trying to avoid the ASTContext::getIntWidth call below.
526 if (Kind == BuiltinType::Short)
527 return integralTypeToPrimTypeS(this->ShortWidth);
528 if (Kind == BuiltinType::UShort)
529 return integralTypeToPrimTypeU(this->ShortWidth);
530
531 if (Kind == BuiltinType::Int)
532 return integralTypeToPrimTypeS(this->IntWidth);
533 if (Kind == BuiltinType::UInt)
534 return integralTypeToPrimTypeU(this->IntWidth);
535 if (Kind == BuiltinType::Long)
536 return integralTypeToPrimTypeS(this->LongWidth);
537 if (Kind == BuiltinType::ULong)
538 return integralTypeToPrimTypeU(this->LongWidth);
539 if (Kind == BuiltinType::LongLong)
540 return integralTypeToPrimTypeS(this->LongLongWidth);
541 if (Kind == BuiltinType::ULongLong)
542 return integralTypeToPrimTypeU(this->LongLongWidth);
543
544 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
545 return integralTypeToPrimTypeS(8);
546 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
547 Kind == BuiltinType::Char8)
548 return integralTypeToPrimTypeU(8);
549
550 if (BT->isSignedInteger())
551 return integralTypeToPrimTypeS(Ctx.getIntWidth(T));
552 if (BT->isUnsignedInteger())
553 return integralTypeToPrimTypeU(Ctx.getIntWidth(T));
554
555 if (BT->isFloatingPoint())
556 return PT_Float;
557 }
558
559 if (T->isPointerOrReferenceType())
560 return PT_Ptr;
561
562 if (T->isMemberPointerType())
563 return PT_MemberPtr;
564
565 if (const auto *BT = T->getAs<BitIntType>()) {
566 if (BT->isSigned())
567 return integralTypeToPrimTypeS(BT->getNumBits());
568 return integralTypeToPrimTypeU(BT->getNumBits());
569 }
570
571 if (const auto *D = T->getAsEnumDecl()) {
572 if (!D->isComplete())
573 return std::nullopt;
574 return classify(D->getIntegerType());
575 }
576
577 if (const auto *AT = T->getAs<AtomicType>())
578 return classify(AT->getValueType());
579
580 if (const auto *OBT = T->getAs<OverflowBehaviorType>())
581 return classify(OBT->getUnderlyingType());
582
583 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
584 return PT_Ptr;
585
586 if (T->isFixedPointType())
587 return PT_FixedPoint;
588
589 // Vector and complex types get here.
590 return std::nullopt;
591}
592
593unsigned Context::getCharBit() const {
594 return Ctx.getTargetInfo().getCharWidth();
595}
596
597/// Simple wrapper around getFloatTypeSemantics() to make code a
598/// little shorter.
599const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
600 return Ctx.getFloatTypeSemantics(T);
601}
602
603bool Context::Run(State &Parent, const Function *Func) {
604 auto Memory = std::make_unique<char[]>(InterpFrame::allocSize(Func));
605 InterpState State(Parent, *P, Stk, FrameAlloc, *this, Func);
606 InterpFrame *Frame = new (Memory.get()) InterpFrame(
607 State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
608 State.Current = Frame;
609
610 if (Interpret(State)) {
611 assert(Stk.empty());
612 return true;
613 }
614
615 Stk.clear();
616 Frame->~InterpFrame();
617 State.Current = &State.BottomFrame;
618 return false;
619}
620
621const CXXMethodDecl *
623 const CXXRecordDecl *StaticDecl,
624 const CXXMethodDecl *InitialFunction) const {
625 assert(DynamicDecl);
626 assert(StaticDecl);
627 assert(InitialFunction);
628
629 const CXXRecordDecl *CurRecord = DynamicDecl;
630 const CXXMethodDecl *FoundFunction = InitialFunction;
631 for (;;) {
632 const CXXMethodDecl *Overrider =
633 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
634 if (Overrider)
635 return Overrider;
636
637 // Common case of only one base class.
638 if (CurRecord->getNumBases() == 1) {
639 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
640 continue;
641 }
642
643 // Otherwise, go to the base class that will lead to the StaticDecl.
644 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
645 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
646 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
647 CurRecord = Base;
648 break;
649 }
650 }
651 }
652
653 llvm_unreachable(
654 "Couldn't find an overriding function in the class hierarchy?");
655 return nullptr;
656}
657
659 assert(FuncDecl);
660 if (const Function *Func = P->getFunction(FuncDecl))
661 return Func;
662
663 // Manually created functions that haven't been assigned proper
664 // parameters yet.
665 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
666 return nullptr;
667
668 bool IsLambdaStaticInvoker = false;
669 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
670 MD && MD->isLambdaStaticInvoker()) {
671 // For a lambda static invoker, we might have to pick a specialized
672 // version if the lambda is generic. In that case, the picked function
673 // will *NOT* be a static invoker anymore. However, it will still
674 // be a non-static member function, this (usually) requiring an
675 // instance pointer. We suppress that later in this function.
676 IsLambdaStaticInvoker = true;
677 }
678 // Set up argument indices.
679 unsigned ParamOffset = 0;
680
681 // If the return is not a primitive, a pointer to the storage where the
682 // value is initialized in is passed as the first argument. See 'RVO'
683 // elsewhere in the code.
684 QualType Ty = FuncDecl->getReturnType();
685 bool HasRVO = false;
686 if (!Ty->isVoidType() && !canClassify(Ty)) {
687 HasRVO = true;
689 }
690
691 // If the function decl is a member decl, the next parameter is
692 // the 'this' pointer. This parameter is pop()ed from the
693 // InterpStack when calling the function.
694 bool HasThisPointer = false;
695 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
696 if (!IsLambdaStaticInvoker) {
697 HasThisPointer = MD->isInstance();
698 if (MD->isImplicitObjectMemberFunction())
700 }
701
702 if (isLambdaCallOperator(MD)) {
703 // The parent record needs to be complete, we need to know about all
704 // the lambda captures.
705 if (!MD->getParent()->isCompleteDefinition())
706 return nullptr;
707 if (MD->isStatic()) {
708 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
709 FieldDecl *LTC;
710
711 MD->getParent()->getCaptureFields(LC, LTC);
712 // Static lambdas cannot have any captures. If this one does,
713 // it has already been diagnosed and we can only ignore it.
714 if (!LC.empty())
715 return nullptr;
716 }
717 }
718 }
719
720 // Assign descriptors to all parameters.
721 // Composite objects are lowered to pointers.
723 ParamDescriptors.reserve(FuncDecl->getNumParams());
724
725 const auto *FuncProto = FuncDecl->getType()->getAs<FunctionProtoType>();
726 unsigned BlockOffset = 0;
727 for (auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->parameters())) {
728 bool IsConst = PD->getType().isConstQualified();
729 bool IsVolatile = PD->getType().isVolatileQualified();
730
731 if (PD->isInvalidDecl() ||
732 !getASTContext().hasSameType(PD->getType(),
733 FuncProto->getParamType(ParamIndex)))
734 return nullptr;
735
736 OptPrimType T = classify(PD->getType());
737 PrimType PT = T.value_or(PT_Ptr);
738 Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, IsConst,
739 /*IsTemporary=*/false,
740 /*IsMutable=*/false, IsVolatile);
741 unsigned PrimTSize = align(primSize(PT));
742 ParamDescriptors.emplace_back(Desc, ParamOffset, BlockOffset, PT);
743 ParamOffset += PrimTSize;
744 BlockOffset += sizeof(Block) + PrimTSize;
745 }
746
747 // Create a handle over the emitted code.
748 assert(!P->getFunction(FuncDecl));
749 const Function *Func =
750 P->createFunction(FuncDecl, ParamOffset, std::move(ParamDescriptors),
751 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
752 return Func;
753}
754
756 const BlockDecl *BD = E->getBlockDecl();
757 // Set up argument indices.
758 unsigned ParamOffset = 0;
760
761 // Assign descriptors to all parameters.
762 // Composite objects are lowered to pointers.
763 for (const ParmVarDecl *PD : BD->parameters()) {
764 bool IsConst = PD->getType().isConstQualified();
765 bool IsVolatile = PD->getType().isVolatileQualified();
766
767 OptPrimType T = classify(PD->getType());
768 PrimType PT = T.value_or(PT_Ptr);
769 Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, IsConst,
770 /*IsTemporary=*/false,
771 /*IsMutable=*/false, IsVolatile);
772 ParamDescriptors.emplace_back(Desc, ParamOffset, ~0u, PT);
773 ParamOffset += align(primSize(PT));
774 }
775
776 if (BD->hasCaptures())
777 return nullptr;
778
779 // Create a handle over the emitted code.
780 Function *Func =
781 P->createFunction(E, ParamOffset, std::move(ParamDescriptors),
782 /*HasThisPointer=*/false, /*HasRVO=*/false,
783 /*IsLambdaStaticInvoker=*/false);
784
785 assert(Func);
786 Func->setDefined(true);
787 // We don't compile the BlockDecl code at all right now.
788 Func->setIsFullyCompiled(true);
789
790 return Func;
791}
792
793unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
794 const RecordDecl *DerivedDecl) const {
795 assert(BaseDecl);
796 assert(DerivedDecl);
797 const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
798 const RecordDecl *CurDecl = DerivedDecl;
799 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
800 assert(CurDecl && FinalDecl);
801
802 unsigned OffsetSum = 0;
803 for (;;) {
804 assert(CurRecord->getNumBases() > 0);
805 // One level up
806 for (const Record::Base &B : CurRecord->bases()) {
807 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
808
809 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
810 OffsetSum += B.Offset;
811 CurRecord = B.R;
812 CurDecl = BaseDecl;
813 break;
814 }
815 }
816 if (CurDecl == FinalDecl)
817 break;
818 }
819
820 assert(OffsetSum > 0);
821 return OffsetSum;
822}
823
824const Record *Context::getRecord(const RecordDecl *D) const {
825 return P->getOrCreateRecord(D);
826}
827
829 return ID == Builtin::BI__builtin_classify_type ||
830 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
831 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
832}
#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:481
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
Definition Context.cpp:497
#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: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:239
A fixed int type of a specified bitwidth.
Definition TypeBase.h:8286
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
bool isGLValue() const
Definition Expr.h:288
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:5398
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:9037
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:8764
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:881
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9264
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
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:479
void registerRedecl(const VarDecl *VD, const APValue &V)
Definition Context.cpp:182
const Function * getOrCreateObjCBlock(const BlockExpr *E)
Definition Context.cpp:755
~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:273
std::optional< uint64_t > evaluateStrlen(State &Parent, const Expr *E)
Evalute.
Definition Context.cpp:354
std::optional< bool > evaluateWithSubstitution(State &Parent, const FunctionDecl *Callee, ArrayRef< const Expr * > Args, const Expr *This, const Expr *Condition)
Definition Context.cpp:453
bool evaluateString(State &Parent, const Expr *E, std::string &Result)
Evaluate.
Definition Context.cpp:289
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
Definition Context.cpp:828
unsigned getCharBit() const
Returns CHAR_BIT.
Definition Context.cpp:593
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
Definition Context.cpp:599
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
Definition Context.h:168
std::optional< uint64_t > tryEvaluateObjectSize(State &Parent, const Expr *E, unsigned Kind, bool IsDynamic)
If.
Definition Context.cpp:420
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:793
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:824
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:658
ASTContext & getASTContext() const
Returns the AST context.
Definition Context.h:109
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:513
bool canClassify(QualType T) const
Definition Context.h:131
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:622
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: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:46
InterpFrame * Current
The current frame.
A pointer to a memory block, live or dead.
Definition Pointer.h:540
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:3232
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2429
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:3822
Top level wrappers for InstallAPI frontend operations.
Expr::ConstantExprKind ConstantExprKind
Definition Expr.h:1062
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