Thanks to visit codestin.com
Credit goes to clang.llvm.org

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