8#include <clang/AST/VTableBuilder.h>
26using namespace asthelpers;
30static llvm::DenseMap<std::pair<const CXXRecordDecl*, const CXXRecordDecl*>,
int>
mThisPointerOffset{};
33static MemberExpr*
AccessMember(std::string_view name,
const ValueDecl* vd, QualType type)
46 vtableRecorDecl =
Struct(
"__mptr"sv);
47 auto AddField = [&](FieldDecl* field) { vtableRecorDecl->addDecl(field); };
52 f =
mkFieldDecl(vtableRecorDecl,
"f"sv, vptpTypedef);
55 vtableRecorDecl->completeDefinition();
58#if IS_CLANG_NEWER_THAN(22)
59 vtableRecorDecl->getASTContext().getCanonicalTagType(vtableRecorDecl);
61 QualType{vtableRecorDecl->getTypeForDecl(), 0u};
86CodeGeneratorVariant::CodeGenerators::CodeGenerators(
OutputFormatHelper& _outputFormatHelper,
88 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
91 new(&cfcg)
CfrontCodeGenerator{_outputFormatHelper, lambdaStack, processingPrimaryTemplate};
93 new(&cg) CodeGenerator{_outputFormatHelper, lambdaStack, processingPrimaryTemplate};
98CodeGeneratorVariant::CodeGenerators::CodeGenerators(OutputFormatHelper& _outputFormatHelper)
101 new(&cfcg) CfrontCodeGenerator{_outputFormatHelper};
103 new(&cg) CodeGenerator{_outputFormatHelper};
108CodeGeneratorVariant::CodeGenerators::~CodeGenerators()
111 cfcg.~CfrontCodeGenerator();
118void CodeGeneratorVariant::Set()
130 return ctor and (ctor->isCopyConstructor() or ctor->isMoveConstructor());
136 return stmt and (stmt->isCopyAssignmentOperator() or stmt->isMoveAssignmentOperator());
142 if(
const auto* md = dyn_cast_or_null<CXXMethodDecl>(vd)) {
144 if(
const auto* ar = dyn_cast_or_null<ArrayType>(type)) {
145 type = ar->getElementType();
150 if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(md)) {
151 if(ctor->isCopyConstructor()) {
152 return StrCat(
"CopyConstructor_"sv, rdName);
153 }
else if(ctor->isMoveConstructor()) {
154 return StrCat(
"MoveConstructor_"sv, rdName);
157 return StrCat(
"Constructor_"sv, rdName);
159 }
else if(isa<CXXDestructorDecl>(md)) {
160 return StrCat(
"Destructor_"sv, rdName);
170 if(
const auto* md = dyn_cast_or_null<CXXMethodDecl>(vd)) {
186 if(
auto* cxxRecordDecl = t->getAsCXXRecordDecl(); cxxRecordDecl and not cxxRecordDecl->isTrivial()) {
196 if(
auto* cxxRecordDecl = t->getAsCXXRecordDecl(); cxxRecordDecl and not cxxRecordDecl->hasTrivialDestructor()) {
204static auto*
CallVecDeleteOrDtor(Expr* objectParam, QualType allocatedType, std::string_view name, uint64_t size)
208 SmallVector<Expr*, 4> args{objectParam,
213 return Call(name, args);
225static auto*
CallVecDtor(Expr* objectParam,
const ConstantArrayType* ar)
235 auto destroyedType = stmt->getDestroyedType();
236 auto* arg =
const_cast<Expr*
>(stmt->getArgument());
240 if(
const auto hasDtor{
HasDtor(destroyedType)}; stmt->isArrayForm() and hasDtor) {
248 bodyStmts.Add(
Call(
"free"sv, {arg}));
257 QualType allocatedType,
259 std::string_view funName)
264 auto dtorName = [&]() {
269 return std::string{
kwNull};
272 SmallVector<Expr*, 6> args{objectParam,
279 return Call(funName, args);
283static auto*
CallVecNew(std::string_view ctorName, Expr* objectParam, QualType allocatedType, Expr* arraySizeExpr)
287 return CallVecNewOrCtor(ctorName, objectParam, allocatedType, arraySizeExpr,
"__cxa_vec_new"sv);
292CallVecCtor(std::string_view ctorName,
const VarDecl* objectParam, QualType allocatedType, Expr* arraySizeExpr)
302 auto* stmt =
const_cast<CXXNewExpr*
>(cstmt);
304 auto allocatedType = stmt->getAllocatedType();
305 auto ctorName =
StrCat(
"Constructor_"sv,
GetName(allocatedType));
307 if(stmt->isArray()) {
310 auto* arraySizeExpr = stmt->getArraySize().value();
311 auto* callMalloc =
Call(
"malloc"sv, {
Mul(
Sizeof(allocatedType), arraySizeExpr)});
318 assign =
Cast(callMalloc,
Ptr(allocatedType));
321 if(allocatedType->getAsCXXRecordDecl()->ctors().empty()) {
327 assign =
Cast(
CallVecNew(ctorName, callMalloc, allocatedType, arraySizeExpr),
Ptr(allocatedType));
332 if(stmt->hasInitializer() and allocatedType->isBuiltinType()) {
348 if(
auto* inits = dyn_cast_or_null<InitListExpr>(stmt->getInitializer())) {
349 auto* expr = [&]() ->
const Expr* {
350 if(
auto* vd = dyn_cast_or_null<VarDecl>(
mLastDecl)) {
372 auto* mallocCall = [&]() -> Expr* {
373 if(stmt->getNumPlacementArgs()) {
374 return stmt->getPlacementArg(0);
379 return Call(
"malloc"sv, {
Sizeof(allocatedType)});
382 mallocCall =
Cast(mallocCall,
Ptr(allocatedType));
384 if(allocatedType->isBuiltinType()) {
387 if(stmt->hasInitializer()) {
415 SmallVector<Expr*, 16> args{mallocCall};
416 if(
auto* ncCtorExpr =
const_cast<CXXConstructExpr*
>(stmt->getConstructExpr())) {
417 args.append(ncCtorExpr->arg_begin(), ncCtorExpr->arg_end());
426 const auto* callee = stmt->getDirectCallee();
428 if(
const auto* cxxCallee = dyn_cast_or_null<CXXMethodDecl>(callee);
IsCopyOrMoveAssign(cxxCallee)) {
429 SmallVector<Expr*, 16> args{};
431 for(
const auto& arg : stmt->arguments()) {
432 args.push_back(
Ref(arg));
438 InsertArg(dyn_cast_or_null<CallExpr>(stmt));
445 if(cur->isPolymorphic() and (0 == cur->getNumBases())) {
456 }
else if(cur->isPolymorphic() and (0 < cur->getNumBases()) and (cur != stmt->getParent())) {
457 for(
const auto& base : cur->bases()) {
458 InsertVtblPtr(stmt, base.getType()->getAsCXXRecordDecl(), bodyStmts);
468 (
IsCopyOrMoveAssign(stmt) or (not stmt->hasBody() and not isa<CXXConstructorDecl>(stmt))));
474 if(stmt->isConst()) {
475 recordDeclType.addConst();
478 auto parentType =
Ptr(recordDeclType);
479 auto* body = stmt->getBody();
482 auto retType = stmt->getReturnType();
484 auto processBaseClassesAndFields = [&](
const CXXRecordDecl* parent) {
487 auto insertFields = [&](
const RecordDecl* rd) {
488 for(
auto* fieldDecl : rd->fields()) {
489 if(
const auto* cxxRecordDecl = fieldDecl->getType()->getAsCXXRecordDecl()) {
493 auto lvalueRefType =
GetGlobalAST().getLValueReferenceType(parentType);
495 auto* rhsMemberExpr =
AccessMember(
"__rhs"sv, fieldDecl, lvalueRefType);
499 {
Ref(lhsMemberExpr),
Ref(rhsMemberExpr)}));
502 auto* rhsMemberExpr =
AccessMember(
"__rhs"sv, fieldDecl, parentType);
504 bodyStmts.AddBodyStmts(
Assign(thisOfParent, fieldDecl, rhsMemberExpr));
509 for(
const auto& base : parent->bases()) {
510 const auto rd = base.getType()->getAsRecordDecl();
518 bodyStmts.AddBodyStmts(callAssignBase);
522 insertFields(parent);
526 if(
const auto* ctorDecl = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
527 const auto* parent = stmt->getParent();
529 if(not stmt->doesThisDeclarationHaveABody()) {
531 if(
const bool showSpecialMemberFunc{stmt->isUserProvided() or stmt->isExplicitlyDefaulted()};
532 not showSpecialMemberFunc) {
536 processBaseClassesAndFields(parent);
538 }
else if(ctorDecl->isDefaultConstructor()) {
539 auto insertFields = [&](
const RecordDecl* rd) {
540 for(
auto* fieldDecl : rd->fields()) {
541 if(
auto* initializer = fieldDecl->getInClassInitializer();
542 initializer and fieldDecl->hasInClassInitializer()) {
543 const bool isConstructorExpr{isa<CXXConstructExpr>(initializer) or
544 isa<ExprWithCleanups>(initializer)};
546 if(not isConstructorExpr) {
549 bodyStmts.AddBodyStmts(
Assign(lhsMemberExpr, fieldDecl, initializer));
560 }
else if(
const auto* cxxRecordDecl = fieldDecl->getType()->getAsCXXRecordDecl()) {
564 if(
auto lhsType = fieldDecl->getType();
HasCtor(lhsType)) {
581 for(
const auto& base : parent->bases()) {
582 auto baseType = base.getType();
584 if(
const auto* baseRd = baseType->getAsCXXRecordDecl();
585 baseRd and baseRd->hasNonTrivialDefaultConstructor()) {
586 bodyStmts.AddBodyStmts(
CallConstructor(baseType,
Ptr(baseType),
nullptr, {}, DoCast::Yes));
594 for(
const auto& base : parent->bases()) {
595 InsertVtblPtr(stmt, base.getType()->getAsCXXRecordDecl(), bodyStmts);
599 insertFields(parent);
603 for(
const auto* init : ctorDecl->inits()) {
604 auto* member = init->getMember();
606 if(not isa<CXXConstructExpr>(init->getInit())) {
607 if(not init->getAnyMember()) {
613 bodyStmts.AddBodyStmts(
Assign(lhsMemberExpr, member, init->getInit()));
616 }
else if(init->isBaseInitializer()) {
617 bodyStmts.AddBodyStmts(init->getInit());
621 auto ctorType = member->getType();
626 callParams.insert(callParams.begin(),
Ref(lhsMemberExpr));
628 bodyStmts.AddBodyStmts(
635 for(
const auto& base : parent->bases()) {
636 InsertVtblPtr(stmt, base.getType()->getAsCXXRecordDecl(), bodyStmts);
641 bodyStmts.AddBodyStmts(body);
647 retType = parentType;
651 if(not stmt->doesThisDeclarationHaveABody() or stmt->isDefaulted()) {
656 processBaseClassesAndFields(stmt->getParent());
658 bodyStmts.AddBodyStmts(body);
664 retType = parentType;
666 }
else if(
const auto* dtor = dyn_cast_or_null<CXXDestructorDecl>(stmt)) {
675 for(
const auto& base : llvm::reverse(dtor->getParent()->bases())) {
676 if(not dtor->isVirtual()) {
680 InsertVtblPtr(stmt, dyn_cast_or_null<CXXRecordDecl>(base.getType()->getAsRecordDecl()), bodyStmts);
684 bodyStmts.AddBodyStmts(body);
687 for(
const auto& base : llvm::reverse(dtor->getParent()->bases())) {
688 if(not dtor->isVirtual()) {
693 auto* cast =
Cast(lhsDeclRef, lhsDeclRef->getType());
703 params.reserve(stmt->getNumParams() + 1);
709 for(
const auto& param : stmt->parameters()) {
710 std::string name{
GetName(*param)};
711 auto type = param->getType();
714 if((0 == name.length()) and
717 type =
Ptr(type.getNonReferenceType());
720 params.emplace_back(name, type);
724 callSpecialMemberFn->setInlineSpecified(stmt->isInlined());
725 callSpecialMemberFn->setStorageClass((stmt->isStatic() or
IsStaticStorageClass(stmt)) ? SC_Static : SC_None);
726 callSpecialMemberFn->setBody(body);
735 const QualType& castDestType,
737 const CastKind& kind)
741 if(not castDestType->isRValueReferenceType() and not(CastKind::CK_UncheckedDerivedToBase == kind)) {
747 if(
is{kind}.
any_of(CastKind::CK_DerivedToBase, CastKind::CK_BaseToDerived)) {
750 sign] = [&]() -> std::pair<std::pair<const CXXRecordDecl*, const CXXRecordDecl*>, std::string_view> {
751 auto plainType = [](QualType t) {
752 if(
const auto* pt = dyn_cast_or_null<PointerType>(t.getTypePtrOrNull())) {
753 return pt->getPointeeType()->getAsCXXRecordDecl();
756 return t->getAsCXXRecordDecl();
759 auto base = plainType(castDestType);
760 auto derived = plainType(subExpr->getType());
762 if((CastKind::CK_BaseToDerived == kind)) {
763 return {{base, derived},
"-"sv};
766 return {{derived, base},
"+"sv};
800 if(stmt->getMessage()) {
817static void ProcessFields(CXXRecordDecl* recordDecl,
const CXXRecordDecl* rd)
821 auto AddField = [&](
const FieldDecl* field) {
826 for(
const auto& base : rd->bases()) {
828 if(
const auto* rdBase = dyn_cast_or_null<CXXRecordDecl>(base.getType().getCanonicalType()->getAsRecordDecl())) {
834 if(rd->isPolymorphic() and (rd->getNumBases() == 0)) {
839 for(
const auto* d : rd->fields()) {
843 if(recordDecl->field_empty()) {
851 std::string ret{
GetName(*decl)};
853 if(
const auto* rdecl = dyn_cast_or_null<CXXRecordDecl>(decl); rdecl->getNumBases() > 1) {
854 for(
const auto& base : rdecl->bases()) {
855 if(
const auto* rd = base.getType()->getAsRecordDecl(); rd == to) {
869 if(
const auto* rdecl = dyn_cast_or_null<CXXRecordDecl>(decl); rdecl->getNumBases() >= 1) {
870 for(
const auto& base : rdecl->bases()) {
871 const auto* rd = base.getType()->getAsRecordDecl();
873 if(
const auto* cxxRd = dyn_cast_or_null<CXXRecordDecl>(rd); not cxxRd or not cxxRd->isPolymorphic()) {
883 return dyn_cast_or_null<CXXRecordDecl>(decl);
891 if(stmt->hasDefinition() and stmt->isPolymorphic()) {
893 static_cast<ItaniumVTableContext*
>(
const_cast<ASTContext&
>(
GetGlobalAST()).getVTableContext())) {
896 auto* mc =
const_cast<ASTContext&
>(
GetGlobalAST()).createMangleContext(
nullptr);
897 SmallString<256> rttiName{};
898 llvm::raw_svector_ostream out(rttiName);
899 mc->mangleCXXRTTI(QualType(stmt->getTypeForDecl(), 0), out);
900 DPrint(
"name: %s\n", rttiName.c_str());
903 SmallVector<Expr*, 16> mInitExprs{};
904 SmallVector<QualType, 5> baseList{};
906 if(stmt->getNumBases() == 0) {
910 for(
const auto& base : stmt->bases()) {
911 baseList.push_back(base.getType());
914 llvm::DenseMap<uint64_t, ThunkInfo> thunkMap{};
915 const VTableLayout& layout{itctx->getVTableLayout(stmt)};
917 for(
const auto& [idx, thunk] : layout.vtable_thunks()) {
918 thunkMap[idx] = thunk;
925 auto pushVtable = [&] {
930 auto* thisRd = baseList[clsIdx - 1]->getAsCXXRecordDecl();
933 vtabl->setInit(
InitList(mInitExprs, vtblData.vtableRecordType));
943 for(
unsigned i = 0;
const auto& vc : layout.vtable_components()) {
944 switch(vc.getKind()) {
945 case VTableComponent::CK_OffsetToTop: {
946 auto off = layout.getVTableOffset(clsIdx);
947 if(
auto rem = (off % 4)) {
959 case VTableComponent::CK_RTTI:
967 case VTableComponent::CK_CompleteDtorPointer:
969 case VTableComponent::CK_DeletingDtorPointer:
970 case VTableComponent::CK_FunctionPointer: {
971 auto* thunkOffset = [&] {
972 if(ThunkInfo thunk = thunkMap.lookup(i); not thunk.isEmpty() and not thunk.This.isEmpty()) {
973 return Int32(thunk.This.NonVirtual);
979 const auto* md = dyn_cast_or_null<FunctionDecl>(vc.getFunctionDecl());
982 if(md->isPureVirtual()) {
995 mInitExprs.push_back(
InitList({thunkOffset,
Int32(0), reicast}, vtblData.vtableRecordType));
1012 if(stmt->hasDefinition()) {
1014 recordDecl->completeDefinition();
1025 auto et = ctx.getElaboratedType(ElaboratedTypeKeyword::ETK_Struct,
nullptr,
GetRecordDeclType(recordDecl),
nullptr);
1031 for(
OnceTrue firstRecordDecl{};
const auto* d : stmt->decls()) {
1032 if((isa<CXXRecordDecl>(d) and firstRecordDecl)
1033 or (stmt->isLambda() and isa<CXXDestructorDecl>(d))
1034 or isa<FieldDecl>(d)
1035 or isa<AccessSpecDecl>(d)
1041 if((stmt->isTrivial() and isa<CXXConstructorDecl>(d)) or
1042 (stmt->hasTrivialDestructor() and isa<CXXDestructorDecl>(d))) {
1053 if(
const auto* me = dyn_cast_or_null<MemberExpr>(stmt->getCallee())) {
1054 auto* obj = me->getBase();
1055 const bool isPointer{obj->getType()->isPointerType()};
1057 if(
const bool isReference =
IsReferenceType(dyn_cast_or_null<VarDecl>(obj->getReferencedDeclOfCallee()));
1058 not isPointer and not isReference) {
1062 if(
const auto* matExpr = dyn_cast_or_null<MaterializeTemporaryExpr>(me->getBase())) {
1063 if(
const auto* tmpExpr = dyn_cast_or_null<CXXBindTemporaryExpr>(matExpr->getSubExpr())) {
1064 if(
const auto* tmpObjExpr = dyn_cast_or_null<CXXTemporaryObjectExpr>(tmpExpr->getSubExpr())) {
1065 obj =
const_cast<CXXTemporaryObjectExpr*
>(tmpObjExpr);
1070 auto* memDecl = me->getMemberDecl();
1072 if(
const auto* ar = dyn_cast_or_null<ConstantArrayType>(obj->getType())) {
1073 if(
const auto* dtor = dyn_cast_or_null<CXXDestructorDecl>(memDecl)) {
1080 SmallVector<Expr*, 16> params{obj};
1081 auto* ncStmt =
const_cast<CXXMemberCallExpr*
>(stmt);
1082 params.append(ncStmt->arg_begin(), ncStmt->arg_end());
1084 if(
auto* md = dyn_cast_or_null<CXXMethodDecl>(memDecl); md and md->isVirtual()) {
1086 auto* cls = md->getParent();
1092 auto destType = not isPointer ?
Ptr(obj->getType()) : obj->getType();
1093 auto atype = isPointer ? obj->getType()->getPointeeType() : obj->getType();
1094 auto idx = mVirtualFunctions[{md, {atype->getAsCXXRecordDecl(), vRecordDecl}}];
1098 auto* vtblArrayPos =
ArraySubscript(accessVptr, idx, vtblField->getType());
1100 auto* p =
Paren(vtblArrayPos);
1101 auto* accessMemberF =
AccessMember(p, vtblData.f,
false);
1106 auto* reicast =
ReinterpretCast(funcPtrFuncDecl->getType(), accessMemberF,
true);
1108 auto* p4 =
Paren(reicast);
1110 auto* p6 =
Paren(p5);
1119 auto* p10 =
Paren(p9);
1120 auto* p11 =
Plus(p10, p7);
1121 auto* p12 =
Paren(p11);
1139 if(not stmt->isMain()) {
1145 SmallVector<Expr*, 16> args{};
1147 for(
auto* param : stmt->parameters()) {
1148 params.emplace_back(
GetName(*param), param->getType());
1152 auto mainName{
"main"sv};
1156 intMain->setBody(stmt->getBody());
1157 intMain->setHasImplicitReturnZero(
true);
1162 auto* mainRetVar =
Variable(
"ret"sv, stmt->getReturnType());
1163 mainRetVar->setInit(
Call(trampolinMainName, args));
1165 auto* mainRetVarDeclStmt =
mkDeclStmt(mainRetVar);
1171 modMain->setBody(body);
1179 if(
P0315Visitor dt{*
this}; not dt.TraverseType(stmt->getType())) {
1187 auto ctor = stmt->getConstructor();
1189 auto* vd = dyn_cast_or_null<VarDecl>(
mLastDecl);
1194 ar = dyn_cast_or_null<ConstantArrayType>(vd->getType());
1205 auto InsertCallCtor = [&](Expr* varNameRef) {
1206 SmallVector<Expr*, 16> args{
Cast(varNameRef,
Ptr(stmt->getType()))};
1208 for(
int i = 0;
auto* arg : stmt->arguments()) {
1209 if(
IsCopyOrMoveCtor(ctor) or ctor->getParamDecl(i)->getType()->isReferenceType()) {
1210 args.push_back(
Ref(arg));
1213 args.push_back(
const_cast<Expr*
>(arg));
1223 if(
const auto* ar = dyn_cast_or_null<ConstantArrayType>(stmt->getType())) {
1224 if(not
HasCtor(ar->getElementType())) {
1225 mInsertSemi =
false;
1231 }
else if(
const auto* tmpObjectExpr = dyn_cast_or_null<CXXTemporaryObjectExpr>(stmt); vd and not tmpObjectExpr) {
1232 if(not
HasCtor(vd->getType())) {
1233 mInsertSemi =
false;
1237 InsertCallCtor(varNameRef);
1240 }
else if(tmpObjectExpr) {
1243 if(not
HasCtor(stmt->getType())) {
1248 InsertCallCtor(varNameRef);
const InsightsOptions & GetInsightsOptions()
Get the global C++ Insights options.
const ASTContext & GetGlobalAST()
Get access to the ASTContext.
constexpr std::string_view kwNull
constexpr std::string_view cxaStart
constexpr std::string_view kwInternalThis
constexpr std::string_view kwTypedefSpace
constexpr std::string_view cxaAtExit
#define RETURN_IF(cond)
! A helper inspired by https://github.com/Microsoft/wil/wiki/Error-handling-helpers
constexpr bool empty() const noexcept
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
void InsertArg(const CXXThisExpr *) override
void InsertCXXMethodDecl(const CXXMethodDecl *, CodeGenerator::SkipBody) override
static CfrontVtableData & VtableData()
void FormatCast(const std::string_view, const QualType &, const Expr *, const CastKind &) override
void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
virtual void InsertArg(const Decl *stmt)
LambdaStackType & mLambdaStack
OutputFormatHelper & mOutputFormatHelper
! Find a LambdaExpr inside a Decltype
DeclStmt * mkDeclStmt(Dcls... dcls)
BinaryOperator * Plus(Expr *var, Expr *assignExpr)
CXXReinterpretCastExpr * ReinterpretCast(QualType toType, const Expr *toExpr, bool makePointer)
CXXRecordDecl * Struct(std::string_view name)
FieldDecl * mkFieldDecl(DeclContext *dc, std::string_view name, QualType type)
params_vector to_params_view(params_store ¶ms)
DeclRefExpr * mkDeclRefExpr(const ValueDecl *vd)
QualType Typedef(std::string_view name, QualType underlayingType)
std::vector< std::pair< std::string_view, QualType > > params_vector
CallExpr * Call(const FunctionDecl *fd, ArrayRef< Expr * > params)
UnaryOperator * Ref(const Expr *e)
VarDecl * Variable(std::string_view name, QualType type, DeclContext *dc)
MemberExpr * AccessMember(const Expr *expr, const ValueDecl *vd, bool isArrow)
DeclRefExpr * mkVarDeclRefExpr(std::string_view name, QualType type)
static CallExpr * CallConstructor(QualType ctorType, DeclRefExpr *lhsDeclRef, Expr *lhsMemberExpr, ArrayRef< Expr * > callParams, DoCast doCast, AsReference asReference)
SmallVector< Expr *, 5 > ArgsToExprVector(const Expr *expr)
ArraySubscriptExpr * ArraySubscript(const Expr *lhs, uint64_t index, QualType type)
ReturnStmt * Return(Expr *stmt)
CXXStaticCastExpr * Cast(const Expr *toExpr, QualType toType)
CXXStaticCastExpr * CastToVoidFunPtr(std::string_view name)
Stmt * Comment(std::string_view comment)
ParenExpr * Paren(Expr *expr)
IfStmt * If(const Expr *condition, ArrayRef< Stmt * > bodyStmts)
BinaryOperator * Mul(Expr *lhs, Expr *rhs)
InitListExpr * InitList(ArrayRef< Expr * > initExprs, QualType t)
UnaryExprOrTypeTraitExpr * Sizeof(QualType toType)
QualType GetRecordDeclType(const CXXMethodDecl *md)
std::vector< std::pair< std::string, QualType > > params_store
FunctionDecl * Function(std::string_view name, QualType returnType, const params_vector ¶meters)
CompoundStmt * mkCompoundStmt(ArrayRef< Stmt * > bodyStmts, SourceLocation beginLoc, SourceLocation endLoc)
IntegerLiteral * Int32(uint64_t value)
QualType ContantArrayTy(QualType t, int size)
UnaryOperator * Dref(const Expr *stmt)
QualType Ptr(QualType srcType)
CXXStaticCastExpr * StaticCast(QualType toType, const Expr *toExpr, bool makePointer)
BinaryOperator * Assign(const VarDecl *var, Expr *assignExpr)
static auto * CallVecDelete(Expr *objectParam, QualType allocatedType)
uint64_t GetSize(const ConstantArrayType *arrayType)
@ HeaderStdlib
Track whether we need to insert <stdlib.h> in Cfront mode.
@ HeaderAssert
Track whether we need to insert <assert.h> in Cfront mode.
@ HeaderStddef
Track whether we need to insert <stddef.h> in Cfront mode.
void PushVtableEntry(const CXXRecordDecl *record, const CXXRecordDecl *recordB, VarDecl *decl)
int GetGlobalVtablePos(const CXXRecordDecl *record, const CXXRecordDecl *recordB)
static llvm::DenseMap< std::pair< const CXXRecordDecl *, const CXXRecordDecl * >, int > mThisPointerOffset
Store the this pointer offset from derived to base class.
std::string GetName(const NamedDecl &nd, const QualifiedName qualifiedName)
static void ProcessFields(CXXRecordDecl *recordDecl, const CXXRecordDecl *rd)
void DPrint(const char *fmt, const auto &... args)
Debug print which is disabled in release-mode.
std::string BuildInternalVarName(const std::string_view &varName)
static bool IsCopyOrMoveAssign(const CXXMethodDecl *stmt)
static bool HasDtor(QualType t)
static const CXXRecordDecl * GetFirstPolymorphicBase(const RecordDecl *decl)
! Find the first polymorphic base class.
static bool HasCtor(QualType t)
static void InsertVtblPtr(const CXXMethodDecl *stmt, const CXXRecordDecl *cur, StmtsContainer &bodyStmts)
static auto * CallVecDtor(Expr *objectParam, const ConstantArrayType *ar)
bool IsReferenceType(const ValueDecl *decl)
static auto * CallVecNewOrCtor(std::string_view ctorName, Expr *objectParam, QualType allocatedType, Expr *arraySizeExpr, std::string_view funName)
static std::string GetSpecialMemberName(const ValueDecl *vd, QualType type)
static auto * CallVecCtor(std::string_view ctorName, const VarDecl *objectParam, QualType allocatedType, Expr *arraySizeExpr)
static bool IsCopyOrMoveCtor(const CXXConstructorDecl *ctor)
bool IsStaticStorageClass(const CXXMethodDecl *md)
static std::string GetFirstPolymorphicBaseName(const RecordDecl *decl, const RecordDecl *to)
static auto * CallVecNew(std::string_view ctorName, Expr *objectParam, QualType allocatedType, Expr *arraySizeExpr)
static auto * CallVecDeleteOrDtor(Expr *objectParam, QualType allocatedType, std::string_view name, uint64_t size)
void EnableGlobalInsert(GlobalInserts idx)
static FieldDecl * AddField(CoroutineASTData &astData, std::string_view name, QualType type)
std::string StrCat(const auto &... args)
QualType vtableRecordType
VarDecl * VtblArrayVar(int size)
FieldDecl * VtblPtrField(const CXXRecordDecl *parent)
! A helper type to have a container for ArrayRef
void Add(const Stmt *stmt)
void AddBodyStmts(Stmt *body)
Handy helper to avoid longish comparisons.
constexpr bool any_of(const auto &... ts) const