21 #include "clang/AST/RecordLayout.h"
22 #include "clang/Frontend/CompilerInstance.h"
23 #include "clang/Sema/Sema.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/Support/Path.h"
29 #define LAMBDA_SCOPE_HELPER(type) \
30 LambdaScopeHandler lambdaScopeHandler{mLambdaStack, mOutputFormatHelper, LambdaCallerType::type};
34 #define CONDITIONAL_LAMBDA_SCOPE_HELPER(type, cond) \
35 std::optional<LambdaScopeHandler> lambdaScopeHandler; \
37 lambdaScopeHandler.emplace(mLambdaStack, mOutputFormatHelper, LambdaCallerType::type); \
41 namespace ranges = std::ranges;
45 #define BUILD_OPT_AND(name, param) std::function name = [](param t) -> MyOptional<param>
46 #define BUILD_OPT_AND_O(name, param, ret) std::function name = [](param t) -> MyOptional<ret>
50 if(t->isPointerType()) {
68 if(isa<T>(t.getTypePtrOrNull())) {
77 return t.getType().getCanonicalType();
82 std::string accessStr{getAccessSpelling(access)};
83 if(not accessStr.empty()) {
91 using namespace asthelpers;
93 static std::string_view
GetCastName(
const CastKind castKind,
bool constnessChange =
false)
95 if(
is{castKind}.
any_of(CastKind::CK_BitCast, CastKind::CK_IntegralToPointer, CastKind::CK_PointerToIntegral)) {
99 if((CastKind::CK_NoOp == castKind) and constnessChange) {
100 return "const_cast"sv;
112 }
else if(decl.isUnion()) {
123 const uint64_t mIndex;
133 void InsertArg(
const ArrayInitIndexExpr*)
override { mOutputFormatHelper.Append(mIndex); }
143 std::string mVarName;
148 , mVarName{std::move(varName)}
153 void InsertArg(
const DeclRefExpr* stmt)
override;
154 void InsertArg(
const BindingDecl* stmt)
override;
157 void InsertDecompositionBindings(
const DecompositionDecl& decompositionDeclStmt);
178 InsertCXXMethodDecl(stmt, SkipBody::Yes);
204 std::string_view varName)
205 :
CodeGenerator{outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
217 if(isa<VarDecl>(stmt->getDecl())) {
218 mOutputFormatHelper.Append(
"_"sv, mVarName);
227 std::string_view mVarName;
245 , mHelper{lambdaCallerType, GetBuffer(outputFormatHelper)}
247 mStack.
push(mHelper);
253 if(not mStack.empty()) {
254 mStack.pop()->finish();
264 for(
auto& l : mStack) {
265 switch(l.callerType()) {
277 return outputFormatHelper;
283 return isArrow ?
"->"sv :
"."sv;
311 if(not stmt->isImplicitAccess()) {
325 auto& langOpts{
GetLangOpts(*rangeForStmt->getLoopVariable())};
326 const bool onlyCpp11{not langOpts.CPlusPlus17};
328 auto* rwStmt =
const_cast<CXXForRangeStmt*
>(rangeForStmt);
330 StmtsContainer outerScopeStmts{};
333 outerScopeStmts.Add(rangeForStmt->getInit());
336 outerScopeStmts.Add(rangeForStmt->getRangeStmt());
339 outerScopeStmts.Add(rangeForStmt->getBeginStmt());
340 outerScopeStmts.Add(rangeForStmt->getEndStmt());
344 StmtsContainer bodyStmts{};
345 bodyStmts.Add(rangeForStmt->getLoopVarStmt());
348 bodyStmts.AddBodyStmts(rwStmt->getBody());
350 const auto& ctx = rangeForStmt->getLoopVariable()->getASTContext();
354 auto* declStmt = [&]() -> DeclStmt* {
356 return mkDeclStmt(rwStmt->getBeginStmt() ? rwStmt->getBeginStmt()->getSingleDecl() :
nullptr,
357 rwStmt->getEndStmt() ? rwStmt->getEndStmt()->getSingleDecl() :
nullptr);
363 auto* innerScope =
mkCompoundStmt(bodyStmts, rangeForStmt->getBeginLoc(), rangeForStmt->getEndLoc());
365 auto* forStmt =
new(ctx) ForStmt(ctx,
368 rwStmt->getLoopVariable(),
371 rangeForStmt->getBeginLoc(),
372 rangeForStmt->getEndLoc(),
373 rangeForStmt->getEndLoc());
375 outerScopeStmts.Add(forStmt);
377 auto* outerScope =
mkCompoundStmt(outerScopeStmts, rangeForStmt->getBeginLoc(), rangeForStmt->getEndLoc());
386 const NestedNameSpecifier* qualifier,
387 const bool hasTemplateKeyword)
391 declName.getAsString());
415 const auto* templatedDecl = stmt->getTemplatedDecl();
435 for(
OnceTrue first{};
const auto* spec : stmt->specializations()) {
436 if(TSK_ExplicitSpecialization == spec->getSpecializationKind()) {
526 if(stmt->getSubStmt()) {
534 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
558 auto* rwStmt =
const_cast<WhileStmt*
>(stmt);
559 auto* conditionVar{rwStmt->getConditionVariable()};
575 if(not conditionVar) {
579 StmtsContainer bodyStmts{};
581 bodyStmts.AddBodyStmts(rwStmt->getBody());
582 bodyStmts.AddBodyStmts(
Assign(conditionVar, conditionVar->getInit()));
598 const CXXRecordDecl& cxxRecordDecl)
600 if(cxxRecordDecl.isLambda()) {
601 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
603 FieldDecl* thisCapture{};
605 cxxRecordDecl.getCaptureFields(captures, thisCapture);
607 if(&fieldDecl == thisCapture) {
610 for(
const auto& [key, value] : captures) {
611 if(&fieldDecl == value) {
630 const auto* base = stmt->getBase();
631 const bool skipBase{[&] {
632 if(
const auto* implicitCast = dyn_cast_or_null<ImplicitCastExpr>(base)) {
633 if(CastKind::CK_UncheckedDerivedToBase == implicitCast->getCastKind()) {
635 return isa<CXXThisExpr>(implicitCast->IgnoreImpCasts());
648 const auto* meDecl = stmt->getMemberDecl();
649 bool skipTemplateArgs{
false};
650 const auto name = [&]() -> std::string {
653 if(
const auto* m = dyn_cast_or_null<CXXMethodDecl>(meDecl)) {
654 if(
const auto* rd = m->getParent(); rd and rd->isLambda() and isa<CXXConversionDecl>(m)) {
655 skipTemplateArgs =
true;
662 else if(
const auto* fd = dyn_cast_or_null<FieldDecl>(meDecl)) {
663 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(fd->getParent())) {
665 return fieldName.value();
673 if(
const auto* convDecl = dyn_cast_or_null<CXXConversionDecl>(meDecl)) {
677 return stmt->getMemberNameInfo().getName().getAsString();
690 if(
const auto cxxMethod = dyn_cast_or_null<CXXMethodDecl>(meDecl)) {
691 if(
const auto* tmplArgs = cxxMethod->getTemplateSpecializationArgs()) {
692 OutputFormatHelper ofm{};
697 for(
OnceFalse needsComma{};
const auto& arg : tmplArgs->asArray()) {
698 if(arg.getKind() == TemplateArgument::Integral) {
699 ofm.AppendComma(needsComma);
701 ofm.Append(arg.getAsIntegral());
712 }
else if(not isa<CXXConversionDecl>(meDecl)) {
725 if(not stmt->isArgumentType()) {
726 const auto* argExpr = stmt->getArgumentExpr();
727 const bool needsParens{not isa<ParenExpr>(argExpr)};
739 const auto& type = stmt->getType();
740 const bool isSigned = type->isSignedIntegerType();
759 if(stmt->isTypeOperand()) {
760 mOutputFormatHelper.Append(GetName(stmt->getTypeOperand(const_cast<ASTContext&>(GetGlobalAST()))));
762 InsertArg(stmt->getExprOperand());
772 BackupAndRestore _{
mLastExpr, stmt->getLHS()};
774 const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
779 const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
788 const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
794 const bool needCast{stmt->getLHS()->getType() != stmt->getComputationLHSType()};
800 clang::ExprResult res = stmt->getLHS();
804 if(
const auto resultingType =
GetGlobalCI().getSema().PrepareScalarCast(res, stmt->getComputationLHSType());
805 resultingType != CK_NoOp) {
806 const QualType castDestType = stmt->getComputationLHSType();
807 FormatCast(kwStaticCast, castDestType, stmt->getLHS(), resultingType);
809 InsertArg(stmt->getLHS());
814 " "sv, BinaryOperator::getOpcodeStr(BinaryOperator::getOpForCompoundAssignment(stmt->getOpcode())),
" "sv);
816 const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
836 return VarDecl::getStorageClassSpecifierString(sc);
847 if(not ret.empty()) {
857 std::string qualifiers{};
859 if(vd.isInline() or vd.isInlineSpecified()) {
865 if(vd.isConstexpr()) {
875 std::string name{std::move(defaultName)};
877 if(
const auto* tvd = dyn_cast_or_null<VarTemplateSpecializationDecl>(decl)) {
881 codeGenerator->InsertTemplateArgs(tvd->getTemplateArgs());
883 name += outputFormatHelper;
900 if(isa<DecompositionDecl>(expr->getDecl())) {
907 for(
const auto* child : stmt->children()) {
932 bool mHaveTemporary{};
934 std::string mTempName{};
935 std::vector<VarDecl*> mDecls{};
939 : codeGenerator{_codeGenerator}
940 , mPrevStmt{const_cast<
Stmt*>(stmt)}
946 for(
auto d : mDecls) {
952 if(
auto* expr = dyn_cast_or_null<CXXConstructExpr>(stmt)) {
957 auto* vd =
Variable(mTempName, expr->getType(), dummy->getDeclContext());
958 dummy->getDeclContext()->addDecl(vd);
959 vd->setInit(
const_cast<CXXConstructExpr*
>(expr));
960 vd->setStorageClass(SC_None);
964 auto* vd = ImplicitParamDecl::Create(
const_cast<ASTContext&
>(ctx),
965 ctx.getTranslationUnitDecl(),
967 &ctx.Idents.get(mTempName),
969 ImplicitParamKind::Other);
976 }
else if(
auto* expr = dyn_cast_or_null<InitListExpr>(stmt)) {
978 auto* vd =
Variable(mTempName, expr->getType());
979 vd->setInit(
const_cast<InitListExpr*
>(expr));
992 bool Found()
const {
return mFound; }
994 std::string
Name()
const {
return mTempName; }
1001 auto* vd =
Variable(mTempName, expr->getType());
1007 auto* ctorConstructExpr = CXXConstructExpr::Create(
GetGlobalAST(),
1009 expr->getBeginLoc(),
1010 expr->getConstructor(),
1012 {expr->getArgs(), expr->getNumArgs()},
1013 expr->hadMultipleCandidates(),
1014 expr->isListInitialization(),
1015 expr->isStdInitListInitialization(),
1016 expr->requiresZeroInitialization(),
1017 expr->getConstructionKind(),
1018 expr->getParenOrBraceRange());
1020 vd->setInit(ctorConstructExpr);
1026 mDecls.push_back(vd);
1030 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr* stmt)
1034 const auto name =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"temp"sv);
1037 auto* vd =
Variable(name, stmt->getType());
1051 vd->setInit(stmt->getSubExpr());
1056 if(SD_FullExpression == stmt->getStorageDuration() and not mHaveTemporary) {
1058 mHaveTemporary =
true;
1059 }
else if(
const auto* extending = stmt->getExtendingDecl()) {
1063 mDecls.push_back(vd);
1068 auto* tmp = mPrevStmt;
1071 for(
auto* child : stmt->children()) {
1087 static SmallVector<std::pair<std::pair<const CXXRecordDecl*, const CXXRecordDecl*>, VarDecl*>, 10>
1095 auto iter = std::ranges::find_if(
1096 gVtables, [&](
const auto& e) {
return (e.first.first == record) and (e.first.second == recordB); });
1099 iter = std::ranges::find_if(
gVtables, [&](
const auto& e) {
return e.first.first == record; });
1102 return std::distance(
gVtables.begin(), iter);
1106 void PushVtableEntry(
const CXXRecordDecl* record,
const CXXRecordDecl* recordB, VarDecl* decl)
1108 gVtables.push_back({{record, recordB}, decl});
1137 ofm.AppendNewLine();
1141 SmallVector<Expr*, 16> mInitExprs{};
1148 ofm.AppendNewLine();
1152 vtable->setInit(
InitList(mInitExprs, vtable->getType()));
1154 cg->InsertArg(vtable);
1156 ofm.AppendNewLine();
1159 cg->InsertArg(cxaStartFun);
1170 ofm.AppendNewLine();
1171 cg->InsertArg(cxaAtExitFun);
1173 return ofm.GetString();
1198 return stmt and stmt->getNumExprs() and isa_and_nonnull<PackExpansionExpr>(stmt->getExpr(0)) and
1199 stmt->getType().isNull();
1208 for(
const auto* decl : stmt->decls()) {
1220 pp.adjustForCPlusPlus();
1224 ::llvm::raw_string_ostream stream{init};
1225 param.printAsInit(stream, pp);
1233 "static constexpr ",
GetName(param.getType().getUnqualifiedType()),
" ", varName, init);
1241 for(
const auto& arg : array) {
1242 if(TemplateArgument::Declaration != arg.getKind()) {
1244 }
else if(
const auto decl = dyn_cast_or_null<TemplateParamObjectDecl>(arg.getAsDecl())) {
1253 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(&decl)) {
1254 if(
const auto* specArgs = fd->getTemplateSpecializationArgs()) {
1257 }
else if(
const auto* vd = dyn_cast_or_null<VarTemplateSpecializationDecl>(&decl)) {
1259 }
else if(
const auto* clsTemplateSpe = dyn_cast_or_null<ClassTemplateSpecializationDecl>(&decl)) {
1269 if(
auto* init = stmt->getInit();
1271 (not(isa<CallExpr>(init) or
1272 (isa<ExprWithCleanups>(init) and
1273 (isa<CallExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr()) or
1274 isa<MaterializeTemporaryExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr())))))) {
1282 if(BindingDeclFinder isBindingDecl{}; isBindingDecl.Find(stmt->getInit())) {
1289 TemporaryDeclFinder temporaryFinder{*
this, stmt->getInit()};
1297 const bool needsGuard = stmt->isOutOfLine() and isTemplateInstantiation(stmt->getTemplateSpecializationKind());
1301 if(stmt->isOutOfLine()) {
1302 if(
const auto* recordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
1303 if(
const auto* classTmpl = recordDecl->getDescribedClassTemplate()) {
1309 if(isa<VarTemplateSpecializationDecl>(stmt)) {
1311 }
else if(needsGuard) {
1325 const bool isMemberPointer{isa<MemberPointerType>(desugaredType.getTypePtrOrNull())};
1326 if(desugaredType->isFunctionPointerType() or isMemberPointer) {
1327 const auto lineNo =
GetSM(*stmt).getSpellingLineNumber(stmt->getSourceRange().getBegin());
1329 const auto funcPtrName{
StrCat(ptrPrefix, lineNo)};
1337 const auto scope = [&] {
1338 if(
const auto* ctx = stmt->getDeclContext(); stmt->getLexicalDeclContext() != ctx) {
1339 OutputFormatHelper scopeOfm{};
1340 scopeOfm.Append(
GetDeclContext(ctx, WithTemplateParameters::Yes));
1345 return std::string{};
1354 const std::string_view pointer = [&]() {
1359 if(stmt->getType()->isAnyPointerType()) {
1368 if(
const auto* init = stmt->getInit()) {
1369 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init);
1384 if(stmt->hasGlobalStorage()) {
1387 stmt->getType(), stmt,
ArgsToExprVector(ctorExpr), DoCast::No, AsReference::Yes);
1403 if(MyOptional<const InitListExpr*> initList{dyn_cast_or_null<InitListExpr>(init)};
1405 initList.and_then(CanonicalType).and_then(Isa<RecordType>).and_not(IsPointer).and_then(IsPOD) and
1406 not isa<ArrayType>(stmt->getType())) {
1411 if(stmt->hasGlobalStorage()) {
1420 initList.and_then(CanonicalType)
1421 .and_then(Isa<RecordType>)
1424 (0 == initList.value()->getNumInits()))) {
1428 if(not(ctorExpr and ctorExpr->getConstructor()->isDefaultConstructor() and
1429 ctorExpr->getConstructor()->getParent()->hasTrivialDefaultConstructor())) {
1431 const bool isPrimaryTemplatePackExpansionExpr{
1434 if(not isa<CXXParenListInitExpr>(init) and not isPrimaryTemplatePackExpansionExpr) {
1440 stmt->getType()->isRValueReferenceType()) {
1442 if(GetInsightsOptions().UseShow2C) {
1443 mOutputFormatHelper.Append(
"&");
1457 if(stmt->isNRVOVariable()) {
1466 if(
const auto* decompDecl = dyn_cast_or_null<DecompositionDecl>(stmt)) {
1469 codeGenerator.InsertDecompositionBindings(*decompDecl);
1481 if(not(cxxMethodDecl and cxxMethodDecl->isLambdaStaticInvoker())) {
1494 if(not cxxMethodDecl->getReturnType()->isVoidType()) {
1500 if(cxxMethodDecl->isFunctionTemplateSpecialization()) {
1504 if(cxxMethodDecl->isTemplated()) {
1505 if(cxxMethodDecl->getDescribedTemplate()) {
1507 TemplateParamsOnly::Yes);
1516 OutputFormatHelper::NameOnly::Yes,
1517 OutputFormatHelper::GenMissingParamName::Yes);
1532 const SourceLocation& instLoc,
1533 std::string_view text)
1535 const auto lineNo = sm.getSpellingLineNumber(instLoc);
1536 const auto& fileId = sm.getFileID(instLoc);
1537 if(
const auto file = sm.getFileEntryRefForID(fileId)) {
1538 const auto fileWithDirName = file->getName();
1539 const auto fileName = llvm::sys::path::filename(fileWithDirName);
1542 text =
"First instantiated from: "sv;
1552 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1561 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1584 if(isa<CoyieldExpr>(stmt)) {
1591 if(
const auto* matTemp = dyn_cast_or_null<MaterializeTemporaryExpr>(stmt->getCommonExpr())) {
1592 const auto* temporary = matTemp->getSubExpr();
1594 if(
const auto* memExpr = dyn_cast_or_null<CXXMemberCallExpr>(temporary)) {
1595 ForEachArg(memExpr->arguments(), [&](
const auto& arg) { InsertArg(arg); });
1601 }
else if(
const auto* unaryexpr = dyn_cast_or_null<UnaryOperator>(stmt->getOperand())) {
1602 if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(unaryexpr->getSubExpr())) {
1618 auto IsPrimaryTemplate = [&] {
1620 if(
const auto* cxxMethod = dyn_cast_or_null<CXXMethodDecl>(stmt)) {
1621 if(
const auto* tmpl = cxxMethod->getParent()->getDescribedClassTemplate();
1622 tmpl and not isa<ClassTemplateSpecializationDecl>(cxxMethod->getParent())) {
1627 return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind()) or
1631 if(stmt->doesThisDeclarationHaveABody()) {
1636 if(
const auto* corBody = dyn_cast_or_null<CoroutineBodyStmt>(stmt->getBody());
1637 (
nullptr != corBody) and not IsPrimaryTemplate() and
GetInsightsOptions().ShowCoroutineTransformation) {
1640 codeGenerator.InsertCoroutine(*stmt, corBody);
1642 const auto exSpec = stmt->getExceptionSpecType();
1643 const bool showNoexcept =
1647 if(stmt->hasImplicitReturnZero()) {
1649 [](
const Stmt* e) { return isa<ReturnStmt>(e); });
1652 const auto* body = stmt->getBody();
1661 for(
const auto* param : stmt->parameters()) {
1662 auto paramType = param->getType();
1663 const bool isPassByValue{not paramType->isPointerType() and not paramType->isReferenceType()};
1664 if(
const auto* rd = paramType->getAsRecordDecl(); rd and isPassByValue) {
1688 dt.TraverseType(stmt->getReturnType());
1691 for(
const auto& param : stmt->parameters()) {
1692 P0315Visitor dt{*
this};
1693 dt.TraverseType(param->getType());
1697 if(
const auto* deductionGuide = dyn_cast_or_null<CXXDeductionGuideDecl>(stmt)) {
1699 }
else if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
1704 RETURN_IF(isa<CXXConversionDecl>(stmt) and not stmt->hasBody());
1722 if(typeConstraint) {
1724 sstream.
Print(*typeConstraint);
1726 return sstream.str();
1750 expr = expr->IgnoreParenImpCasts();
1753 if(Expr::EvalResult evalResult{};
1754 isa<CXXFunctionalCastExpr>(expr) and
1755 expr->EvaluateAsConstantExpr(evalResult,
GetGlobalAST(), ConstantExprKind::Normal)) {
1756 return std::pair<QualType, APValue>{expr->getType(), evalResult.Val};
1764 const TemplateParamsOnly templateParamsOnly)
1766 const bool full{TemplateParamsOnly::No == templateParamsOnly};
1769 for(
const auto* param : list) {
1770 if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param);
1771 nonTmplParam and nonTmplParam->hasDefaultArgument()) {
1774 auto* init =
GetGlobalAST().getTemplateParamObjectDecl(val->first, val->second);
1786 for(
OnceFalse needsComma{};
const auto* param : list) {
1789 const auto& typeName =
GetName(*param);
1791 if(
const auto* tt = dyn_cast_or_null<TemplateTypeParmDecl>(param)) {
1793 if(tt->wasDeclaredWithTypename()) {
1795 }
else if(not tt->hasTypeConstraint()) {
1802 if(0 == typeName.size() or tt->isImplicit() ) {
1807 not typeConstraint.empty()) {
1816 if(tt->hasDefaultArgument() and not tt->defaultArgumentWasInherited()) {
1817 const auto& defaultArg = tt->getDefaultArgument();
1819 if(
const auto decltypeType = dyn_cast_or_null<DecltypeType>(defaultArg.getArgument().getAsType())) {
1822 InsertArg(decltypeType->getUnderlyingExpr());
1830 }
else if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param)) {
1832 if(
const auto nttpType = nonTmplParam->getType();
1833 nttpType->isFunctionPointerType() or nttpType->isMemberFunctionPointerType()) {
1838 GetName(nttpType),
" "sv,
Ellipsis(nonTmplParam->isParameterPack()), typeName);
1841 if(nonTmplParam->hasDefaultArgument()) {
1848 }
else if(
const auto* tmplTmplParam = dyn_cast_or_null<TemplateTemplateParmDecl>(param)) {
1853 if(tmplTmplParam->hasDefaultArgument()) {
1880 SmallVector<const ClassTemplateSpecializationDecl*, 10> specializations{};
1883 for(
const auto* spec : stmt->specializations()) {
1886 if(TSK_ImplicitInstantiation == spec->getSpecializationKind()) {
1887 specializations.push_back(spec);
1892 ranges::sort(specializations,
1893 [](
const ClassTemplateSpecializationDecl* a,
const ClassTemplateSpecializationDecl* b) {
1894 return a->getPointOfInstantiation() < b->getPointOfInstantiation();
1897 for(
const auto* spec : specializations) {
1905 for(
OnceFalse needsComma{};
const auto& expr : stmt->children()) {
1925 OnceFalse needsComma{uint64_t{0} != startAt};
1926 for_each(startAt, size, [&](
auto) {
1927 ret.AppendComma(needsComma);
1932 return ret.GetString();
1943 ((stmt->getNumInits() > 1) or stmt->getArrayFiller() or
1944 ((0 < stmt->getNumInits()) and isa<ImplicitValueInitExpr>(stmt->getInit(0))))),
1946 mOutputFormatHelper.IncreaseIndent();
1948 ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); });
1951 if(stmt->getType().getCanonicalType()->isScalarType()) {
1962 if(
const auto* filler = stmt->getArrayFiller()) {
1963 OutputFormatHelper ofm{};
1968 dyn_cast_or_null<ConstantArrayType>(stmt->getType().getTypePtrOrNull()),
1970 stmt->getNumInits());
1976 mOutputFormatHelper.DecreaseIndent();
1980 void CodeGenerator::InsertArg(
const CXXDefaultInitExpr* stmt)
1982 const auto* subExpr = stmt->getExpr();
1984 InsertCurlysIfRequired(subExpr);
1988 void CodeGenerator::InsertArg(
const CXXDeleteExpr* stmt)
1990 mOutputFormatHelper.Append(
kwDelete);
1992 if(stmt->isArrayForm()) {
1993 mOutputFormatHelper.Append(
"[]"sv);
1996 mOutputFormatHelper.Append(
' ');
1998 InsertArg(stmt->getArgument());
2002 void CodeGenerator::InsertConstructorExpr(
const auto* stmt)
2008 dt.TraverseType(stmt->getType());
2010 if(not mLambdaStack.empty()) {
2011 for(
const auto& e : mLambdaStack) {
2012 RETURN_IF((LambdaCallerType::MemberCallExpr == e.callerType()) and isa<DecltypeType>(stmt->getType()));
2017 mOutputFormatHelper.Append(
GetName(stmt->getType(), Unqualified::Yes));
2019 const BraceKind braceKind =
ValueOr(stmt->isListInitialization(), BraceKind::Curlys, BraceKind::Parens);
2021 WrapInParensOrCurlys(braceKind, [&]() {
2022 if(
const auto& arguments = stmt->arguments(); not arguments.empty()) {
2023 ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); });
2029 void CodeGenerator::InsertArg(
const CXXConstructExpr* stmt)
2031 InsertConstructorExpr(stmt);
2035 void CodeGenerator::InsertArg(
const CXXUnresolvedConstructExpr* stmt)
2037 BackupAndRestore _{mNoEmptyInitList, NoEmptyInitList::Yes};
2039 InsertConstructorExpr(stmt);
2043 void CodeGenerator::InsertArg(
const UnresolvedMemberExpr* stmt)
2049 mOutputFormatHelper.Append(stmt->getMemberNameInfo().getAsString());
2051 if(stmt->getNumTemplateArgs()) {
2052 InsertTemplateArgs(*stmt);
2057 void CodeGenerator::InsertArg(
const PackExpansionExpr* stmt)
2059 InsertArg(stmt->getPattern());
2064 void CodeGenerator::InsertArg(
const CXXFoldExpr* stmt)
2066 auto operatorStr = BinaryOperator::getOpcodeStr(stmt->getOperator());
2070 const auto* init = stmt->getInit();
2072 if(stmt->isLeftFold()) {
2075 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2081 InsertArg(stmt->getPattern());
2083 if(stmt->isRightFold()) {
2084 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv,
kwElipsis);
2087 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2095 void CodeGenerator::InsertArg(
const CXXInheritedCtorInitExpr* stmt)
2097 const auto& constructorDecl = *stmt->getConstructor();
2100 WrapInParens([&]() {
2101 mOutputFormatHelper.AppendParameterList(constructorDecl.parameters(),
2102 OutputFormatHelper::NameOnly::Yes,
2103 OutputFormatHelper::GenMissingParamName::Yes);
2108 bool CodeGenerator::InsideDecltype()
const
2110 return (not mLambdaStack.empty()) and (LambdaCallerType::Decltype == mLambdaStack.back().callerType());
2114 void CodeGenerator::InsertArg(
const CXXPseudoDestructorExpr* stmt)
2116 InsertArg(stmt->getBase());
2118 mOutputFormatHelper.Append(
ArrowOrDot(stmt->isArrow()),
"~",
GetName(stmt->getDestroyedType()));
2122 void CodeGenerator::InsertArg(
const CXXMemberCallExpr* stmt)
2126 InsertArg(stmt->getCallee());
2128 WrapInParens([&]() { ForEachArg(stmt->arguments(), [&](
const auto& arg) { InsertArg(arg); }); });
2132 void CodeGenerator::InsertArg(
const ParenExpr* stmt)
2134 WrapInParens([&]() { InsertArg(stmt->getSubExpr()); });
2138 void CodeGenerator::InsertArg(
const CXXParenListInitExpr* stmt)
2140 WrapInParens([&]() { ForEachArg(stmt->getInitExprs(), [&](
const auto& init) { InsertArg(init); }); });
2144 void CodeGenerator::InsertArg(
const UnaryOperator* stmt)
2146 StringRef opCodeName = UnaryOperator::getOpcodeStr(stmt->getOpcode());
2147 const bool insertBefore{not stmt->isPostfix()};
2150 mOutputFormatHelper.Append(opCodeName);
2153 InsertArg(stmt->getSubExpr());
2155 if(not insertBefore) {
2156 mOutputFormatHelper.Append(opCodeName);
2161 void CodeGenerator::InsertArg(
const StringLiteral* stmt)
2163 StringStream stream{};
2164 stream.Print(*stmt);
2166 mOutputFormatHelper.Append(stream.str());
2170 void CodeGenerator::InsertArg(
const ArrayInitIndexExpr* stmt)
2172 Error(stmt,
"ArrayInitIndexExpr should not be reached in CodeGenerator");
2176 void CodeGenerator::InsertArg(
const ArraySubscriptExpr* stmt)
2178 if((not
GetInsightsOptions().UseAltArraySubscriptionSyntax) or stmt->getLHS()->isLValue()) {
2179 InsertArg(stmt->getLHS());
2181 mOutputFormatHelper.Append(
'[');
2182 InsertArg(stmt->getRHS());
2183 mOutputFormatHelper.Append(
']');
2186 mOutputFormatHelper.Append(
"(*("sv);
2187 InsertArg(stmt->getLHS());
2188 mOutputFormatHelper.Append(
" + "sv);
2190 InsertArg(stmt->getRHS());
2191 mOutputFormatHelper.Append(
"))"sv);
2196 void CodeGenerator::InsertArg(
const ArrayInitLoopExpr* stmt)
2198 WrapInCurlys([&]() {
2199 const uint64_t size = stmt->getArraySize().getZExtValue();
2202 ArrayInitCodeGenerator codeGenerator{mOutputFormatHelper, i};
2203 codeGenerator.
InsertArg(stmt->getSubExpr());
2209 void CodeGenerator::InsertArg(
const OpaqueValueExpr* stmt)
2211 InsertArg(stmt->getSourceExpr());
2215 void CodeGenerator::InsertArg(
const CallExpr* stmt)
2217 const bool insideDecltype{InsideDecltype()};
2220 if(insideDecltype) {
2221 mLambdaStack.back().setInsertName(
true);
2224 UpdateCurrentPos(mCurrentCallExprPos);
2226 InsertArg(stmt->getCallee());
2228 if(
const auto* declRefExpr = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts())) {
2229 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(declRefExpr->getDecl())) {
2230 if((not declRefExpr->getNumTemplateArgs() and
GetInsightsOptions().ShowAllCallExprTemplateParameters) or
2231 isa<UserDefinedLiteral>(stmt)) {
2232 InsertTemplateArgs(*fd);
2237 WrapInParens([&]() {
2238 auto* funcDecl = dyn_cast_or_null<FunctionDecl>(stmt->getCalleeDecl());
2241 ForEachArg(stmt->arguments(), [&](
const auto* arg) {
2244 if(const auto* tmpExpr = dyn_cast_or_null<CXXBindTemporaryExpr>(arg)) {
2245 if(const auto* tmp = dyn_cast_or_null<CXXTemporaryObjectExpr>(tmpExpr->getSubExpr())) {
2246 if(GetInsightsOptions().UseShow2C) {
2251 } else if(GetInsightsOptions().ShowLifetime) {
2252 mOutputFormatHelper.Append(GetName(*tmp));
2258 if(
GetInsightsOptions().UseShow2C and funcDecl and (funcDecl->getNumParams() >= parmIdx) and
2260 if(auto* unop = dyn_cast_or_null<UnaryOperator>(arg); not unop or (unop->getOpcode() != UO_AddrOf)) {
2269 if(insideDecltype) {
2270 mLambdaStack.back().setInsertName(
false);
2273 mCurrentCallExprPos.reset();
2277 void CodeGenerator::InsertArg(
const CXXNamedCastExpr* stmt)
2279 const QualType castDestType = stmt->getTypeAsWritten();
2280 const Expr* subExpr = stmt->getSubExpr();
2282 FormatCast(stmt->getCastName(), castDestType, subExpr, stmt->getCastKind());
2286 void CodeGenerator::InsertArg(
const ImplicitCastExpr* stmt)
2288 const Expr* subExpr = stmt->getSubExpr();
2289 const auto castKind = stmt->getCastKind();
2292 auto isMatchingCast = [](
const CastKind kind,
const bool hideImplicitCasts,
const bool showXValueCasts) {
2294 case CastKind::CK_Dependent: [[fallthrough]];
2295 case CastKind::CK_IntegralCast: [[fallthrough]];
2296 case CastKind::CK_IntegralToBoolean: [[fallthrough]];
2297 case CastKind::CK_IntegralToPointer: [[fallthrough]];
2298 case CastKind::CK_PointerToIntegral: [[fallthrough]];
2299 case CastKind::CK_BitCast: [[fallthrough]];
2300 case CastKind::CK_UncheckedDerivedToBase: [[fallthrough]];
2301 case CastKind::CK_ToUnion:
2304 case CastKind::CK_AtomicToNonAtomic: [[fallthrough]];
2305 case CastKind::CK_DerivedToBase: [[fallthrough]];
2306 case CastKind::CK_FloatingCast: [[fallthrough]];
2307 case CastKind::CK_IntegralToFloating: [[fallthrough]];
2308 case CastKind::CK_FloatingToIntegral: [[fallthrough]];
2309 case CastKind::CK_NonAtomicToAtomic:
return true;
2312 if((showXValueCasts or not hideImplicitCasts) and (CastKind::CK_NoOp == kind)) {
2317 if(not hideImplicitCasts) {
2319 case CastKind::CK_NullToPointer: [[fallthrough]];
2320 case CastKind::CK_NullToMemberPointer: [[fallthrough]];
2323 case CastKind::CK_NoOp: [[fallthrough]];
2324 case CastKind::CK_ArrayToPointerDecay:
return true;
2333 if(not isMatchingCast(castKind, hideImplicitCasts, stmt->isXValue() or ShowXValueCasts())) {
2336 mOutputFormatHelper.Append(
"*"sv);
2341 }
else if(isa<IntegerLiteral>(subExpr) and hideImplicitCasts) {
2342 InsertArg(stmt->IgnoreCasts());
2346 }
else if(stmt->isPartOfExplicitCast()) {
2347 InsertArg(stmt->IgnoreCasts());
2351 const QualType castDestType{[&] {
2352 const auto type{stmt->getType()};
2356 if(VK_XValue == stmt->getValueKind()) {
2357 return GetGlobalAST().getRValueReferenceType(type.getCanonicalType());
2358 }
else if(type->isDependentType()) {
2363 return type.getCanonicalType();
2366 FormatCast(castName, castDestType, subExpr, castKind);
2371 void CodeGenerator::InsertArg(
const DeclRefExpr* stmt)
2373 if(
const auto* tmplObjParam = dyn_cast_or_null<TemplateParamObjectDecl>(stmt->getDecl())) {
2374 mOutputFormatHelper.Append(
GetName(*tmplObjParam));
2376 }
else if(
const auto* vd = dyn_cast_or_null<VarDecl>(stmt->getDecl());
2378 const auto* init = vd->getInit();
2380 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(init)) {
2381 mOutputFormatHelper.Append(
GetName(*dref));
2384 }
else if(
const auto* inList = dyn_cast_or_null<InitListExpr>(init)) {
2385 mOutputFormatHelper.Append(
GetName(*dyn_cast_or_null<DeclRefExpr>(inList->getInit(0))));
2390 if(
const auto* ctx = stmt->getDecl()->getDeclContext(); not ctx->isFunctionOrMethod() and
2391 not isa<NonTypeTemplateParmDecl>(stmt->getDecl()) and
2393 if(
const auto* qualifier = stmt->getQualifier();
2394 qualifier and (qualifier->getKind() == NestedNameSpecifier::SpecifierKind::Global)) {
2398 mOutputFormatHelper.Append(
"::"sv,
GetPlainName(*stmt));
2401 OutputFormatHelper ofm{};
2402 CodeGeneratorVariant codeGenerator{ofm};
2406 mOutputFormatHelper.Append(ScopeHandler::RemoveCurrentScope(ofm.GetString()),
GetPlainName(*stmt));
2410 mOutputFormatHelper.Append(
GetName(*stmt));
2413 if(
const auto* varTmplSpecDecl = dyn_cast_or_null<VarTemplateSpecializationDecl>(stmt->getDecl())) {
2414 InsertTemplateArgs(*varTmplSpecDecl);
2416 InsertTemplateArgs(*stmt);
2421 void CodeGenerator::InsertArg(
const CompoundStmt* stmt)
2423 mOutputFormatHelper.OpenScope();
2424 mLifeTimeTracker.StartScope(isa_and_nonnull<FunctionDecl>(mLastDecl));
2428 const bool requiresImplicitReturnZero{std::exchange(mRequiresImplicitReturnZero,
false)};
2430 HandleCompoundStmt(stmt);
2432 if(requiresImplicitReturnZero) {
2440 mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper, isa_and_nonnull<ReturnStmt>(mLastStmt));
2442 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
2446 template<
typename... Args>
2449 return (... and not isa<Args>(stmt));
2453 void CodeGenerator::HandleCompoundStmt(
const CompoundStmt* stmt)
2455 for(
const auto* item : stmt->body()) {
2460 const bool skipSemiForLambda{mLambdaStack.empty() and isa<LambdaExpr>(item)};
2472 InsertSemi() and not skipSemiForLambda and not mSkipSemi) {
2473 mOutputFormatHelper.AppendSemiNewLine();
2481 void CodeGenerator::InsertIfOrSwitchInitVariables(same_as_any_of<const IfStmt, const SwitchStmt>
auto* stmt)
2483 if(
const auto* conditionVar = stmt->getConditionVariable()) {
2484 InsertArg(conditionVar);
2487 if(
const auto* init = stmt->getInit()) {
2490 if(not isa<DeclStmt>(init)) {
2491 mOutputFormatHelper.AppendSemiNewLine();
2497 void CodeGenerator::InsertArg(
const IfStmt* stmt)
2499 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
2502 mOutputFormatHelper.OpenScope();
2504 InsertIfOrSwitchInitVariables(stmt);
2509 WrapInParensIfNeeded(
2510 not stmt->isConsteval(),
2512 mShowConstantExprValue = ShowConstantExprValue::Yes;
2514 InsertArg(stmt->getCond());
2516 mShowConstantExprValue = ShowConstantExprValue::No;
2518 AddSpaceAtTheEnd::Yes);
2520 mOutputFormatHelper.Append(
ValueOrDefault(stmt->isNegatedConsteval(),
" !"sv),
2523 WrapInCompoundIfNeeded(stmt->getThen(), AddNewLineAfter::No);
2526 if(
const auto* elsePart = stmt->getElse()) {
2527 mOutputFormatHelper.Append(
2531 WrapInCompoundIfNeeded(elsePart, AddNewLineAfter::No);
2535 mOutputFormatHelper.AppendNewLine();
2538 mOutputFormatHelper.CloseScope();
2539 mOutputFormatHelper.AppendNewLine();
2543 mOutputFormatHelper.AppendNewLine();
2550 std::string_view mContinueLabel{};
2557 , mContinueLabel{continueLabel}
2578 auto* tmp = mPrevStmt;
2581 for(
auto* child : stmt->children()) {
2590 void CodeGenerator::InsertArg(
const ForStmt* stmt)
2597 auto* rwStmt =
const_cast<ForStmt*
>(stmt);
2599 StmtsContainer bodyStmts{};
2601 auto continueLabel =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"__continue_"sv);
2602 const bool insertLabel = ContinueASTTransformer{rwStmt->getBody(), continueLabel}.found;
2604 bodyStmts.AddBodyStmts(rwStmt->getBody());
2608 bodyStmts.Add(
Label(continueLabel));
2611 bodyStmts.Add(rwStmt->getInc());
2613 auto* condition = [&]() -> Expr* {
2614 if(rwStmt->getCond()) {
2615 return rwStmt->getCond();
2621 auto* outerBody =
mkCompoundStmt(bodyStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2622 auto* whileStmt = WhileStmt::Create(
2623 ctx,
nullptr, condition, outerBody, stmt->getBeginLoc(), stmt->getLParenLoc(), stmt->getRParenLoc());
2625 StmtsContainer outerScopeStmts{};
2626 outerScopeStmts.Add(rwStmt->getInit());
2627 outerScopeStmts.Add(whileStmt);
2629 auto* outerScopeBody =
mkCompoundStmt(outerScopeStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2631 InsertArg(outerScopeBody);
2632 mOutputFormatHelper.AppendNewLine();
2639 mOutputFormatHelper.Append(
"for"sv);
2643 if(
const auto* init = stmt->getInit()) {
2644 MultiStmtDeclCodeGenerator codeGenerator{
2645 mOutputFormatHelper, mLambdaStack, InsertVarDecl(nullptr)};
2649 mOutputFormatHelper.Append(
"; "sv);
2652 InsertArg(stmt->getCond());
2653 mOutputFormatHelper.Append(
"; "sv);
2655 InsertArg(stmt->getInc());
2657 AddSpaceAtTheEnd::Yes);
2660 WrapInCompoundIfNeeded(stmt->getBody(), AddNewLineAfter::Yes);
2663 mOutputFormatHelper.AppendNewLine();
2669 if(not type.isNull()) {
2670 if(
auto* typePtr = type.getTypePtrOrNull()) {
2671 if(
auto pointee = typePtr->getPointeeType(); not pointee.isNull()) {
2672 return pointee.isConstQualified();
2681 void CodeGenerator::InsertArg(
const CStyleCastExpr* stmt)
2683 const auto castKind = stmt->getCastKind();
2684 const QualType castDestType = stmt->getType().getCanonicalType();
2688 FormatCast(castName, castDestType, stmt->getSubExpr(), castKind);
2692 void CodeGenerator::InsertArg(
const CXXNewExpr* stmt)
2694 const auto noEmptyInitList = mNoEmptyInitList;
2695 FinalAction _{[&] { mNoEmptyInitList = noEmptyInitList; }};
2696 mNoEmptyInitList =
GetInsightsOptions().UseShow2C ? NoEmptyInitList::Yes : NoEmptyInitList::No;
2698 mOutputFormatHelper.Append(
"new "sv);
2700 if(stmt->getNumPlacementArgs()) {
2703 WrapInParens([&]() {
2704 ForEachArg(stmt->placement_arguments(), [&](
const auto& placementArg) { InsertArg(placementArg); });
2708 if(
const auto* ctorExpr = stmt->getConstructExpr()) {
2709 InsertArg(ctorExpr);
2712 auto name =
GetName(stmt->getAllocatedType());
2715 if(stmt->isArray()) {
2716 OutputFormatHelper ofm{};
2717 CodeGeneratorVariant codeGenerator{ofm};
2720 codeGenerator->
InsertArg(stmt->getArraySize().value());
2733 mOutputFormatHelper.Append(name);
2735 if(stmt->hasInitializer()) {
2736 InsertCurlysIfRequired(stmt->getInitializer());
2742 void CodeGenerator::InsertArg(
const MaterializeTemporaryExpr* stmt)
2745 const auto* temporary = stmt->getSubExpr();
2746 WrapInParensIfNeeded(isa_and_nonnull<ConditionalOperator>(temporary), [&] { InsertArg(temporary); });
2750 void CodeGenerator::InsertArg(
const CXXOperatorCallExpr* stmt)
2754 const auto* callee = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts());
2755 const bool isCXXMethod{callee and isa<CXXMethodDecl>(callee->getDecl())};
2757 if(2 == stmt->getNumArgs()) {
2758 auto getArg = [&](
unsigned idx) {
2759 const auto* arg = stmt->getArg(idx);
2764 arg = arg->IgnoreImpCasts();
2767 return dyn_cast_or_null<DeclRefExpr>(arg);
2770 const auto* param1 = getArg(0);
2771 const auto* param2 = getArg(1);
2773 if(callee and param1 and param2) {
2774 const std::string replace = [&]() {
2776 auto nameWithTmplArguments = [](
const auto param) {
2780 if(isa<CXXMethodDecl>(callee->getDecl())) {
2781 return StrCat(nameWithTmplArguments(param1),
2785 nameWithTmplArguments(param2),
2790 nameWithTmplArguments(param1),
2792 nameWithTmplArguments(param2),
2797 mOutputFormatHelper.Append(replace);
2803 auto cb = stmt->child_begin();
2804 const auto* fallbackArg0 = stmt->getArg(0);
2808 std::advance(cb, 1);
2810 const auto* arg1 = *cb;
2812 std::advance(cb, 1);
2815 if(not isCXXMethod) {
2818 if(
const auto* adl = dyn_cast_or_null<UnresolvedLookupExpr>(stmt->getCallee())) {
2822 mOutputFormatHelper.Append(
GetName(*callee));
2825 mOutputFormatHelper.Append(
"("sv);
2829 if(isa<DeclRefExpr>(fallbackArg0)) {
2830 InsertArgWithParensIfNeeded(fallbackArg0);
2833 InsertArgWithParensIfNeeded(arg1);
2838 const OverloadedOperatorKind opKind = stmt->getOperator();
2842 mOutputFormatHelper.Append(
"."sv, operatorKw, getOperatorSpelling(opKind),
"("sv);
2846 const auto childRange = llvm::make_range(cb, stmt->child_end());
2849 ForEachArg(childRange, [&](
const auto& child) {
2850 if(not isCXXMethod) {
2852 mOutputFormatHelper.Append(
", "sv);
2858 mOutputFormatHelper.Append(
')');
2862 void CodeGenerator::InsertArg(
const LambdaExpr* stmt)
2864 if(not mLambdaStack.empty()) {
2865 const bool insertName{mLambdaStack.back().insertName()};
2867 HandleLambdaExpr(stmt, mLambdaStack.back());
2873 }
else if(LambdaInInitCapture::Yes == mLambdaInitCapture) {
2875 HandleLambdaExpr(stmt, mLambdaStack.back());
2878 HandleLambdaExpr(stmt, mLambdaStack.back());
2881 if(not mLambdaStack.empty()) {
2882 mLambdaStack.back().insertInits(mOutputFormatHelper);
2887 void CodeGenerator::InsertArg(
const CXXThisExpr* stmt)
2891 mOutputFormatHelper.Append(
kwThis);
2895 void CodeGenerator::InsertArg(
const CXXBindTemporaryExpr* stmt)
2897 InsertArg(stmt->getSubExpr());
2901 void CodeGenerator::InsertArg(
const CXXFunctionalCastExpr* stmt)
2903 const bool isConstructor{isa<CXXConstructExpr>(stmt->getSubExpr())};
2904 const bool isStdListInit{isa<CXXStdInitializerListExpr>(stmt->getSubExpr())};
2905 const bool isListInitialization{stmt->getLParenLoc().isInvalid()};
2906 const bool needsParens{not isConstructor and not isListInitialization and not isStdListInit};
2909 if(not isConstructor and not isStdListInit) {
2910 mOutputFormatHelper.Append(
GetName(stmt->getTypeAsWritten()));
2913 WrapInParensIfNeeded(needsParens, [&] { InsertArg(stmt->getSubExpr()); });
2917 void CodeGenerator::InsertArg(
const CXXBoolLiteralExpr* stmt)
2923 void CodeGenerator::InsertArg(
const GNUNullExpr* )
2925 mOutputFormatHelper.Append(
kwNull);
2929 void CodeGenerator::InsertArg(
const CharacterLiteral* stmt)
2931 StringStream stream{};
2932 stream.Print(*stmt);
2934 auto str = std::move(stream.str());
2936 if(str ==
"'\\x00'"sv) {
2938 }
else if(str ==
"'\\xff'"sv) {
2942 mOutputFormatHelper.Append(str);
2946 void CodeGenerator::InsertArg(
const PredefinedExpr* stmt)
2950 if(
const auto* functionName = stmt->getFunctionName()) {
2951 InsertArg(functionName);
2953 const auto name = PredefinedExpr::getIdentKindName(stmt->getIdentKind());
2955 mOutputFormatHelper.Append(name);
2960 void CodeGenerator::InsertArg(
const ExprWithCleanups* stmt)
2962 mLifeTimeTracker.StartScope(
false);
2963 TemporaryDeclFinder temporaryFinder{*
this, not mProcessingVarDecl ? stmt->getSubExpr() :
nullptr};
2965 InsertArg(stmt->getSubExpr());
2968 mOutputFormatHelper.AppendSemiNewLine();
2971 mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper,
false);
2975 std::string CodeGenerator::GetValueOfValueInit(
const QualType& t)
2977 const QualType& type = t.getCanonicalType();
2979 if(type->isScalarType()) {
2980 switch(type->getScalarTypeKind()) {
2981 case Type::STK_CPointer:
2982 case Type::STK_BlockPointer:
2983 case Type::STK_ObjCObjectPointer:
2984 case Type::STK_MemberPointer:
return std::string{
kwNullptr};
2986 case Type::STK_Bool:
return std::string{
kwFalse};
2988 case Type::STK_Integral:
2989 case Type::STK_Floating:
2990 if(
const auto* bt = type->getAs<BuiltinType>()) {
2991 switch(bt->getKind()) {
2993 case BuiltinType::Char_U:
2994 case BuiltinType::UChar:
2995 case BuiltinType::Char_S:
2996 case BuiltinType::SChar:
return "'\\0'";
2997 case BuiltinType::WChar_U:
2998 case BuiltinType::WChar_S:
return "L'\\0'";
2999 case BuiltinType::Char16:
return "u'\\0'";
3000 case BuiltinType::Char32:
return "U'\\0'";
3002 case BuiltinType::Half:
3003 case BuiltinType::Float:
return "0.0f";
3004 case BuiltinType::Double:
return "0.0";
3011 case Type::STK_FloatingComplex:
3012 case Type::STK_IntegralComplex:
3013 if(
const auto* complexType = type->getAs<ComplexType>()) {
3014 return GetValueOfValueInit(complexType->getElementType());
3019 case Type::STK_FixedPoint:
Error(
"STK_FixedPoint is not implemented");
break;
3022 }
else if(
const auto* tt = dyn_cast_or_null<ConstantArrayType>(t.getTypePtrOrNull())) {
3023 const auto& elementType{tt->getElementType()};
3024 const std::string elementTypeInitValue{GetValueOfValueInit(elementType)};
3026 return FillConstantArray(tt, elementTypeInitValue, uint64_t{0});
3029 return std::string{
"0"sv};
3033 void CodeGenerator::InsertArg(
const ImplicitValueInitExpr* stmt)
3035 mOutputFormatHelper.Append(GetValueOfValueInit(stmt->getType()));
3039 void CodeGenerator::InsertArg(
const CXXScalarValueInitExpr* stmt)
3041 mOutputFormatHelper.Append(
GetName(stmt->getType()),
"()"sv);
3045 void CodeGenerator::InsertArg(
const CXXTryStmt* stmt)
3047 mOutputFormatHelper.AppendNewLine(
kwTrySpace);
3049 InsertArg(stmt->getTryBlock());
3052 InsertArg(stmt->getHandler(i));
3055 mOutputFormatHelper.AppendNewLine();
3059 void CodeGenerator::InsertArg(
const CXXCatchStmt* stmt)
3061 mOutputFormatHelper.Append(
" catch"sv);
3065 if(not stmt->getCaughtType().isNull()) {
3066 mOutputFormatHelper.Append(
3067 GetTypeNameAsParameter(stmt->getCaughtType(), stmt->getExceptionDecl()->getName()));
3069 mOutputFormatHelper.Append(kwElipsis);
3072 AddSpaceAtTheEnd::Yes);
3074 InsertArg(stmt->getHandlerBlock());
3078 void CodeGenerator::InsertArg(
const CXXThrowExpr* stmt)
3080 mOutputFormatHelper.Append(
"throw "sv);
3082 InsertArg(stmt->getSubExpr());
3086 void CodeGenerator::InsertArg(
const ConstantExpr* stmt)
3088 if((ShowConstantExprValue::Yes == mShowConstantExprValue) and stmt->hasAPValueResult()) {
3089 if(
const auto value = stmt->getAPValueResult(); value.isInt()) {
3090 mOutputFormatHelper.Append(value.getInt());
3095 InsertArg(stmt->getSubExpr());
3099 void CodeGenerator::InsertArg(
const TypeAliasDecl* stmt)
3101 const auto& underlyingType = stmt->getUnderlyingType();
3104 P0315Visitor dt{*
this};
3105 dt.TraverseType(underlyingType);
3109 if(
auto* templateSpecializationType = underlyingType->getAs<TemplateSpecializationType>()) {
3110 const bool carriesNamespace{[&] {
3111 if(
const auto tn = templateSpecializationType->getTemplateName();
3112 (TemplateName::QualifiedTemplate == tn.getKind()) or (TemplateName::DependentTemplate == tn.getKind())) {
3113 const auto* qtn = tn.getAsQualifiedTemplateName();
3115 return qtn->getQualifier() !=
nullptr;
3121 if(
const auto* elaboratedType = underlyingType->getAs<ElaboratedType>()) {
3122 if(templateSpecializationType->isSugared() and not carriesNamespace) {
3124 InsertNamespace(elaboratedType->getQualifier());
3128 StringStream stream{};
3129 stream.Print(*templateSpecializationType);
3131 mOutputFormatHelper.Append(stream.str());
3133 InsertTemplateArgs(*templateSpecializationType);
3134 }
else if(
auto* dependentTemplateSpecializationType =
3135 underlyingType->getAs<DependentTemplateSpecializationType>()) {
3139 InsertNamespace(dependentTemplateSpecializationType->getQualifier());
3141 mOutputFormatHelper.Append(
kwTemplateSpace, dependentTemplateSpecializationType->getIdentifier()->getName());
3143 InsertTemplateArgs(*dependentTemplateSpecializationType);
3146 mOutputFormatHelper.Append(
GetName(underlyingType));
3149 mOutputFormatHelper.AppendSemiNewLine();
3153 void CodeGenerator::InsertArg(
const TypedefDecl* stmt)
3162 void CodeGenerator::InsertCXXMethodHeader(
const CXXMethodDecl* stmt,
OutputFormatHelper& initOutputFormatHelper)
3165 CXXConstructorDecl* cxxInheritedCtorDecl{
nullptr};
3169 if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
3170 CodeGeneratorVariant codeGenerator{initOutputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
3176 for(
OnceTrue first{};
const auto* init : ctor->inits()) {
3179 initOutputFormatHelper.
Append(
": "sv);
3181 initOutputFormatHelper.
Append(
", "sv);
3186 if(
const auto* member = init->getMember()) {
3187 initOutputFormatHelper.
Append(member->getName());
3190 const auto* inlineInit = init->getInit();
3191 bool useCurlies{
false};
3193 if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3194 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3198 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3206 const auto* inlineInit = init->getInit();
3209 if(
const auto* member = init->getMember()) {
3210 initOutputFormatHelper.
Append(member->getName());
3212 if(isa<ParenListExpr>(inlineInit)) {
3218 }
else if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3219 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3225 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3228 const auto braceKind = isa<ParenListExpr>(inlineInit) ? BraceKind::Parens : BraceKind::Curlys;
3238 InsertTemplateGuardBegin(stmt);
3239 InsertFunctionNameWithReturnType(*stmt, cxxInheritedCtorDecl);
3243 void CodeGenerator::InsertCXXMethodDecl(
const CXXMethodDecl* stmt, SkipBody skipBody)
3246 initOutputFormatHelper.
SetIndent(mOutputFormatHelper, OutputFormatHelper::SkipIndenting::Yes);
3248 const auto posBeforeFunc = mOutputFormatHelper.CurrentPos();
3250 InsertCXXMethodHeader(stmt, initOutputFormatHelper);
3252 if(not stmt->isUserProvided() or stmt->isExplicitlyDefaulted()) {
3253 InsertTemplateGuardEnd(stmt);
3257 mOutputFormatHelper.Append(initOutputFormatHelper);
3259 if(isa<CXXConversionDecl>(stmt)) {
3260 if(stmt->getParent()->isLambda() and not stmt->doesThisDeclarationHaveABody()) {
3261 mOutputFormatHelper.AppendNewLine();
3262 WrapInCurlys([&]() {
3263 mOutputFormatHelper.AppendNewLine();
3264 mOutputFormatHelper.Append(
" "sv,
kwReturn,
" "sv);
3265 if(
const auto* invoker = stmt->getParent()->getLambdaStaticInvoker()) {
3266 mOutputFormatHelper.AppendSemiNewLine(invoker->getName());
3268 mOutputFormatHelper.AppendSemiNewLine(kwOperator,
"()"sv);
3274 if((SkipBody::No == skipBody) and stmt->doesThisDeclarationHaveABody() and not stmt->isLambdaStaticInvoker()) {
3275 InsertMethodBody(stmt, posBeforeFunc);
3277 }
else if(not InsertLambdaStaticInvoker(stmt) or (SkipBody::Yes == skipBody)) {
3278 mOutputFormatHelper.AppendSemiNewLine();
3281 InsertTemplateGuardEnd(stmt);
3283 if(SkipBody::No == skipBody) {
3284 mOutputFormatHelper.AppendNewLine();
3289 void CodeGenerator::InsertArg(
const CXXMethodDecl* stmt)
3295 not stmt->isExplicitlyDefaulted() and not stmt->isDeleted());
3297 InsertCXXMethodDecl(stmt, SkipBody::No);
3301 void CodeGenerator::InsertArg(
const EnumDecl* stmt)
3305 if(stmt->isScoped()) {
3306 if(stmt->isScopedUsingClassTag()) {
3313 mOutputFormatHelper.Append(stmt->getName());
3315 if(stmt->isFixed()) {
3316 mOutputFormatHelper.Append(
" : "sv,
GetName(stmt->getIntegerType()));
3319 mOutputFormatHelper.AppendNewLine();
3323 mOutputFormatHelper.IncreaseIndent();
3324 mOutputFormatHelper.AppendNewLine();
3327 ForEachArg(stmt->enumerators(), [&](
const auto* value) {
3329 mOutputFormatHelper.AppendNewLine();
3335 InsertArg(stmt->getBody());
3337 mOutputFormatHelper.DecreaseIndent();
3338 mOutputFormatHelper.AppendNewLine();
3340 AddSpaceAtTheEnd::No);
3342 mOutputFormatHelper.AppendSemiNewLine();
3343 mOutputFormatHelper.AppendNewLine();
3347 void CodeGenerator::InsertArg(
const EnumConstantDecl* stmt)
3349 mOutputFormatHelper.Append(stmt->getName());
3351 InsertAttributes(stmt);
3353 if(
const auto* initExpr = stmt->getInitExpr()) {
3356 InsertArg(initExpr);
3370 static const std::string_view spaces{
" "sv};
3372 if(offset >= spaces.size()) {
3375 return spaces.substr(0, spaces.size() - offset);
3380 void CodeGenerator::InsertArg(
const FieldDecl* stmt)
3383 P0315Visitor dt{*
this};
3385 auto type =
GetType(stmt->getType());
3386 dt.TraverseType(type);
3388 const auto initialSize{mOutputFormatHelper.size()};
3389 InsertAttributes(stmt->attrs());
3391 if(stmt->isMutable()) {
3395 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getParent())) {
3396 std::string name{
GetName(*stmt)};
3399 name = std::move(fieldName.value());
3404 if(
const auto* constantExpr = dyn_cast_or_null<ConstantExpr>(stmt->getBitWidth())) {
3405 mOutputFormatHelper.Append(
':');
3406 InsertArg(constantExpr);
3410 if(
const auto* initializer = stmt->getInClassInitializer();
3411 stmt->hasInClassInitializer() and initializer and cxxRecordDecl->isAggregate()) {
3412 const bool isConstructorExpr{isa<CXXConstructExpr>(initializer) or isa<ExprWithCleanups>(initializer)};
3413 if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) {
3417 InsertArg(initializer);
3421 mOutputFormatHelper.Append(
';');
3424 const auto* fieldClass = stmt->getParent();
3426 auto effectiveFieldSize{
GetGlobalAST().getTypeInfoInChars(type).Width.getQuantity()};
3427 auto getFieldOffsetInBytes = [&recordLayout](
const FieldDecl* field) {
3428 return recordLayout.getFieldOffset(field->getFieldIndex()) / 8;
3430 auto fieldOffset = getFieldOffsetInBytes(stmt);
3431 const auto offset = mOutputFormatHelper.size() - initialSize;
3433 mOutputFormatHelper.Append(
GetSpaces(offset),
" /* offset: "sv, fieldOffset,
", size: "sv, effectiveFieldSize);
3442 const auto expectedOffset = fieldOffset + effectiveFieldSize;
3443 const auto nextOffset = [&]() -> uint64_t {
3445 if(
const auto next = stmt->getFieldIndex() + 1; recordLayout.getFieldCount() > next) {
3447 const auto* field = *std::next(fieldClass->fields().begin(), next);
3449 return getFieldOffsetInBytes(field);
3453 return recordLayout.getSize().getQuantity();
3456 if(expectedOffset < nextOffset) {
3457 const auto padding = nextOffset - expectedOffset;
3458 mOutputFormatHelper.AppendNewLine();
3460 mOutputFormatHelper.Append(s,
GetSpaces(s.length()),
" size: ", padding);
3463 mOutputFormatHelper.AppendNewLine(
" */"sv);
3466 mOutputFormatHelper.AppendNewLine();
3471 void CodeGenerator::InsertArg(
const AccessSpecDecl* stmt)
3473 mOutputFormatHelper.AppendNewLine();
3478 void CodeGenerator::InsertArg(
const StaticAssertDecl* stmt)
3482 if(not stmt->isFailed()) {
3483 mOutputFormatHelper.Append(
"/* PASSED: "sv);
3485 mOutputFormatHelper.Append(
"/* FAILED: "sv);
3492 InsertArg(stmt->getAssertExpr());
3494 if(stmt->getMessage()) {
3495 mOutputFormatHelper.Append(
", "sv);
3496 InsertArg(stmt->getMessage());
3504 void CodeGenerator::InsertArg(
const UsingDirectiveDecl* stmt)
3507 if(
const auto& name =
GetName(*stmt->getNominatedNamespace()); not name.empty()) {
3513 void CodeGenerator::InsertArg(
const NamespaceDecl* stmt)
3517 if(stmt->isInline()) {
3523 if(not stmt->isAnonymousNamespace()) {
3524 mOutputFormatHelper.Append(
" "sv, stmt->getName());
3527 InsertAttributes(stmt);
3529 mOutputFormatHelper.AppendNewLine();
3531 mOutputFormatHelper.OpenScope();
3533 for(
const auto* decl : stmt->decls()) {
3537 mOutputFormatHelper.CloseScope();
3538 mOutputFormatHelper.AppendNewLine();
3542 void CodeGenerator::ParseDeclContext(
const DeclContext* ctx)
3548 void CodeGenerator::InsertArg(
const UsingDecl* stmt)
3551 ofm.
SetIndent(mOutputFormatHelper, OutputFormatHelper::SkipIndenting::Yes);
3556 if(stmt->shadow_size()) {
3557 for(
const auto* shadow : stmt->shadows()) {
3558 RETURN_IF(isa<ConstructorUsingShadowDecl>(shadow));
3560 if(
const auto* shadowUsing = dyn_cast_or_null<UsingShadowDecl>(shadow)) {
3561 if(
const auto* targetDecl = shadowUsing->getTargetDecl(); not isa<TypeAliasDecl>(targetDecl)) {
3562 UsingCodeGenerator codeGenerator{ofm};
3571 InsertQualifierAndName(stmt->getDeclName(), stmt->getQualifier(),
false);
3573 mOutputFormatHelper.AppendSemiNewLine();
3576 if(not ofm.empty()) {
3577 mOutputFormatHelper.AppendNewLine(ofm);
3582 void CodeGenerator::InsertArg(
const UnresolvedUsingValueDecl* stmt)
3586 InsertQualifierAndName(stmt->getDeclName(), stmt->getQualifier(),
false);
3588 mOutputFormatHelper.AppendSemiNewLine(
Ellipsis(stmt->isPackExpansion()));
3592 void CodeGenerator::InsertArg(
const NamespaceAliasDecl* stmt)
3594 mOutputFormatHelper.AppendNewLine(
3599 void CodeGenerator::InsertArg(
const FriendDecl* stmt)
3601 if(
const auto* typeInfo = stmt->getFriendType()) {
3604 }
else if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(stmt->getFriendDecl())) {
3607 }
else if(
const auto* fdt = dyn_cast_or_null<FunctionTemplateDecl>(stmt->getFriendDecl())) {
3612 if(
const auto* ctd = dyn_cast_or_null<ClassTemplateDecl>(stmt->getFriendDecl())) {
3613 InsertTemplateParameters(*ctd->getTemplateParameters());
3623 void CodeGenerator::InsertArg(
const CXXNoexceptExpr* stmt)
3631 void CodeGenerator::InsertArg(
const CXXDeductionGuideDecl* stmt)
3633 RETURN_IF(DeductionCandidate::Copy == stmt->getDeductionCandidateKind());
3635 const bool isImplicit{stmt->isImplicit()};
3636 const bool noSpecializations = [&] {
3637 if(
const auto* dt = stmt->getDescribedFunctionTemplate()) {
3638 return dt->specializations().empty();
3645 RETURN_IF(not stmt->isUsed() and isImplicit and noSpecializations);
3647 const bool isSpecialization{stmt->isFunctionTemplateSpecialization()};
3648 const bool needsTemplateGuard{isImplicit or isSpecialization};
3650 if(needsTemplateGuard) {
3651 InsertTemplateGuardBegin(stmt);
3654 const auto* deducedTemplate = stmt->getDeducedTemplate();
3656 if(isSpecialization) {
3657 InsertTemplateSpecializationHeader(*stmt);
3658 }
else if(
const auto* e = stmt->getDescribedFunctionTemplate()) {
3659 InsertTemplateParameters(*e->getTemplateParameters());
3662 mOutputFormatHelper.Append(
GetName(*deducedTemplate));
3664 if(stmt->getNumParams()) {
3665 WrapInParens([&] { mOutputFormatHelper.AppendParameterList(stmt->parameters()); });
3667 mOutputFormatHelper.Append(
"()"sv);
3670 mOutputFormatHelper.AppendSemiNewLine(
hlpArrow,
GetName(stmt->getReturnType()));
3672 if(needsTemplateGuard) {
3673 InsertTemplateGuardEnd(stmt);
3678 void CodeGenerator::InsertTemplate(
const FunctionTemplateDecl* stmt,
bool withSpec)
3682 mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::Yes;
3685 InsertArg(stmt->getTemplatedDecl());
3687 mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::No;
3691 for(
const auto* spec : stmt->specializations()) {
3693 if(spec->getPreviousDecl()) {
3697 mOutputFormatHelper.AppendNewLine();
3699 mOutputFormatHelper.AppendNewLine();
3704 void CodeGenerator::InsertArg(
const FunctionTemplateDecl* stmt)
3706 InsertTemplate(stmt,
true);
3710 void CodeGenerator::InsertArg(
const TypeAliasTemplateDecl* stmt)
3712 InsertTemplateParameters(*stmt->getTemplateParameters());
3714 InsertArg(stmt->getTemplatedDecl());
3718 void CodeGenerator::InsertArg(
const AttributedStmt* stmt)
3720 for(
const auto& attr : stmt->getAttrs()) {
3721 InsertAttribute(*attr);
3724 InsertArg(stmt->getSubStmt());
3728 void CodeGenerator::InsertAttributes(
const Decl* stmt)
3730 if(stmt->hasAttrs()) {
3731 mOutputFormatHelper.Append(
" "sv);
3733 InsertAttributes(stmt->attrs());
3738 void CodeGenerator::InsertAttributes(
const Decl::attr_range& attrs)
3741 for(
const auto& attr : attrs) {
3742 InsertAttribute(*attr);
3747 void CodeGenerator::InsertAttribute(
const Attr& attr)
3750 RETURN_IF(attr::Override == attr.getKind());
3753 RETURN_IF(attr::Final == attr.getKind());
3756 RETURN_IF(attr::NoInline == attr.getKind());
3759 if(
const auto* alignedAttr = dyn_cast_or_null<AlignedAttr>(&attr)) {
3760 auto insert = [&](
const QualType type,
const TemplateTypeParmType* tmplTypeParam) {
3761 mOutputFormatHelper.Append(attr.getSpelling(),
3767 Ellipsis(tmplTypeParam->isParameterPack()),
3771 if(alignedAttr->isAlignmentExpr()) {
3772 if(
const auto* unaryExpr = dyn_cast_or_null<UnaryExprOrTypeTraitExpr>(alignedAttr->getAlignmentExpr())) {
3773 if(
const auto* tmplTypeParam =
3774 dyn_cast_or_null<TemplateTypeParmType>(unaryExpr->getArgumentType().getTypePtrOrNull())) {
3775 insert(unaryExpr->getArgumentType(), tmplTypeParam);
3779 }
else if(
const auto* tmplTypeParam =
3780 alignedAttr->getAlignmentType()->getType()->getAs<TemplateTypeParmType>()) {
3781 insert(alignedAttr->getAlignmentType()->getType(), tmplTypeParam);
3788 pp.adjustForCPlusPlus();
3790 attr.printPretty(stream, pp);
3793 std::string_view start{stream.str()};
3795 mOutputFormatHelper.Append(start,
" "sv);
3799 void CodeGenerator::InsertArg(
const CXXRecordDecl* stmt)
3801 const size_t insertPosBeforeClass{mOutputFormatHelper.CurrentPos()};
3802 const auto indentAtInsertPosBeforeClass{mOutputFormatHelper.GetIndent()};
3807 RETURN_IF(stmt->isLambda() and (mLambdaStack.empty() or (
nullptr == mLambdaExpr)));
3809 const auto* classTemplatePartialSpecializationDecl = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(stmt);
3810 const auto* classTemplateSpecializationDecl = dyn_cast_or_null<ClassTemplateSpecializationDecl>(stmt);
3814 const bool isClassTemplateSpecialization{classTemplatePartialSpecializationDecl or classTemplateSpecializationDecl};
3815 const bool tmplRequiresIfDef{[&] {
3816 if(classTemplatePartialSpecializationDecl) {
3817 return classTemplatePartialSpecializationDecl->isImplicit();
3819 }
else if(classTemplateSpecializationDecl) {
3820 return not classTemplateSpecializationDecl->isExplicitInstantiationOrSpecialization();
3827 if(tmplRequiresIfDef) {
3828 mOutputFormatHelper.InsertEndIfTemplateGuard();
3832 if(isClassTemplateSpecialization) {
3833 if(tmplRequiresIfDef) {
3834 InsertInstantiationPoint(
GetSM(*classTemplateSpecializationDecl),
3835 classTemplateSpecializationDecl->getPointOfInstantiation());
3836 mOutputFormatHelper.InsertIfDefTemplateGuard();
3839 if(classTemplatePartialSpecializationDecl) {
3840 InsertTemplateParameters(*classTemplatePartialSpecializationDecl->getTemplateParameters());
3842 InsertTemplateSpecializationHeader(*stmt);
3845 }
else if(stmt->getLexicalDeclContext() != stmt->getDeclContext()) {
3846 if(
const auto* parent = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
3847 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
3848 InsertTemplateParameters(*outerClasTemplateDecl->getTemplateParameters());
3855 InsertAttributes(stmt->attrs());
3857 mOutputFormatHelper.Append(
GetName(*stmt));
3859 if(classTemplateSpecializationDecl) {
3860 InsertTemplateArgs(*classTemplateSpecializationDecl);
3863 if(stmt->hasAttr<FinalAttr>()) {
3868 if(not stmt->hasDefinition() or not stmt->isCompleteDefinition()) {
3869 mOutputFormatHelper.AppendSemiNewLine();
3873 if(stmt->getNumBases()) {
3874 mOutputFormatHelper.Append(
" : "sv);
3876 ForEachArg(stmt->bases(), [&](
const auto& base) {
3877 mOutputFormatHelper.Append(getAccessSpelling(base.getAccessSpecifier()),
3879 ValueOrDefault(base.isVirtual(), kwVirtualSpace),
3880 GetName(base.getType()),
3881 Ellipsis(base.isPackExpansion()));
3887 mOutputFormatHelper.AppendNewLine(
3888 " /* size: "sv, recordLayout.getSize(),
", align: "sv, recordLayout.getAlignment(),
" */"sv);
3891 mOutputFormatHelper.AppendNewLine();
3894 mOutputFormatHelper.OpenScope();
3897 for(
size_t offset{};
const auto& base : stmt->bases()) {
3898 const auto& baseRecordLayout =
GetRecordLayout(base.getType()->getAsRecordDecl());
3899 const auto baseVar =
StrCat(
"/* base ("sv,
GetName(base.getType()),
")"sv);
3900 const auto size = baseRecordLayout.getSize().getQuantity();
3902 mOutputFormatHelper.AppendNewLine(
3903 baseVar,
GetSpaces(baseVar.size()),
" offset: "sv, offset,
", size: "sv, size,
" */"sv);
3909 UpdateCurrentPos(mCurrentFieldPos);
3913 Decl::Kind formerKind{};
3914 AccessSpecifier lastAccess{stmt->isClass() ? AS_private : AS_public};
3915 for(
const auto* d : stmt->decls()) {
3916 if(isa<CXXRecordDecl>(d) and firstRecordDecl) {
3922 if(not firstDecl and (d->getKind() != formerKind)) {
3926 if((stmt->isLambda() and isa<CXXDestructorDecl>(d)) and not d->isUsed()) {
3932 if(lastAccess != d->getAccess()) {
3933 lastAccess = d->getAccess();
3936 if(not isa<AccessSpecDecl>(d)) {
3943 formerKind = d->getKind();
3946 if(stmt->isLambda()) {
3947 const LambdaCallerType lambdaCallerType = mLambdaStack.back().callerType();
3948 const bool ctorRequired{stmt->capture_size() or stmt->lambdaIsDefaultConstructibleAndAssignable()};
3951 if(AS_public != lastAccess) {
3952 mOutputFormatHelper.AppendNewLine();
3955 std::string_view p{pub};
3957 mOutputFormatHelper.AppendNewLine(p);
3960 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
3963 if(stmt->hasConstexprDefaultConstructor()) {
3968 mOutputFormatHelper.Append(
GetName(*stmt),
"("sv);
3971 SmallVector<std::string, 5> ctorInitializerList{};
3972 std::string ctorArguments{
'{'};
3976 [&](std::string_view name,
const FieldDecl* fd,
bool isThis,
const Expr* expr,
bool ) {
3977 if(firstCtorArgument) {
3979 mOutputFormatHelper.Append(
", "sv);
3980 ctorArguments.append(
", "sv);
3983 bool byConstRef{
false};
3985 auto fieldDeclType{fd->getType()};
3988 std::string fname =
StrCat(
"_"sv, name);
3992 if(
const auto* cxxConstructExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
3993 cxxConstructExpr and cxxConstructExpr->getConstructor()->isMoveConstructor()) {
3995 OutputFormatHelper ofm{};
3996 LambdaInitCaptureCodeGenerator codeGenerator{ofm, mLambdaStack, name};
3998 if(cxxConstructExpr->getNumArgs()) {
3999 ForEachArg(cxxConstructExpr->arguments(),
4000 [&](
const auto& arg) { codeGenerator.InsertArg(arg); });
4003 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4009 }
else if(not fieldDeclType->isReferenceType() and not fieldDeclType->isAnyPointerType() and
4010 not fieldDeclType->isUndeducedAutoType()) {
4012 const auto* exprWithoutImpCasts = expr->IgnoreParenImpCasts();
4015 if(exprWithoutImpCasts->isXValue()) {
4018 OutputFormatHelper ofm{};
4019 LambdaInitCaptureCodeGenerator codeGenerator{ofm, mLambdaStack, name};
4024 }
else if(exprWithoutImpCasts
4026 or exprWithoutImpCasts->getType().isConstQualified()
4033 if(exprWithoutImpCasts->isPRValue() and isa<CXXBindTemporaryExpr>(exprWithoutImpCasts) and
4034 not exprWithoutImpCasts->getType().isConstQualified()) {
4035 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4037 fname =
StrCat(
"std::move("sv, fname,
")"sv);
4041 fieldDeclType.addConst();
4045 if(exprWithoutImpCasts->isXValue()) {
4046 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4048 }
else if(not isMoved) {
4049 fieldDeclType = stmt->getASTContext().getLValueReferenceType(fieldDeclType);
4053 const std::string_view elips{
4054 Ellipsis(isa_and_nonnull<PackExpansionType>(fieldDeclType->getPointeeType().getTypePtrOrNull()))};
4057 fieldDeclType = fieldDeclType.getCanonicalType();
4059 ctorInitializerList.push_back(
StrCat(fieldName,
"{"sv, fname, elips,
"}"sv));
4061 if(not isThis and expr) {
4063 OutputFormatHelper ofmLambdaInCtor{};
4064 ofmLambdaInCtor.SetIndent(indentAtInsertPosBeforeClass);
4065 CodeGenerator cgLambdaInCtor{ofmLambdaInCtor, LambdaInInitCapture::Yes};
4067 if(P0315Visitor dt{cgLambdaInCtor}; dt.TraverseStmt(
const_cast<Expr*
>(expr))) {
4069 OutputFormatHelper ofm{};
4070 CodeGeneratorVariant codeGenerator{ofm, mLambdaStack, mProcessingPrimaryTemplate};
4072 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4073 ctorExpr and byConstRef and (1 == ctorExpr->getNumArgs())) {
4074 codeGenerator->
InsertArg(ctorExpr->getArg(0));
4084 ctorArguments.append(ofm);
4087 OutputFormatHelper ofm{};
4088 LambdaNameOnlyCodeGenerator ccg{ofm};
4089 ccg.InsertArg(expr);
4091 ctorArguments.append(ofm.GetString());
4093 mOutputFormatHelper.InsertAt(insertPosBeforeClass, ofmLambdaInCtor);
4096 if(isThis and not fieldDeclType->isPointerType()) {
4097 ctorArguments.append(
"*"sv);
4100 ctorArguments.append(name);
4106 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
4107 FieldDecl* thisCapture{};
4109 stmt->getCaptureFields(captures, thisCapture);
4113 const auto* captureInit = mLambdaExpr->capture_init_begin();
4115 addToInits(
kwThis, thisCapture,
true, *captureInit,
false);
4121 for(
const auto& [c, cinit] : zip(mLambdaExpr->captures(), mLambdaExpr->capture_inits())) {
4122 if(not c.capturesVariable()) {
4126 const auto* capturedVar = c.getCapturedVar();
4127 if(
const auto* value = captures[capturedVar]) {
4129 if(
const auto* bindingDecl = dyn_cast_or_null<BindingDecl>(capturedVar)) {
4130 capturedVar = bindingDecl->getHoldingVar();
4133 addToInits(
GetName(*capturedVar),
4137 VarDecl::ListInit == dyn_cast_or_null<VarDecl>(capturedVar)->getInitStyle());
4141 ctorArguments.append(
"}"sv);
4146 mOutputFormatHelper.Append(
")"sv);
4148 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
4152 mOutputFormatHelper.AppendNewLine();
4154 for(
OnceTrue firstCtorInitializer{};
const auto& initializer : ctorInitializerList) {
4155 if(firstCtorInitializer) {
4156 mOutputFormatHelper.Append(
": "sv);
4158 mOutputFormatHelper.Append(
", "sv);
4161 mOutputFormatHelper.AppendNewLine(initializer);
4164 mOutputFormatHelper.AppendNewLine(
"{}"sv);
4169 mOutputFormatHelper.CloseScope();
4171 if(not
is{lambdaCallerType}.any_of(LambdaCallerType::VarDecl,
4172 LambdaCallerType::InitCapture,
4173 LambdaCallerType::CallExpr,
4174 LambdaCallerType::MemberCallExpr,
4175 LambdaCallerType::TemplateHead,
4176 LambdaCallerType::Decltype)) {
4177 mOutputFormatHelper.Append(
" "sv,
GetLambdaName(*stmt), ctorArguments);
4178 }
else if(not
is{lambdaCallerType}.any_of(LambdaCallerType::TemplateHead, LambdaCallerType::Decltype)) {
4179 mLambdaStack.back().inits().append(ctorArguments);
4182 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
4186 mOutputFormatHelper.Append(
" "sv,
GetName(*stmt));
4189 mOutputFormatHelper.AppendSemiNewLine();
4190 mOutputFormatHelper.AppendNewLine();
4194 void CodeGenerator::InsertArg(
const DeclStmt* stmt)
4196 for(
const auto* decl : stmt->decls()) {
4202 void CodeGenerator::InsertArg(
const SubstNonTypeTemplateParmExpr* stmt)
4204 InsertArg(stmt->getReplacement());
4208 void CodeGenerator::InsertArg(
const SizeOfPackExpr* stmt)
4210 if(stmt->isPartiallySubstituted()) {
4211 mOutputFormatHelper.Append(stmt->getPartialArguments().size());
4212 }
else if(not stmt->isValueDependent()) {
4213 mOutputFormatHelper.Append(stmt->getPackLength());
4220 void CodeGenerator::InsertArg(
const ReturnStmt* stmt)
4224 UpdateCurrentPos(mCurrentReturnPos);
4227 TemporaryDeclFinder temporaryFinder{*
this, stmt->getRetValue(),
true};
4229 mOutputFormatHelper.Append(
kwReturn);
4231 if(
const auto* retVal = stmt->getRetValue()) {
4232 mOutputFormatHelper.Append(
' ');
4234 if(not temporaryFinder.Found()) {
4235 if(
const auto* nrvoVD = stmt->getNRVOCandidate()) {
4236 mOutputFormatHelper.Append(
GetName(*nrvoVD));
4241 mOutputFormatHelper.Append(temporaryFinder.Name());
4246 mSkipSemi = mLifeTimeTracker.Return(mOutputFormatHelper);
4251 mCurrentReturnPos.reset();
4255 void CodeGenerator::InsertArg(
const NullStmt* )
4257 mOutputFormatHelper.AppendSemiNewLine();
4262 void CodeGenerator::InsertArg(
const StmtExpr* stmt)
4264 WrapInParens([&] { InsertArg(stmt->getSubStmt()); });
4268 void CodeGenerator::InsertArg(
const CppInsightsCommentStmt* stmt)
4270 mOutputFormatHelper.AppendCommentNewLine(stmt->Comment());
4274 void CodeGenerator::InsertArg(
const ConceptSpecializationExpr* stmt)
4276 if(
const auto* namedConcept = stmt->getNamedConcept()) {
4277 mOutputFormatHelper.Append(
GetName(*namedConcept));
4278 InsertTemplateArgs(stmt->getTemplateArgsAsWritten()->arguments());
4281 if(not stmt->isValueDependent()) {
4289 void CodeGenerator::InsertArg(
const RequiresExpr* stmt)
4293 const auto localParameters = stmt->getLocalParameters();
4294 WrapInParensIfNeeded(
4295 not localParameters.empty(),
4296 [&] { mOutputFormatHelper.AppendParameterList(localParameters); },
4297 AddSpaceAtTheEnd::Yes);
4299 mOutputFormatHelper.OpenScope();
4301 const auto noEmptyInitList = mNoEmptyInitList;
4302 FinalAction _{[&] { mNoEmptyInitList = noEmptyInitList; }};
4303 mNoEmptyInitList = NoEmptyInitList::Yes;
4305 for(
const auto& requirement : stmt->getRequirements()) {
4306 if(
const auto* typeRequirement = dyn_cast_or_null<concepts::TypeRequirement>(requirement)) {
4307 if(typeRequirement->isSubstitutionFailure()) {
4310 mOutputFormatHelper.Append(
GetName(typeRequirement->getType()->getType()));
4314 }
else if(
const auto* exprRequirement = dyn_cast_or_null<concepts::ExprRequirement>(requirement)) {
4315 if(exprRequirement->isExprSubstitutionFailure()) {
4320 WrapInCurliesIfNeeded(exprRequirement->isCompound(), [&] { InsertArg(exprRequirement->getExpr()); });
4322 if(exprRequirement->hasNoexceptRequirement()) {
4326 if(
const auto& returnTypeRequirement = exprRequirement->getReturnTypeRequirement();
4327 not returnTypeRequirement.isEmpty()) {
4329 not typeConstraint.empty()) {
4330 mOutputFormatHelper.Append(
hlpArrow, std::move(typeConstraint));
4334 }
else if(
const auto* nestedRequirement = dyn_cast_or_null<concepts::NestedRequirement>(requirement)) {
4337 if(nestedRequirement->hasInvalidConstraint()) {
4340 mOutputFormatHelper.Append(
kwFalse);
4342 InsertArg(nestedRequirement->getConstraintExpr());
4346 mOutputFormatHelper.AppendSemiNewLine();
4349 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
4353 void CodeGenerator::InsertArg(
const CXXDefaultArgExpr* stmt)
4355 InsertArg(stmt->getExpr());
4359 void CodeGenerator::InsertArg(
const CXXStdInitializerListExpr* stmt)
4363 const auto typeName{
GetName(stmt->getType(), Unqualified::Yes)};
4366 RETURN_IF(not mCurrentVarDeclPos.has_value() and not mCurrentFieldPos.has_value() and
4367 not mCurrentReturnPos.has_value() and not mCurrentCallExprPos.has_value());
4369 const auto* subExpr = stmt->getSubExpr();
4371 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(subExpr); dref and
GetInsightsOptions().ShowLifetime) {
4372 const auto size =
GetSize(dyn_cast_or_null<ConstantArrayType>(subExpr->getType()));
4374 mOutputFormatHelper.Append(typeName,
"{"sv,
GetName(*dref),
", "sv, size,
"}"sv);
4378 std::string modifiers{};
4379 size_t variableInsertPos = mCurrentReturnPos.value_or(
4380 mCurrentVarDeclPos.value_or(mCurrentCallExprPos.value_or(0)));
4382 auto& ofmToInsert = [&]() -> decltype(
auto) {
4383 if(not mCurrentVarDeclPos.has_value() and not mCurrentReturnPos.has_value() and
4384 not mCurrentCallExprPos.has_value()) {
4385 variableInsertPos = mCurrentFieldPos.value_or(0);
4386 mCurrentVarDeclPos = variableInsertPos;
4388 return (*mOutputFormatHelperOutside);
4391 return (mOutputFormatHelper);
4394 OutputFormatHelper ofm{};
4395 ofm.SetIndent(ofmToInsert, OutputFormatHelper::SkipIndenting::Yes);
4397 const auto size = [&]() ->
size_t {
4398 if(
const auto* mat = dyn_cast<MaterializeTemporaryExpr>(subExpr)) {
4399 if(
const auto* list = dyn_cast_or_null<InitListExpr>(mat->getSubExpr())) {
4400 return list->getNumInits();
4407 auto internalListName =
4411 CodeGeneratorVariant codeGenerator{ofm};
4413 ofm.AppendSemiNewLine();
4415 ofmToInsert.InsertAt(variableInsertPos, ofm);
4417 mOutputFormatHelper.Append(typeName,
"{"sv, internalListName,
", "sv, size,
"}"sv);
4419 if(mCurrentReturnPos.has_value()) {
4420 mCurrentReturnPos = mCurrentReturnPos.value() + ofm.size();
4421 }
else if(mCurrentVarDeclPos.has_value()) {
4422 mCurrentVarDeclPos = mCurrentVarDeclPos.value() + ofm.size();
4424 mCurrentCallExprPos = mCurrentCallExprPos.value() + ofm.size();
4428 mOutputFormatHelper.Append(typeName);
4429 InsertArg(stmt->getSubExpr());
4434 void CodeGenerator::InsertArg(
const CXXNullPtrLiteralExpr* )
4440 void CodeGenerator::InsertArg(
const LabelDecl* stmt)
4442 mOutputFormatHelper.Append(stmt->getName());
4446 void CodeGenerator::InsertArg(
const Decl* stmt)
4450 #define SUPPORTED_DECL(type) \
4451 if(isa<type>(stmt)) { \
4452 InsertArg(static_cast<const type*>(stmt)); \
4456 #define IGNORED_DECL SUPPORTED_DECL
4460 ToDo(stmt, mOutputFormatHelper);
4464 void CodeGenerator::InsertArg(
const Stmt* stmt)
4473 #define SUPPORTED_STMT(type) \
4474 if(isa<type>(stmt)) { \
4475 InsertArg(dyn_cast_or_null<type>(stmt)); \
4479 #define IGNORED_STMT SUPPORTED_STMT
4483 ToDo(stmt, mOutputFormatHelper);
4487 void CodeGenerator::FormatCast(
const std::string_view castName,
4488 const QualType& castDestType,
4489 const Expr* subExpr,
4490 const CastKind& castKind)
4492 const bool isCastToBase{
is{castKind}.
any_of(CK_DerivedToBase, CK_UncheckedDerivedToBase) and
4493 castDestType->isRecordType()};
4494 const std::string castDestTypeText{
4495 StrCat(
GetName(castDestType), ((isCastToBase and not castDestType->isAnyPointerType()) ?
"&"sv :
""sv))};
4497 mOutputFormatHelper.Append(castName,
"<"sv, castDestTypeText,
">("sv);
4499 mOutputFormatHelper.Append(
')');
4503 void CodeGenerator::InsertArgWithParensIfNeeded(
const Stmt* stmt)
4505 const bool needsParens = [&]() {
4506 if(
const auto* expr = dyn_cast_or_null<Expr>(stmt)) {
4507 if(
const auto* dest = dyn_cast_or_null<UnaryOperator>(expr->IgnoreImplicit())) {
4508 return (dest->getOpcode() == clang::UO_Deref);
4515 WrapInParensIfNeeded(needsParens, [&] { InsertArg(stmt); });
4519 void CodeGenerator::InsertSuffix(
const QualType& type)
4521 if(
const auto* typePtr = type.getTypePtrOrNull(); typePtr and typePtr->isBuiltinType()) {
4522 if(
const auto* bt = dyn_cast_or_null<BuiltinType>(typePtr)) {
4523 const auto kind = bt->getKind();
4525 mOutputFormatHelper.Append(GetBuiltinTypeSuffix(kind));
4531 void CodeGenerator::InsertTemplateArgs(
const ClassTemplateSpecializationDecl& clsTemplateSpe)
4533 if(
const auto* ar = clsTemplateSpe.getTemplateArgsAsWritten()) {
4534 InsertTemplateArgs(ar->arguments());
4536 InsertTemplateArgs(clsTemplateSpe.getTemplateArgs());
4541 void CodeGenerator::HandleTemplateParameterPack(
const ArrayRef<TemplateArgument>& args)
4543 ForEachArg(args, [&](
const auto& arg) { InsertTemplateArg(arg); });
4547 void CodeGenerator::InsertTemplateArg(
const TemplateArgument& arg)
4549 switch(arg.getKind()) {
4550 case TemplateArgument::Type: mOutputFormatHelper.Append(
GetName(arg.getAsType()));
break;
4551 case TemplateArgument::Declaration:
4553 if(
const auto decl = dyn_cast_or_null<TemplateParamObjectDecl>(arg.getAsDecl())) {
4554 mOutputFormatHelper.Append(
GetName(*decl));
4556 mOutputFormatHelper.Append(
"&"sv,
GetName(*arg.getAsDecl(), QualifiedName::Yes));
4559 case TemplateArgument::NullPtr: mOutputFormatHelper.Append(
kwNullptr);
break;
4560 case TemplateArgument::Integral:
4562 if(
const auto& integral = arg.getAsIntegral(); arg.getIntegralType()->isCharType()) {
4563 const char c{
static_cast<char>(integral.getZExtValue())};
4564 mOutputFormatHelper.Append(
"'"sv, std::string{c},
"'"sv);
4566 mOutputFormatHelper.Append(integral);
4570 case TemplateArgument::Expression: {
4572 mOutputFormatHelper.Append(
4576 InsertArg(arg.getAsExpr());
4581 case TemplateArgument::Pack: HandleTemplateParameterPack(arg.pack_elements());
break;
4582 case TemplateArgument::Template:
4583 mOutputFormatHelper.Append(
GetName(*arg.getAsTemplate().getAsTemplateDecl()));
4585 case TemplateArgument::TemplateExpansion:
4586 mOutputFormatHelper.Append(
GetName(*arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()));
4588 case TemplateArgument::Null: mOutputFormatHelper.Append(
"null"sv);
break;
4589 case TemplateArgument::StructuralValue: mOutputFormatHelper.Append(arg.getAsStructuralValue());
break;
4594 void CodeGenerator::HandleLocalStaticNonTrivialClass(
const VarDecl* stmt)
4601 const bool threadSafe{langOpts.ThreadsafeStatics and langOpts.CPlusPlus11 and
4602 (stmt->isLocalVarDecl() ) and not stmt->getTLSKind()};
4605 const std::string compilerBoolVarName{
StrCat(internalVarName,
"Guard"sv)};
4608 auto* compilerGuardVar =
4609 Variable(compilerBoolVarName, threadSafe ?
Typedef(
"uint64_t"sv, ctx.UnsignedLongTy) : ctx.BoolTy);
4610 compilerGuardVar->setStorageClass(StorageClass::SC_Static);
4611 InsertArg(compilerGuardVar);
4614 auto* compilerStorageVar =
Variable(internalVarName,
4615 ctx.getConstantArrayType(ctx.CharTy,
4616 llvm::APInt(ctx.getTypeSize(ctx.getSizeType()), 0),
4618 ArraySizeModifier::Normal,
4621 compilerStorageVar->setStorageClass(StorageClass::SC_Static);
4624 AlignedAttr::CreateImplicit(
const_cast<ASTContext&
>(ctx),
4628 AlignedAttr::Spelling::Keyword_alignas);
4630 compilerStorageVar->addAttr(alignedAttr);
4632 const std::string typeName{
GetName(stmt->getType())};
4633 mOutputFormatHelper.AppendSemiNewLine(
4634 "alignas("sv, typeName,
") static char "sv, internalVarName,
"[sizeof("sv, typeName,
")]"sv);
4637 mOutputFormatHelper.AppendNewLine();
4641 const bool canThrow{[&] {
4642 const ValueDecl* decl = [&]() ->
const ValueDecl* {
4643 const auto* init = stmt->getInit()->IgnoreCasts();
4644 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init)) {
4645 return ctorExpr->getConstructor();
4646 }
else if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(init)) {
4647 return callExpr->getDirectCallee();
4654 if(
const auto* func = decl->getType()->castAs<FunctionProtoType>()) {
4655 return not func->isNothrow();
4663 auto* init =
const_cast<Expr*
>(stmt->getInit());
4665 if(
const bool isCallExpr{not isa<CXXConstructExpr>(init->IgnoreCasts())}; isCallExpr) {
4667 init =
Call(
"std::move"sv, {init});
4676 auto type = stmt->getType();
4677 type.removeLocalConst();
4678 SmallVector<Stmt*, 4> allocAndFlagBodyStmts{
New({
Ref(compilerStorageVar)}, init, type),
4680 auto allocAndFlagBodyCompound =
mkCompoundStmt(allocAndFlagBodyStmts);
4687 Try(allocAndFlagBodyCompound,
Catch({
Call(
"__cxa_guard_abort"sv, {
Ref(compilerGuardVar)}),
Throw()})));
4689 innerBodyStmts.AddBodyStmts(allocAndFlagBodyCompound);
4697 StrCat(
"__cxa_atexit("sv, typeName,
"::~"sv, typeName,
", &"sv, internalVarName,
", &__dso_handle);"sv)));
4699 auto* aquireIf =
If(
Call(
"__cxa_guard_acquire"sv, {
Ref(compilerGuardVar)}), innerBodyStmts);
4700 bodyStmts.AddBodyStmts(aquireIf);
4702 bodyStmts.AddBodyStmts(allocAndFlagBodyCompound);
4709 std::string_view CodeGenerator::GetBuiltinTypeSuffix(
const BuiltinType::Kind& kind)
4711 #define CASE(K, retVal) \
4712 case BuiltinType::K: return retVal
4715 CASE(ULong,
"UL"sv);
4716 CASE(ULongLong,
"ULL"sv);
4717 CASE(UInt128,
"ULLL"sv);
4719 CASE(LongLong,
"LL"sv);
4721 CASE(LongDouble,
"L"sv);
4728 void CodeGenerator::HandleLambdaExpr(
const LambdaExpr* lambda,
LambdaHelper& lambdaHelper)
4733 LambdaCodeGenerator codeGenerator{outputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
4734 codeGenerator.mCapturedThisAsCopy = ranges::any_of(
4735 lambda->captures(), [](
auto& c) { return (c.capturesThis() and (c.getCaptureKind() == LCK_StarThis)); });
4738 codeGenerator.
InsertArg(lambda->getLambdaClass());
4742 void CodeGenerator::InsertConceptConstraint(
const llvm::SmallVectorImpl<const Expr*>& constraints,
4743 const InsertInline insertInline)
4745 for(
OnceTrue first{};
const auto* c : constraints) {
4746 if(first and (InsertInline::Yes == insertInline)) {
4747 mOutputFormatHelper.Append(
' ');
4753 if(InsertInline::No == insertInline) {
4754 mOutputFormatHelper.AppendNewLine();
4761 void CodeGenerator::InsertConceptConstraint(
const TemplateParameterList& tmplDecl)
4763 if(
const auto* reqClause = tmplDecl.getRequiresClause()) {
4764 SmallVector<const Expr*, 1> constraints{reqClause};
4766 InsertConceptConstraint(constraints, InsertInline::No);
4772 void CodeGenerator::InsertConceptConstraint(
const FunctionDecl* tmplDecl)
4774 SmallVector<const Expr*, 5> constraints{};
4775 tmplDecl->getAssociatedConstraints(constraints);
4777 InsertConceptConstraint(constraints, InsertInline::Yes);
4782 void CodeGenerator::InsertConceptConstraint(
const VarDecl* varDecl)
4784 if(
const auto* t = varDecl->getType()->getContainedAutoType()) {
4785 if(t->getTypeConstraintConcept()) {
4794 void CodeGenerator::InsertFunctionNameWithReturnType(
const FunctionDecl& decl,
4795 const CXXConstructorDecl* cxxInheritedCtorDecl)
4797 bool isLambda{
false};
4798 bool isFirstCxxMethodDecl{
true};
4799 const auto* methodDecl{dyn_cast_or_null<CXXMethodDecl>(&decl)};
4800 bool isCXXMethodDecl{
nullptr != methodDecl};
4801 const bool isClassTemplateSpec{isCXXMethodDecl and isa<ClassTemplateSpecializationDecl>(methodDecl->getParent())};
4802 const bool requiresComment{isCXXMethodDecl and not methodDecl->isUserProvided() and
4803 not methodDecl->isExplicitlyDefaulted()};
4805 const bool isLambdaStaticInvoker{isCXXMethodDecl and methodDecl->isLambdaStaticInvoker()};
4806 const FunctionDecl& constExprDecl{not isLambdaStaticInvoker ? decl
4807 : *methodDecl->getParent()->getLambdaCallOperator()};
4811 if(requiresComment) {
4815 isLambda = methodDecl->getParent()->isLambda();
4816 isFirstCxxMethodDecl = (
nullptr == methodDecl->getPreviousDecl());
4820 if(isa<CXXConversionDecl>(decl) and TypeContainsSubType<PointerType, FunctionProtoType>(desugaredReturnType)) {
4821 mOutputFormatHelper.AppendSemiNewLine(
4825 if(isCXXMethodDecl and decl.isOutOfLine()) {
4826 if(
const auto* parent = methodDecl->getParent()) {
4827 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
4828 InsertTemplateParameters(*outerClasTemplateDecl->getTemplateParameters());
4833 if(decl.isTemplated()) {
4834 if(decl.getDescribedTemplate()) {
4835 InsertTemplateParameters(*decl.getDescribedTemplate()->getTemplateParameters());
4838 }
else if(decl.isFunctionTemplateSpecialization() or (isClassTemplateSpec and decl.isOutOfLine() and
4839 (decl.getLexicalDeclContext() != methodDecl->getParent()))) {
4840 InsertTemplateSpecializationHeader(decl);
4843 InsertAttributes(decl.attrs());
4845 if(not decl.isFunctionTemplateSpecialization() or (isCXXMethodDecl and isFirstCxxMethodDecl)) {
4846 if(not decl.isOutOfLine() or (decl.getStorageClass() == SC_Extern)) {
4853 if(isCXXMethodDecl and not decl.isOutOfLine()) {
4861 if(Decl::FOK_None != decl.getFriendObjectKind()) {
4865 if(decl.isInlined()) {
4869 if(methodDecl and isFirstCxxMethodDecl) {
4870 if(methodDecl->isVirtual()) {
4874 const auto exspec = ExplicitSpecifier::getFromDecl(methodDecl);
4876 if(
const auto* expr = exspec.getExpr()) {
4881 switch(exspec.getKind()) {
4882 case ExplicitSpecKind::Unresolved: InsertArg(expr); break;
4883 case ExplicitSpecKind::ResolvedFalse: mOutputFormatHelper.Append(kwFalse); break;
4884 case ExplicitSpecKind::ResolvedTrue: mOutputFormatHelper.Append(
"true"sv); break;
4887 AddSpaceAtTheEnd::Yes);
4889 }
else if(exspec.isExplicit()) {
4894 if(constExprDecl.isConstexpr()) {
4895 const bool skipConstexpr{isLambda and not isa<CXXConversionDecl>(constExprDecl)};
4899 const bool isConversionOpWithConstevalCallOp{[&]() {
4901 if(
const auto callOp = methodDecl->getParent()->getLambdaCallOperator()) {
4902 return callOp->isConsteval();
4909 if(not isConversionOpWithConstevalCallOp and constExprDecl.isConstexprSpecified()) {
4920 }
else if(isConversionOpWithConstevalCallOp or constExprDecl.isConsteval()) {
4929 if(not isFirstCxxMethodDecl or InsertNamespace() and decl.getQualifier()) {
4931 cg->InsertNamespace(decl.getQualifier());
4934 }
else if(not isFirstCxxMethodDecl or InsertNamespace() and not decl.getQualifier()) {
4935 const auto* parent = methodDecl->getParent();
4936 outputFormatHelper.
Append(parent->getName(),
"::"sv);
4940 if(not isa<CXXConversionDecl>(decl)) {
4941 if(isa<CXXConstructorDecl>(decl) or isa<CXXDestructorDecl>(decl)) {
4943 if(isa<CXXDestructorDecl>(decl)) {
4944 outputFormatHelper.
Append(
'~');
4947 outputFormatHelper.
Append(
GetName(*methodDecl->getParent()));
4954 if(isFirstCxxMethodDecl and decl.isFunctionTemplateSpecialization()) {
4959 outputFormatHelper.
Append(
'(');
4963 if(cxxInheritedCtorDecl) {
4965 OutputFormatHelper::NameOnly::No,
4966 OutputFormatHelper::GenMissingParamName::Yes);
4970 const OutputFormatHelper::GenMissingParamName genMissingParamName{
4971 isLambdaStaticInvoker ? OutputFormatHelper::GenMissingParamName::Yes
4972 : OutputFormatHelper::GenMissingParamName::No};
4975 decl.parameters(), OutputFormatHelper::NameOnly::No, genMissingParamName);
4977 if(
GetInsightsOptions().UseShow2C and not decl.isVariadic() and decl.param_empty()) {
4978 outputFormatHelper.
Append(
"void"sv);
4982 if(decl.isVariadic()) {
4983 outputFormatHelper.
Append(
", ..."sv);
4986 outputFormatHelper.
Append(
')');
4988 if(not isa<CXXConstructorDecl>(decl) and not isa<CXXDestructorDecl>(decl)) {
4989 if(isa<CXXConversionDecl>(decl)) {
4990 const std::string typeName{TypeContainsSubType<PointerType, FunctionProtoType>(desugaredReturnType)
4992 :
GetName(desugaredReturnType)};
4999 mOutputFormatHelper.Append(outputFormatHelper);
5002 mOutputFormatHelper.Append(
GetConst(decl));
5005 if(methodDecl->isVolatile()) {
5009 if(methodDecl->hasAttr<FinalAttr>()) {
5014 switch(decl.getType()->getAs<FunctionProtoType>()->getRefQualifier()) {
5015 case RQ_None:
break;
5016 case RQ_LValue: mOutputFormatHelper.Append(
" &"sv);
break;
5017 case RQ_RValue: mOutputFormatHelper.Append(
" &&"sv);
break;
5024 InsertConceptConstraint(&decl);
5026 if(decl.isPureVirtual()) {
5027 mOutputFormatHelper.Append(
" = 0"sv);
5030 if(decl.isDeleted()) {
5032 if(
auto* delInfo = decl.getDefalutedOrDeletedInfo()) {
5033 WrapInParens([&]() { InsertArg(delInfo->getDeletedMessage()); }, AddSpaceAtTheEnd::No);
5035 mOutputFormatHelper.AppendSemiNewLine();
5038 }
else if(decl.isDefaulted()) {
5044 void CodeGenerator::InsertCurlysIfRequired(
const Stmt* stmt)
5046 const bool requiresCurlys{not isa<InitListExpr>(stmt) and not isa<ParenExpr>(stmt) and
5047 not isa<CXXDefaultInitExpr>(stmt)};
5049 if(requiresCurlys) {
5050 mOutputFormatHelper.Append(
'{');
5055 if(requiresCurlys) {
5056 mOutputFormatHelper.Append(
'}');
5061 void CodeGenerator::WrapInParensOrCurlys(
const BraceKind braceKind,
5063 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5065 if(BraceKind::Curlys == braceKind) {
5066 mOutputFormatHelper.Append(
'{');
5068 mOutputFormatHelper.Append(
'(');
5073 if(BraceKind::Curlys == braceKind) {
5074 mOutputFormatHelper.Append(
'}');
5076 mOutputFormatHelper.Append(
')');
5079 if(AddSpaceAtTheEnd::Yes == addSpaceAtTheEnd) {
5080 mOutputFormatHelper.Append(
' ');
5085 void CodeGenerator::WrapInCompoundIfNeeded(
const Stmt* stmt,
const AddNewLineAfter addNewLineAfter)
5087 const bool hasNoCompoundStmt = not(isa<CompoundStmt>(stmt) or isa<AttributedStmt>(stmt));
5089 if(hasNoCompoundStmt) {
5090 mOutputFormatHelper.OpenScope();
5093 if(not isa<NullStmt>(stmt)) {
5096 const bool isAttrWithCompound{[&] {
5097 auto* attrStmt = dyn_cast_or_null<AttributedStmt>(stmt);
5098 return attrStmt and isa<CompoundStmt>(attrStmt->getSubStmt());
5102 if(IsStmtRequiringSemi<IfStmt, CompoundStmt, NullStmt, WhileStmt, DoStmt>(stmt) and not isAttrWithCompound) {
5103 mOutputFormatHelper.AppendSemiNewLine();
5107 if(hasNoCompoundStmt) {
5108 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
5111 const bool addNewLine = (AddNewLineAfter::Yes == addNewLineAfter);
5112 if(addNewLine or (hasNoCompoundStmt and addNewLine)) {
5113 mOutputFormatHelper.AppendNewLine();
5114 }
else if(not addNewLine or (hasNoCompoundStmt and not addNewLine)) {
5115 mOutputFormatHelper.Append(
' ');
5120 void CodeGenerator::WrapInParens(
void_func_ref lambda,
const AddSpaceAtTheEnd addSpaceAtTheEnd)
5122 WrapInParensOrCurlys(BraceKind::Parens, lambda, addSpaceAtTheEnd);
5126 void CodeGenerator::WrapInParensIfNeeded(
bool needsParens,
5128 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5131 WrapInParensOrCurlys(BraceKind::Parens, lambda, addSpaceAtTheEnd);
5138 void CodeGenerator::WrapInCurliesIfNeeded(
bool needsParens,
5140 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5143 WrapInParensOrCurlys(BraceKind::Curlys, lambda, addSpaceAtTheEnd);
5150 void CodeGenerator::WrapInCurlys(
void_func_ref lambda,
const AddSpaceAtTheEnd addSpaceAtTheEnd)
5152 WrapInParensOrCurlys(BraceKind::Curlys, lambda, addSpaceAtTheEnd);
5156 void CodeGenerator::InsertArg(
const BindingDecl*)
5163 void StructuredBindingsCodeGenerator::InsertArg(
const BindingDecl* stmt)
5165 const auto* bindingStmt = stmt->getBinding();
5172 auto type = stmt->getType();
5176 if(
const auto* holdingVar = stmt->getHoldingVar()) {
5184 type = holdingVar->getType().getCanonicalType();
5186 bindingStmt = holdingVar->getAnyInitializer();
5188 }
else if(not type->isLValueReferenceType()) {
5189 type = stmt->getASTContext().getLValueReferenceType(type);
5192 InsertAttributes(stmt->attrs());
5194 mOutputFormatHelper.Append(
GetQualifiers(*dyn_cast_or_null<VarDecl>(stmt->getDecomposedDecl())),
5198 InsertArg(bindingStmt);
5200 mOutputFormatHelper.AppendSemiNewLine();
5204 void StructuredBindingsCodeGenerator::InsertDecompositionBindings(
const DecompositionDecl& decompositionDeclStmt)
5206 for(
const auto* bindingDecl : decompositionDeclStmt.bindings()) {
5207 InsertArg(bindingDecl);
5212 void StructuredBindingsCodeGenerator::InsertArg(
const DeclRefExpr* stmt)
5214 const auto name =
GetName(*stmt);
5216 mOutputFormatHelper.Append(name);
5219 mOutputFormatHelper.Append(mVarName);
5221 InsertTemplateArgs(*stmt);
5226 void LambdaCodeGenerator::InsertArg(
const CXXThisExpr* stmt)
5230 if(mCapturedThisAsCopy) {
#define LAMBDA_SCOPE_HELPER(type)
Convenience macro to create a LambdaScopeHandler on the stack.
#define CONDITIONAL_LAMBDA_SCOPE_HELPER(type, cond)
The lambda scope helper is only created if cond is true.
InsightsOptions & GetInsightsOptionsRW()
const CompilerInstance & GetGlobalCI()
Get access to the CompilerInstance.
const ASTContext & GetGlobalAST()
Get access to the ASTContext.
const InsightsOptions & GetInsightsOptions()
Get the global C++ Insights options.
#define SCOPE_HELPER(d)
Helper to create a ScopeHandler on the stack which adds the current Decl to it and removes it once th...
constexpr std::string_view kwTemplate
constexpr std::string_view kwNull
constexpr std::string_view kwCommentStart
constexpr std::string_view kwRequiresSpace
constexpr std::string_view kwStaticAssert
constexpr std::string_view kwCoAwaitSpace
constexpr std::string_view kwReturn
constexpr std::string_view kwReinterpretCast
constexpr std::string_view kwNamespaceSpace
constexpr std::string_view kwContinue
constexpr std::string_view kwSpaceConstEvalSpace
constexpr std::string_view cxaStart
constexpr std::string_view kwCCommentEndSpace
constexpr std::string_view kwInlineSpace
constexpr std::string_view kwMutableSpace
constexpr std::string_view kwUsingSpace
constexpr std::string_view kwDelete
constexpr std::string_view kwConstExprSpace
constexpr std::string_view kwTemplateSpace
constexpr std::string_view kwCoReturnSpace
constexpr std::string_view kwCoYieldSpace
constexpr std::string_view kwSpaceConstExpr
constexpr std::string_view kwSpaceCCommentEndSpace
constexpr std::string_view kwNamespace
constexpr std::string_view kwCaseSpace
constexpr std::string_view kwSizeof
constexpr std::string_view kwUnionSpace
constexpr std::string_view kwSpaceCCommentEnd
constexpr std::string_view kwEnumSpace
constexpr std::string_view kwElipsisSpace
constexpr std::string_view kwClassSpace
constexpr std::string_view kwTypeId
constexpr std::string_view kwConstEvalSpace
constexpr std::string_view kwSpaceEqualsDefault
constexpr std::string_view kwThis
constexpr std::string_view kwSpaceVolatile
constexpr std::string_view kwStructSpace
constexpr std::string_view functionPointerPrefix
constexpr std::string_view kwStaticCast
constexpr std::string_view kwElipsis
constexpr std::string_view kwOperator
constexpr std::string_view kwSpaceFinal
constexpr std::string_view kwNoexcept
constexpr std::string_view kwCCommentStartSpace
constexpr std::string_view kwTypeNameSpace
constexpr std::string_view kwExplicitSpace
constexpr std::string_view kwSwitch
constexpr std::string_view kwFriendSpace
constexpr std::string_view kwOperatorSpace
constexpr std::string_view kwInternalThis
constexpr std::string_view kwCppCommentStartSpace
constexpr std::string_view kwStaticSpace
constexpr std::string_view kwSpaceNoexcept
constexpr std::string_view kwSpaceEqualsDelete
constexpr std::string_view kwAlignof
constexpr std::string_view kwRequires
constexpr std::string_view kwNullptr
constexpr std::string_view kwFalse
constexpr std::string_view kwTrySpace
constexpr std::string_view kwExplicit
constexpr std::string_view hlpArrow
constexpr std::string_view hlpAssing
constexpr std::string_view kwBreak
constexpr std::string_view kwDoSpace
constexpr std::string_view memberVariablePointerPrefix
constexpr std::string_view kwWhile
constexpr std::string_view cxaAtExit
constexpr std::string_view kwVirtualSpace
constexpr std::string_view kwGotoSpace
constexpr std::string_view kwConceptSpace
#define RETURN_IF(cond)
! A helper inspired by https://github.com/Microsoft/wil/wiki/Error-handling-helpers
llvm::function_ref< void()> void_func_ref
void push(TStackListEntry &entry) noexcept
ArrayInitCodeGenerator(OutputFormatHelper &_outputFormatHelper, const uint64_t index)
void InsertArg(const ArrayInitIndexExpr *) override
Find a DeclRefExpr belonging to a DecompositionDecl.
bool Find(const Stmt *stmt)
BindingDeclFinder()=default
void VisitStmt(const Stmt *stmt)
void VisitDeclRefExpr(const DeclRefExpr *expr)
static CfrontVtableData & VtableData()
void setInsertName(bool b)
OutputFormatHelper & buffer()
LambdaScopeHandler(LambdaStackType &stack, OutputFormatHelper &outputFormatHelper, const LambdaCallerType lambdaCallerType)
More or less the heart of C++ Insights.
void InsertFunctionNameWithReturnType(const FunctionDecl &decl, const CXXConstructorDecl *cxxInheritedCtorDecl=nullptr)
Insert the code for a FunctionDecl.
void WrapInParensIfNeeded(bool needsParens, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
void WrapInCompoundIfNeeded(const Stmt *stmt, const AddNewLineAfter addNewLineAfter)
static std::map< std::string, bool > mSeenDecls
void InsertQualifierAndNameWithTemplateArgs(const DeclarationName &declName, const auto *stmt)
void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
static std::string FillConstantArray(const ConstantArrayType *ct, const std::string &value, const uint64_t startAt)
virtual void InsertArg(const Decl *stmt)
void InsertTemplateSpecializationHeader(const Decl &)
Insert template<> to introduce a template specialization.
virtual bool InsertVarDecl(const VarDecl *)
const LambdaExpr * mLambdaExpr
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaStackType &lambdaStack, LambdaInInitCapture lambdaInitCapture, ProcessingPrimaryTemplate processingPrimaryTemplate)
! We do not want to transform a primary template which contains a Coroutine.
void InsertInstantiationPoint(const SourceManager &sm, const SourceLocation &instLoc, std::string_view text={})
Inserts the instantiation point of a template.
ProcessingPrimaryTemplate mProcessingPrimaryTemplate
void InsertTemplateArgs(const T &t)
std::optional< size_t > mCurrentVarDeclPos
OutputFormatHelper * mOutputFormatHelperOutside
Helper output buffer for std::initializer_list expansion.
void WrapInCurliesIfNeeded(bool needsParens, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
void InsertTemplateGuardEnd(const FunctionDecl *stmt)
static std::string GetValueOfValueInit(const QualType &t)
void LifetimeAddExtended(const VarDecl *, const ValueDecl *)
void HandleLocalStaticNonTrivialClass(const VarDecl *stmt)
Show what is behind a local static variable.
std::optional< size_t > mCurrentCallExprPos
void InsertTemplateParameters(const TemplateParameterList &list, const TemplateParamsOnly templateParamsOnly=TemplateParamsOnly::No)
! Skip template, type constraints and class/typename.
void InsertIfOrSwitchInitVariables(same_as_any_of< const IfStmt, const SwitchStmt > auto *stmt)
virtual bool InsertSemi()
void UpdateCurrentPos(std::optional< size_t > &pos)
bool InsertLambdaStaticInvoker(const CXXMethodDecl *cxxMethodDecl)
void InsertTemplateGuardBegin(const FunctionDecl *stmt)
LambdaStackType & mLambdaStack
void InsertConceptConstraint(const llvm::SmallVectorImpl< const Expr * > &constraints, const InsertInline insertInline)
virtual bool InsertComma()
virtual bool InsertNamespace() const
void ForEachArg(const auto &arguments, auto &&lambda)
void InsertQualifierAndName(const DeclarationName &declName, const NestedNameSpecifier *qualifier, const bool hasTemplateKeyword)
NoEmptyInitList mNoEmptyInitList
At least in case if a requires-clause containing T{} we don't want to get T{{}}.
friend class CodeGeneratorVariant
void InsertMethodBody(const FunctionDecl *stmt, const size_t posBeforeFunc)
bool mRequiresImplicitReturnZero
Track whether this is a function with an imlpicit return 0.
static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS
void WrapInParensOrCurlys(const BraceKind curlys, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
std::optional< size_t > mCurrentFieldPos
void InsertTemplateArg(const TemplateArgument &arg)
void InsertSuffix(const QualType &type)
void InsertAttributes(const Decl *)
void StartLifetimeScope()
virtual bool SkipSpaceAfterVarDecl()
void InsertCurlysIfRequired(const Stmt *stmt)
Check whether or not this statement will add curlys or parentheses and add them only if required.
OutputFormatHelper & mOutputFormatHelper
LifetimeTracker mLifeTimeTracker
void InsertTemplateArgsObjectParam(const ArrayRef< TemplateArgument > &array)
void ParseDeclContext(const DeclContext *Ctx)
A special container which creates either a CodeGenerator or a CfrontCodeGenerator depending on the co...
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
A special code generator for Lambda init captures which use std::move.
LambdaInitCaptureCodeGenerator(OutputFormatHelper &outputFormatHelper, LambdaStackType &lambdaStack, std::string_view varName)
void InsertArg(const DeclRefExpr *stmt) override
void InsertArg(const LambdaExpr *stmt) override
bool EndScope(OutputFormatHelper &ofm, bool clear)
void Add(const VarDecl *decl)
void AddExtended(const VarDecl *decl, const ValueDecl *extending)
void StartScope(bool funcStart)
! Find a LambdaExpr inside a Decltype
static std::string RemoveCurrentScope(std::string name)
Remove the current scope from a string.
Specialization for ::llvm::raw_string_ostream with an internal std::string buffer.
void Print(const TemplateArgument &)
StructuredBindingsCodeGenerator(OutputFormatHelper &_outputFormatHelper, std::string &&varName)
virtual bool ShowXValueCasts() const override
Show casts to xvalues independent from the show all casts option.
Find a DeclRefExpr belonging to a DecompositionDecl.
void VisitStmt(Stmt *stmt)
TemporaryDeclFinder(CodeGenerator &_codeGenerator, const Stmt *stmt, bool inspectReturn=false)
void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *expr)
void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *stmt)
Handle using statements which pull functions ore members from a base class into the class.
bool InsertNamespace() const override
void InsertArg(const FieldDecl *stmt) override
UsingCodeGenerator(OutputFormatHelper &_outputFormatHelper)
void InsertArg(const CXXMethodDecl *stmt) override
void InsertArg(const CXXRecordDecl *) override
void InsertArg(const TypedefDecl *) override
BinaryOperator * Equal(Expr *var, Expr *assignExpr)
DeclStmt * mkDeclStmt(Dcls... dcls)
DeclRefExpr * mkDeclRefExpr(const ValueDecl *vd)
QualType Typedef(std::string_view name, QualType underlayingType)
CXXNewExpr * New(ArrayRef< Expr * > placementArgs, const Expr *expr, QualType t)
CallExpr * Call(const FunctionDecl *fd, ArrayRef< Expr * > params)
UnaryOperator * Ref(const Expr *e)
VarDecl * Variable(std::string_view name, QualType type, DeclContext *dc)
SmallVector< Expr *, 5 > ArgsToExprVector(const Expr *expr)
ReturnStmt * Return(Expr *stmt)
Stmt * Comment(std::string_view comment)
IfStmt * If(const Expr *condition, ArrayRef< Stmt * > bodyStmts)
BinaryOperator * And(VarDecl *lhs, Expr *rhs)
GotoStmt * Goto(std::string_view labelName)
InitListExpr * InitList(ArrayRef< Expr * > initExprs, QualType t)
CXXCatchStmt * Catch(ArrayRef< Stmt * > body)
CXXThrowExpr * Throw(const Expr *expr)
void ReplaceNode(Stmt *parent, Stmt *oldNode, Stmt *newNode)
UnaryExprOrTypeTraitExpr * Sizeof(QualType toType)
static CallExpr * CallConstructor(QualType ctorType, DeclRefExpr *lhsDeclRef, Expr *lhsMemberExpr, ArrayRef< Expr * > callParams, DoCast doCast, AsReference asReference)
LabelStmt * Label(std::string_view name)
CXXBoolLiteralExpr * Bool(bool b)
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)
CXXStaticCastExpr * StaticCast(QualType toType, const Expr *toExpr, bool makePointer)
BinaryOperator * Assign(const VarDecl *var, Expr *assignExpr)
CXXTryStmt * Try(const Stmt *tryBody, CXXCatchStmt *catchAllBody)
CallExpr * CallDestructor(const VarDecl *varDecl)
void StrCat(std::string &ret, const auto &... args)
static std::string GetName(QualType t, const Unqualified unqualified=Unqualified::No, const InsightsSuppressScope supressScope=InsightsSuppressScope::No)
std::string ConvertToBoolString(bool b)
Convert a boolean value to a string representation of "true" or "false".
static std::string AccessToStringWithColon(const AccessSpecifier &access)
void InsertBefore(std::string &source, const std::string_view &find, const std::string_view &replace)
static void PushGlobalVariableDtor(const Expr *callExpr)
uint64_t GetSize(const ConstantArrayType *arrayType)
std::string GetLambdaName(const CXXRecordDecl &lambda)
@ HeaderException
Track whether there was a noexcept transformation requireing the exception header.
bool Contains(const std::string_view source, const std::string_view search)
BUILD_OPT_AND(IsPointer, QualType)
std::string BuildRetTypeName(const Decl &decl)
static void ToDo(std::string_view name, OutputFormatHelper &outputFormatHelper, std::source_location loc)
void DPrint([[maybe_unused]] const char *fmt, [[maybe_unused]] const auto &... args)
Debug print which is disabled in release-mode.
const std::string GetNoExcept(const FunctionDecl &decl)
const SourceManager & GetSM(const Decl &decl)
std::string GetPlainName(const DeclRefExpr &DRE)
static std::string_view ArrowOrDot(bool isArrow)
std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword)
void PushVtableEntry(const CXXRecordDecl *record, const CXXRecordDecl *recordB, VarDecl *decl)
int GetGlobalVtablePos(const CXXRecordDecl *record, const CXXRecordDecl *recordB)
static T ValueOr(bool b, T val, T el)
void Error(const char *fmt, const auto &... args)
Log an error.
Once< false > OnceFalse
Returns false only once, following checks return true.
static auto & GetRecordLayout(const RecordDecl *recordDecl)
std::string MakeLineColumnName(const SourceManager &sm, const SourceLocation &loc, const std::string_view &prefix)
static std::string_view GetCastName(const CastKind castKind, bool constnessChange=false)
static std::string GetTypeConstraintAsString(const TypeConstraint *typeConstraint)
static bool IsStmtRequiringSemi(const Stmt *stmt)
QualType GetType(QualType t)
In Cfront mode we transform references to pointers.
std::string GetName(const NamedDecl &nd, const QualifiedName qualifiedName)
const LangOptions & GetLangOpts(const Decl &decl)
std::string EmitGlobalVariableCtors()
static std::string_view EllipsisSpace(bool b)
std::string BuildInternalVarName(const std::string_view &varName)
auto GetSpaces(std::string::size_type offset)
static void PushGlobalVariable(const Expr *callExpr)
static std::string FormatVarTemplateSpecializationDecl(const Decl *decl, std::string &&defaultName)
static std::string GetStorageClassAsStringWithSpace(const StorageClass &sc)
static SmallVector< Expr *, 10 > globalVarDtors
static std::string_view GetTagDeclTypeName(const TagDecl &decl)
const std::string_view GetConst(const FunctionDecl &decl)
BUILD_OPT_AND_O(CanonicalType, const InitListExpr &, QualType)
static bool IsConstQualifiedType(QualType type)
std::string GetTemporaryName(const Expr &tmp)
std::string BuildTemplateParamObjectName(std::string name)
static std::string GetQualifiers(const VarDecl &vd)
bool IsReferenceType(const ValueDecl *decl)
static T ValueOrDefault(bool b, T v)
void AppendTemplateTypeParamName(OutputFormatHelper &ofm, const TemplateTypeParmDecl *decl, const bool isParameter, const TemplateTypeParmType *type)
static std::string_view Ellipsis(bool b)
Once< true > OnceTrue
Returns true only once, following checks return false.
std::string GetDeclContext(const DeclContext *ctx, WithTemplateParameters withTemplateParameters)
const QualType GetDesugarType(const QualType &QT)
Remove decltype from a QualType, if possible.
static SmallVector< Expr *, 10 > globalVarCtors
static std::string GetUnqualifiedScopelessName(const Type *type, const InsightsSuppressScope supressScope)
bool IsStaticStorageClass(const CXXMethodDecl *md)
static bool IsPrimaryTemplatePackExpansionExpr(const ParenListExpr *stmt)
void EnableGlobalInsert(GlobalInserts idx)
std::string GetNestedName(const NestedNameSpecifier *nns, const IgnoreNamespace ignoreNamespace)
static std::optional< std::pair< QualType, APValue > > EvaluateNTTPAsConstantExpr(const Expr *expr)
Evaluates a potential NTTP as a constant expression.
static SmallVector< std::pair< std::pair< const CXXRecordDecl *, const CXXRecordDecl * >, VarDecl * >, 10 > gVtables
void for_each(T start, T end, TFunc &&func)
static std::string_view GetStorageClassAsString(const StorageClass &sc)
static std::optional< std::string > GetFieldDeclNameForLambda(const FieldDecl &fieldDecl, const CXXRecordDecl &cxxRecordDecl)
std::string GetTypeNameAsParameter(const QualType &t, std::string_view varName, const Unqualified unqualified)
static bool IsTrivialStaticClassVarDecl(const DeclRefExpr &declRefExpr)
std::string StrCat(const auto &... args)
QualType GetDesugarReturnType(const FunctionDecl &FD)
VarDecl * VtblArrayVar(int size)
! A helper type to have a container for ArrayRef
void AddBodyStmts(Stmt *body)
Handy helper to avoid longish comparisons.
constexpr bool any_of(const auto &... ts) const