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