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