217 if(isa<VarDecl>(stmt->getDecl())) {
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 if(stmt->getDependence() != ExprDependenceScope::ExprDependence::None) {
801 InsertArg(stmt->getLHS());
803 clang::ExprResult res = stmt->getLHS();
807 if(const auto resultingType = GetGlobalCI().getSema().PrepareScalarCast(res, stmt->getComputationLHSType());
808 resultingType != CK_NoOp) {
809 const QualType castDestType = stmt->getComputationLHSType();
810 FormatCast(kwStaticCast, castDestType, stmt->getLHS(), resultingType);
812 InsertArg(stmt->getLHS());
818 " "sv, BinaryOperator::getOpcodeStr(BinaryOperator::getOpForCompoundAssignment(stmt->getOpcode())),
" "sv);
820 const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
840 return VarDecl::getStorageClassSpecifierString(sc);
851 if(not ret.empty()) {
861 std::string qualifiers{};
863 if(vd.isInline() or vd.isInlineSpecified()) {
869 if(vd.isConstexpr()) {
879 std::string name{std::move(defaultName)};
881 if(
const auto* tvd = dyn_cast_or_null<VarTemplateSpecializationDecl>(decl)) {
885 codeGenerator->InsertTemplateArgs(tvd->getTemplateArgs());
887 name += outputFormatHelper;
904 if(isa<DecompositionDecl>(expr->getDecl())) {
911 for(
const auto* child : stmt->children()) {
936 bool mHaveTemporary{};
938 std::string mTempName{};
939 std::vector<VarDecl*> mDecls{};
943 : codeGenerator{_codeGenerator}
944 , mPrevStmt{const_cast<
Stmt*>(stmt)}
950 for(
auto d : mDecls) {
956 if(
auto* expr = dyn_cast_or_null<CXXConstructExpr>(stmt)) {
961 auto* vd =
Variable(mTempName, expr->getType(), dummy->getDeclContext());
962 dummy->getDeclContext()->addDecl(vd);
963 vd->setInit(
const_cast<CXXConstructExpr*
>(expr));
964 vd->setStorageClass(SC_None);
968 auto* vd = ImplicitParamDecl::Create(
const_cast<ASTContext&
>(ctx),
969 ctx.getTranslationUnitDecl(),
971 &ctx.Idents.get(mTempName),
973 ImplicitParamKind::Other);
980 }
else if(
auto* expr = dyn_cast_or_null<InitListExpr>(stmt)) {
982 auto* vd =
Variable(mTempName, expr->getType());
983 vd->setInit(
const_cast<InitListExpr*
>(expr));
996 bool Found()
const {
return mFound; }
998 std::string
Name()
const {
return mTempName; }
1005 auto* vd =
Variable(mTempName, expr->getType());
1011 auto* ctorConstructExpr = CXXConstructExpr::Create(
GetGlobalAST(),
1013 expr->getBeginLoc(),
1014 expr->getConstructor(),
1016 {expr->getArgs(), expr->getNumArgs()},
1017 expr->hadMultipleCandidates(),
1018 expr->isListInitialization(),
1019 expr->isStdInitListInitialization(),
1020 expr->requiresZeroInitialization(),
1021 expr->getConstructionKind(),
1022 expr->getParenOrBraceRange());
1024 vd->setInit(ctorConstructExpr);
1030 mDecls.push_back(vd);
1034 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr* stmt)
1038 const auto name =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"temp"sv);
1041 auto* vd =
Variable(name, stmt->getType());
1055 vd->setInit(stmt->getSubExpr());
1060 if(SD_FullExpression == stmt->getStorageDuration() and not mHaveTemporary) {
1062 mHaveTemporary =
true;
1063 }
else if(
const auto* extending = stmt->getExtendingDecl()) {
1067 mDecls.push_back(vd);
1072 auto* tmp = mPrevStmt;
1075 for(
auto* child : stmt->children()) {
1091 static SmallVector<std::pair<std::pair<const CXXRecordDecl*, const CXXRecordDecl*>, VarDecl*>, 10>
1099 auto iter = std::ranges::find_if(
1100 gVtables, [&](
const auto& e) {
return (e.first.first == record) and (e.first.second == recordB); });
1103 iter = std::ranges::find_if(
gVtables, [&](
const auto& e) {
return e.first.first == record; });
1106 return std::distance(
gVtables.begin(), iter);
1110void PushVtableEntry(
const CXXRecordDecl* record,
const CXXRecordDecl* recordB, VarDecl* decl)
1112 gVtables.push_back({{record, recordB}, decl});
1141 ofm.AppendNewLine();
1145 SmallVector<Expr*, 16> mInitExprs{};
1152 ofm.AppendNewLine();
1156 vtable->setInit(
InitList(mInitExprs, vtable->getType()));
1158 cg->InsertArg(vtable);
1160 ofm.AppendNewLine();
1163 cg->InsertArg(cxaStartFun);
1174 ofm.AppendNewLine();
1175 cg->InsertArg(cxaAtExitFun);
1177 return ofm.GetString();
1202 return stmt and stmt->getNumExprs() and isa_and_nonnull<PackExpansionExpr>(stmt->getExpr(0)) and
1203 stmt->getType().isNull();
1212 for(
const auto* decl : stmt->decls()) {
1224 pp.adjustForCPlusPlus();
1228 ::llvm::raw_string_ostream stream{init};
1229 param.printAsInit(stream, pp);
1237 "static constexpr ",
GetName(param.getType().getUnqualifiedType()),
" ", varName, init);
1245 for(
const auto& arg : array) {
1246 if(TemplateArgument::Declaration != arg.getKind()) {
1248 }
else if(
const auto decl = dyn_cast_or_null<TemplateParamObjectDecl>(arg.getAsDecl())) {
1257 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(&decl)) {
1258 if(
const auto* specArgs = fd->getTemplateSpecializationArgs()) {
1261 }
else if(
const auto* vd = dyn_cast_or_null<VarTemplateSpecializationDecl>(&decl)) {
1263 }
else if(
const auto* clsTemplateSpe = dyn_cast_or_null<ClassTemplateSpecializationDecl>(&decl)) {
1273 if(
auto* init = stmt->getInit();
1275 (not(isa<CallExpr>(init) or
1276 (isa<ExprWithCleanups>(init) and
1277 (isa<CallExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr()) or
1278 isa<MaterializeTemporaryExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr())))))) {
1286 if(BindingDeclFinder isBindingDecl{}; isBindingDecl.Find(stmt->getInit())) {
1293 TemporaryDeclFinder temporaryFinder{*
this, stmt->getInit()};
1301 const bool needsGuard = stmt->isOutOfLine() and isTemplateInstantiation(stmt->getTemplateSpecializationKind());
1305 if(stmt->isOutOfLine()) {
1306 if(
const auto* recordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
1307 if(
const auto* classTmpl = recordDecl->getDescribedClassTemplate()) {
1313 if(isa<VarTemplateSpecializationDecl>(stmt)) {
1315 }
else if(needsGuard) {
1329 const bool isMemberPointer{isa<MemberPointerType>(desugaredType.getTypePtrOrNull())};
1330 if(desugaredType->isFunctionPointerType() or isMemberPointer) {
1331 const auto lineNo =
GetSM(*stmt).getSpellingLineNumber(stmt->getSourceRange().getBegin());
1333 const auto funcPtrName{
StrCat(ptrPrefix, lineNo)};
1341 const auto scope = [&] {
1342 if(
const auto* ctx = stmt->getDeclContext(); stmt->getLexicalDeclContext() != ctx) {
1343 OutputFormatHelper scopeOfm{};
1344 scopeOfm.Append(
GetDeclContext(ctx, WithTemplateParameters::Yes));
1349 return std::string{};
1358 const std::string_view pointer = [&]() {
1363 if(stmt->getType()->isAnyPointerType()) {
1372 if(
const auto* init = stmt->getInit()) {
1373 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init);
1388 if(stmt->hasGlobalStorage()) {
1389 if(ctorExpr->getConstructor()->isDefaultConstructor() and
1390 ctorExpr->getConstructor()->getParent()->hasTrivialDefaultConstructor()) {
1401 stmt->getType(), stmt,
ArgsToExprVector(ctorExpr), DoCast::No, AsReference::Yes);
1418 if(MyOptional<const InitListExpr*> initList{dyn_cast_or_null<InitListExpr>(init)};
1420 initList.and_then(CanonicalType).and_then(Isa<RecordType>).and_not(IsPointer).and_then(IsPOD) and
1421 not isa<ArrayType>(stmt->getType())) {
1426 if(stmt->hasGlobalStorage()) {
1435 initList.and_then(CanonicalType)
1436 .and_then(Isa<RecordType>)
1439 (0 == initList.value()->getNumInits()))) {
1443 if(not(ctorExpr and ctorExpr->getConstructor()->isDefaultConstructor() and
1444 ctorExpr->getConstructor()->getParent()->hasTrivialDefaultConstructor())) {
1446 const bool isPrimaryTemplatePackExpansionExpr{
1449 if(not isa<CXXParenListInitExpr>(init) and not isPrimaryTemplatePackExpansionExpr) {
1455 stmt->getType()->isRValueReferenceType()) {
1457 if(GetInsightsOptions().UseShow2C) {
1458 mOutputFormatHelper.Append(
"&");
1471 (stmt->getStorageDuration() == SD_Static) and
1472 (stmt->getDeclContext()->isNamespace() or
1473 (is{stmt->getStorageClass()}.any_of(SC_Static, SC_Extern)))) {
1477 if(stmt->isNRVOVariable()) {
1486 if(
const auto* decompDecl = dyn_cast_or_null<DecompositionDecl>(stmt)) {
1489 codeGenerator.InsertDecompositionBindings(*decompDecl);
1494 mOutputFormatHelper.InsertEndIfTemplateGuard();
1501 if(not(cxxMethodDecl and cxxMethodDecl->isLambdaStaticInvoker())) {
1514 if(not cxxMethodDecl->getReturnType()->isVoidType()) {
1520 if(cxxMethodDecl->isFunctionTemplateSpecialization()) {
1524 if(cxxMethodDecl->isTemplated()) {
1525 if(cxxMethodDecl->getDescribedTemplate()) {
1527 TemplateParamsOnly::Yes);
1536 OutputFormatHelper::NameOnly::Yes,
1537 OutputFormatHelper::GenMissingParamName::Yes);
1552 const SourceLocation& instLoc,
1553 std::string_view text)
1555 const auto lineNo = sm.getSpellingLineNumber(instLoc);
1556 const auto& fileId = sm.getFileID(instLoc);
1557 if(
const auto file = sm.getFileEntryRefForID(fileId)) {
1558 const auto fileWithDirName = file->getName();
1559 const auto fileName = llvm::sys::path::filename(fileWithDirName);
1562 text =
"First instantiated from: "sv;
1572 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1581 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1604 if(isa<CoyieldExpr>(stmt)) {
1611 if(
const auto* matTemp = dyn_cast_or_null<MaterializeTemporaryExpr>(stmt->getCommonExpr())) {
1612 const auto* temporary = matTemp->getSubExpr();
1614 if(
const auto* memExpr = dyn_cast_or_null<CXXMemberCallExpr>(temporary)) {
1615 ForEachArg(memExpr->arguments(), [&](
const auto& arg) { InsertArg(arg); });
1621 }
else if(
const auto* unaryexpr = dyn_cast_or_null<UnaryOperator>(stmt->getOperand())) {
1622 if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(unaryexpr->getSubExpr())) {
1638 auto IsPrimaryTemplate = [&] {
1640 if(
const auto* cxxMethod = dyn_cast_or_null<CXXMethodDecl>(stmt)) {
1641 if(
const auto* tmpl = cxxMethod->getParent()->getDescribedClassTemplate();
1642 tmpl and not isa<ClassTemplateSpecializationDecl>(cxxMethod->getParent())) {
1647 return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind()) or
1651 if(stmt->doesThisDeclarationHaveABody()) {
1656 if(
const auto* corBody = dyn_cast_or_null<CoroutineBodyStmt>(stmt->getBody());
1657 (
nullptr != corBody) and not IsPrimaryTemplate() and
GetInsightsOptions().ShowCoroutineTransformation) {
1660 codeGenerator.InsertCoroutine(*stmt, corBody);
1662 const auto exSpec = stmt->getExceptionSpecType();
1663 const bool showNoexcept =
1667 if(stmt->hasImplicitReturnZero()) {
1669 [](
const Stmt* e) { return isa<ReturnStmt>(e); });
1672 const auto* body = stmt->getBody();
1681 for(
const auto* param : stmt->parameters()) {
1682 auto paramType = param->getType();
1683 const bool isPassByValue{not paramType->isPointerType() and not paramType->isReferenceType()};
1684 if(
const auto* rd = paramType->getAsRecordDecl(); rd and isPassByValue) {
1708 dt.TraverseType(stmt->getReturnType());
1711 for(
const auto& param : stmt->parameters()) {
1712 P0315Visitor dt{*
this};
1713 dt.TraverseType(param->getType());
1717 if(
const auto* deductionGuide = dyn_cast_or_null<CXXDeductionGuideDecl>(stmt)) {
1719 }
else if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
1724 RETURN_IF(isa<CXXConversionDecl>(stmt) and not stmt->hasBody());
1742 if(typeConstraint) {
1744 sstream.
Print(*typeConstraint);
1746 return sstream.str();
1770 expr = expr->IgnoreParenImpCasts();
1773 if(Expr::EvalResult evalResult{};
1774 isa<CXXFunctionalCastExpr>(expr) and
1775 expr->EvaluateAsConstantExpr(evalResult,
GetGlobalAST(), ConstantExprKind::Normal)) {
1776 return std::pair<QualType, APValue>{expr->getType(), evalResult.Val};
1784 const TemplateParamsOnly templateParamsOnly)
1786 const bool full{TemplateParamsOnly::No == templateParamsOnly};
1789 for(
const auto* param : list) {
1790 if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param);
1791 nonTmplParam and nonTmplParam->hasDefaultArgument()) {
1794 auto* init =
GetGlobalAST().getTemplateParamObjectDecl(val->first, val->second);
1806 for(
OnceFalse needsComma{};
const auto* param : list) {
1809 const auto& typeName =
GetName(*param);
1811 if(
const auto* tt = dyn_cast_or_null<TemplateTypeParmDecl>(param)) {
1813 if(tt->wasDeclaredWithTypename()) {
1815 }
else if(not tt->hasTypeConstraint()) {
1822 if(0 == typeName.size() or tt->isImplicit() ) {
1827 not typeConstraint.empty()) {
1836 if(tt->hasDefaultArgument() and not tt->defaultArgumentWasInherited()) {
1837 const auto& defaultArg = tt->getDefaultArgument();
1839 if(
const auto decltypeType = dyn_cast_or_null<DecltypeType>(defaultArg.getArgument().getAsType())) {
1842 InsertArg(decltypeType->getUnderlyingExpr());
1850 }
else if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param)) {
1852 if(
const auto nttpType = nonTmplParam->getType();
1853 nttpType->isFunctionPointerType() or nttpType->isMemberFunctionPointerType()) {
1858 GetName(nttpType),
" "sv,
Ellipsis(nonTmplParam->isParameterPack()), typeName);
1861 if(nonTmplParam->hasDefaultArgument()) {
1868 }
else if(
const auto* tmplTmplParam = dyn_cast_or_null<TemplateTemplateParmDecl>(param)) {
1873 if(tmplTmplParam->hasDefaultArgument()) {
1900 SmallVector<const ClassTemplateSpecializationDecl*, 10> specializations{};
1903 for(
const auto* spec : stmt->specializations()) {
1906 if(TSK_ImplicitInstantiation == spec->getSpecializationKind()) {
1907 specializations.push_back(spec);
1912 ranges::sort(specializations,
1913 [](
const ClassTemplateSpecializationDecl* a,
const ClassTemplateSpecializationDecl* b) {
1914 return a->getPointOfInstantiation() < b->getPointOfInstantiation();
1917 for(
const auto* spec : specializations) {
1925 for(
OnceFalse needsComma{};
const auto& expr : stmt->children()) {
1945 OnceFalse needsComma{uint64_t{0} != startAt};
1946 for_each(startAt, size, [&](
auto) {
1947 ret.AppendComma(needsComma);
1952 return ret.GetString();
1963 ((stmt->getNumInits() > 1) or stmt->getArrayFiller() or
1964 ((0 < stmt->getNumInits()) and isa<ImplicitValueInitExpr>(stmt->getInit(0))))),
1966 mOutputFormatHelper.IncreaseIndent();
1968 ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); });
1971 if(stmt->getType().getCanonicalType()->isScalarType()) {
1982 if(
const auto* filler = stmt->getArrayFiller()) {
1983 OutputFormatHelper ofm{};
1988 dyn_cast_or_null<ConstantArrayType>(stmt->getType().getTypePtrOrNull()),
1990 stmt->getNumInits());
1996 mOutputFormatHelper.DecreaseIndent();
2002 const auto* subExpr = stmt->getExpr();
2012 if(stmt->isArrayForm()) {
2028 dt.TraverseType(stmt->getType());
2042 if(
const auto& arguments = stmt->arguments(); not arguments.empty()) {
2043 ForEachArg(stmt->arguments(), [&](
const auto& arg) { InsertArg(arg); });
2071 if(stmt->getNumTemplateArgs()) {
2086 auto operatorStr = BinaryOperator::getOpcodeStr(stmt->getOperator());
2090 const auto* init = stmt->getInit();
2092 if(stmt->isLeftFold()) {
2095 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2103 if(stmt->isRightFold()) {
2117 if(stmt->isFullySubstituted()) {
2118 const auto* constExpr = dyn_cast_or_null<ConstantExpr>(stmt->getIndexExpr());
2121 constExpr->getAPValueResult().getInt());
2134 const auto& constructorDecl = *stmt->getConstructor();
2139 OutputFormatHelper::NameOnly::Yes,
2140 OutputFormatHelper::GenMissingParamName::Yes);
2183 StringRef opCodeName = UnaryOperator::getOpcodeStr(stmt->getOpcode());
2184 const bool insertBefore{not stmt->isPostfix()};
2192 if(not insertBefore) {
2200 StringStream stream{};
2201 stream.Print(*stmt);
2209 Error(stmt,
"ArrayInitIndexExpr should not be reached in CodeGenerator");
2215 if((not
GetInsightsOptions().UseAltArraySubscriptionSyntax) or stmt->getLHS()->isLValue()) {
2236 const uint64_t size = stmt->getArraySize().getZExtValue();
2240 codeGenerator.
InsertArg(stmt->getSubExpr());
2257 if(insideDecltype) {
2265 if(
const auto* declRefExpr = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts())) {
2266 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(declRefExpr->getDecl())) {
2267 if((not declRefExpr->getNumTemplateArgs() and
GetInsightsOptions().ShowAllCallExprTemplateParameters) or
2268 isa<UserDefinedLiteral>(stmt)) {
2275 auto* funcDecl = dyn_cast_or_null<FunctionDecl>(stmt->getCalleeDecl());
2278 ForEachArg(stmt->arguments(), [&](
const auto* arg) {
2281 if(const auto* tmpExpr = dyn_cast_or_null<CXXBindTemporaryExpr>(arg)) {
2282 if(const auto* tmp = dyn_cast_or_null<CXXTemporaryObjectExpr>(tmpExpr->getSubExpr())) {
2283 if(GetInsightsOptions().UseShow2C) {
2288 } else if(GetInsightsOptions().ShowLifetime) {
2289 mOutputFormatHelper.Append(GetName(*tmp));
2295 if(
GetInsightsOptions().UseShow2C and funcDecl and (funcDecl->getNumParams() >= parmIdx) and
2297 if(auto* unop = dyn_cast_or_null<UnaryOperator>(arg); not unop or (unop->getOpcode() != UO_AddrOf)) {
2306 if(insideDecltype) {
2307 mLambdaStack.back().setInsertName(
false);
2310 mCurrentCallExprPos.reset();
2316 const QualType castDestType = stmt->getTypeAsWritten();
2317 const Expr* subExpr = stmt->getSubExpr();
2319 FormatCast(stmt->getCastName(), castDestType, subExpr, stmt->getCastKind());
2325 const Expr* subExpr = stmt->getSubExpr();
2326 const auto castKind = stmt->getCastKind();
2329 auto isMatchingCast = [](
const CastKind kind,
const bool hideImplicitCasts,
const bool showXValueCasts) {
2331 case CastKind::CK_Dependent: [[fallthrough]];
2332 case CastKind::CK_IntegralCast: [[fallthrough]];
2333 case CastKind::CK_IntegralToBoolean: [[fallthrough]];
2334 case CastKind::CK_IntegralToPointer: [[fallthrough]];
2335 case CastKind::CK_PointerToIntegral: [[fallthrough]];
2336 case CastKind::CK_BitCast: [[fallthrough]];
2337 case CastKind::CK_UncheckedDerivedToBase: [[fallthrough]];
2338 case CastKind::CK_ToUnion:
2341 case CastKind::CK_AtomicToNonAtomic: [[fallthrough]];
2342 case CastKind::CK_DerivedToBase: [[fallthrough]];
2343 case CastKind::CK_FloatingCast: [[fallthrough]];
2344 case CastKind::CK_IntegralToFloating: [[fallthrough]];
2345 case CastKind::CK_FloatingToIntegral: [[fallthrough]];
2346 case CastKind::CK_NonAtomicToAtomic:
return true;
2349 if((showXValueCasts or not hideImplicitCasts) and (CastKind::CK_NoOp == kind)) {
2354 if(not hideImplicitCasts) {
2356 case CastKind::CK_NullToPointer: [[fallthrough]];
2357 case CastKind::CK_NullToMemberPointer: [[fallthrough]];
2360 case CastKind::CK_NoOp: [[fallthrough]];
2361 case CastKind::CK_ArrayToPointerDecay:
return true;
2368 }(castKind, hideImplicitCasts, stmt->isXValue() or
ShowXValueCasts());
2370 if(not isMatchingCast) {
2378 }
else if(isa<IntegerLiteral>(subExpr) and hideImplicitCasts) {
2383 }
else if(stmt->isPartOfExplicitCast()) {
2392 if(isa<CStyleCastExpr>(subExpr) or isa<CXXNamedCastExpr>(subExpr)) {
2400 const QualType castDestType{[&] {
2401 const auto type{stmt->getType()};
2405 if(VK_XValue == stmt->getValueKind()) {
2406 return GetGlobalAST().getRValueReferenceType(type.getCanonicalType());
2407 }
else if(type->isDependentType()) {
2412 return type.getCanonicalType();
2415 FormatCast(castName, castDestType, subExpr, castKind);
2422 if(
const auto* tmplObjParam = dyn_cast_or_null<TemplateParamObjectDecl>(stmt->getDecl())) {
2425 }
else if(
const auto* vd = dyn_cast_or_null<VarDecl>(stmt->getDecl());
2427 const auto* init = vd->getInit();
2429 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(init)) {
2433 }
else if(
const auto* inList = dyn_cast_or_null<InitListExpr>(init)) {
2439 if(
const auto* ctx = stmt->getDecl()->getDeclContext(); not ctx->isFunctionOrMethod() and
2440 not isa<NonTypeTemplateParmDecl>(stmt->getDecl()) and
2442 if(
const auto* qualifier = stmt->getQualifier();
2443 qualifier and (qualifier->getKind() == NestedNameSpecifier::SpecifierKind::Global)) {
2450 OutputFormatHelper ofm{};
2462 if(
const auto* varTmplSpecDecl = dyn_cast_or_null<VarTemplateSpecializationDecl>(stmt->getDecl())) {
2481 if(requiresImplicitReturnZero) {
2495template<
typename... Args>
2498 return (... and not isa<Args>(stmt));
2504 for(
const auto* item : stmt->body()) {
2532 if(
const auto* conditionVar = stmt->getConditionVariable()) {
2536 if(
const auto* init = stmt->getInit()) {
2539 if(not isa<DeclStmt>(init)) {
2548 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
2559 not stmt->isConsteval(),
2561 mShowConstantExprValue = ShowConstantExprValue::Yes;
2563 InsertArg(stmt->getCond());
2565 mShowConstantExprValue = ShowConstantExprValue::No;
2567 AddSpaceAtTheEnd::Yes);
2575 if(
const auto* elsePart = stmt->getElse()) {
2599 std::string_view mContinueLabel{};
2606 , mContinueLabel{continueLabel}
2627 auto* tmp = mPrevStmt;
2630 for(
auto* child : stmt->children()) {
2646 auto* rwStmt =
const_cast<ForStmt*
>(stmt);
2648 StmtsContainer bodyStmts{};
2650 auto continueLabel =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"__continue_"sv);
2651 const bool insertLabel = ContinueASTTransformer{rwStmt->getBody(), continueLabel}.found;
2653 bodyStmts.AddBodyStmts(rwStmt->getBody());
2657 bodyStmts.Add(
Label(continueLabel));
2660 bodyStmts.Add(rwStmt->getInc());
2662 auto* condition = [&]() -> Expr* {
2663 if(rwStmt->getCond()) {
2664 return rwStmt->getCond();
2670 auto* outerBody =
mkCompoundStmt(bodyStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2671 auto* whileStmt = WhileStmt::Create(
2672 ctx,
nullptr, condition, outerBody, stmt->getBeginLoc(), stmt->getLParenLoc(), stmt->getRParenLoc());
2674 StmtsContainer outerScopeStmts{};
2675 outerScopeStmts.Add(rwStmt->getInit());
2676 outerScopeStmts.Add(whileStmt);
2678 auto* outerScopeBody =
mkCompoundStmt(outerScopeStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2692 if(
const auto* init = stmt->getInit()) {
2693 MultiStmtDeclCodeGenerator codeGenerator{
2694 mOutputFormatHelper, mLambdaStack, InsertVarDecl(nullptr)};
2706 AddSpaceAtTheEnd::Yes);
2712 mOutputFormatHelper.AppendNewLine();
2718 if(not type.isNull()) {
2719 if(
auto* typePtr = type.getTypePtrOrNull()) {
2720 if(
auto pointee = typePtr->getPointeeType(); not pointee.isNull()) {
2721 return pointee.isConstQualified();
2732 const auto castKind = stmt->getCastKind();
2733 const QualType castDestType = stmt->getType().getCanonicalType();
2737 FormatCast(castName, castDestType, stmt->getSubExpr(), castKind);
2749 if(stmt->getNumPlacementArgs()) {
2753 ForEachArg(stmt->placement_arguments(), [&](
const auto& placementArg) { InsertArg(placementArg); });
2757 if(
const auto* ctorExpr = stmt->getConstructExpr()) {
2761 auto name =
GetName(stmt->getAllocatedType());
2764 if(stmt->isArray()) {
2765 OutputFormatHelper ofm{};
2769 codeGenerator->
InsertArg(stmt->getArraySize().value());
2784 if(stmt->hasInitializer()) {
2794 const auto* temporary = stmt->getSubExpr();
2803 const auto* callee = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts());
2804 const bool isCXXMethod{callee and isa<CXXMethodDecl>(callee->getDecl())};
2806 if(2 == stmt->getNumArgs()) {
2807 auto getArg = [&](
unsigned idx) {
2808 const auto* arg = stmt->getArg(idx);
2813 arg = arg->IgnoreImpCasts();
2816 return dyn_cast_or_null<DeclRefExpr>(arg);
2819 const auto* param1 = getArg(0);
2820 const auto* param2 = getArg(1);
2822 if(callee and param1 and param2) {
2823 const std::string replace = [&]() {
2825 auto nameWithTmplArguments = [](
const auto param) {
2829 if(isa<CXXMethodDecl>(callee->getDecl())) {
2830 return StrCat(nameWithTmplArguments(param1),
2834 nameWithTmplArguments(param2),
2839 nameWithTmplArguments(param1),
2841 nameWithTmplArguments(param2),
2852 auto cb = stmt->child_begin();
2853 const auto* fallbackArg0 = stmt->getArg(0);
2857 std::advance(cb, 1);
2859 const auto* arg1 = *cb;
2861 std::advance(cb, 1);
2864 if(not isCXXMethod) {
2867 if(
const auto* adl = dyn_cast_or_null<UnresolvedLookupExpr>(stmt->getCallee())) {
2878 if(isa<DeclRefExpr>(fallbackArg0)) {
2887 const OverloadedOperatorKind opKind = stmt->getOperator();
2895 const auto childRange = llvm::make_range(cb, stmt->child_end());
2898 ForEachArg(childRange, [&](
const auto& child) {
2899 if(not isCXXMethod) {
2950 const bool isConstructor{isa<CXXConstructExpr>(stmt->getSubExpr())};
2951 const bool isStdListInit{isa<CXXStdInitializerListExpr>(stmt->getSubExpr())};
2952 const bool isListInitialization{stmt->getLParenLoc().isInvalid()};
2953 const bool needsParens{not isConstructor and not isListInitialization and not isStdListInit};
2956 if(not isConstructor and not isStdListInit) {
2978 StringStream stream{};
2979 stream.Print(*stmt);
2981 auto str = std::move(stream.str());
2983 if(str ==
"'\\x00'"sv) {
2985 }
else if(str ==
"'\\xff'"sv) {
2997 if(
const auto* functionName = stmt->getFunctionName()) {
3000 const auto name = PredefinedExpr::getIdentKindName(stmt->getIdentKind());
3010 TemporaryDeclFinder temporaryFinder{*
this, not
mProcessingVarDecl ? stmt->getSubExpr() :
nullptr};
3024 const QualType& type = t.getCanonicalType();
3026 if(type->isScalarType()) {
3027 switch(type->getScalarTypeKind()) {
3028 case Type::STK_CPointer:
3029 case Type::STK_BlockPointer:
3030 case Type::STK_ObjCObjectPointer:
3031 case Type::STK_MemberPointer:
return std::string{
kwNullptr};
3033 case Type::STK_Bool:
return std::string{
kwFalse};
3035 case Type::STK_Integral:
3036 case Type::STK_Floating:
3037 if(
const auto* bt = type->getAs<BuiltinType>()) {
3038 switch(bt->getKind()) {
3040 case BuiltinType::Char_U:
3041 case BuiltinType::UChar:
3042 case BuiltinType::Char_S:
3043 case BuiltinType::SChar:
return "'\\0'";
3044 case BuiltinType::WChar_U:
3045 case BuiltinType::WChar_S:
return "L'\\0'";
3046 case BuiltinType::Char16:
return "u'\\0'";
3047 case BuiltinType::Char32:
return "U'\\0'";
3049 case BuiltinType::Half:
3050 case BuiltinType::Float:
return "0.0f";
3051 case BuiltinType::Double:
return "0.0";
3058 case Type::STK_FloatingComplex:
3059 case Type::STK_IntegralComplex:
3060 if(
const auto* complexType = type->getAs<ComplexType>()) {
3066 case Type::STK_FixedPoint:
Error(
"STK_FixedPoint is not implemented");
break;
3069 }
else if(
const auto* tt = dyn_cast_or_null<ConstantArrayType>(t.getTypePtrOrNull())) {
3070 const auto& elementType{tt->getElementType()};
3076 return std::string{
"0"sv};
3112 if(not stmt->getCaughtType().isNull()) {
3113 mOutputFormatHelper.Append(
3114 GetTypeNameAsParameter(stmt->getCaughtType(), stmt->getExceptionDecl()->getName()));
3116 mOutputFormatHelper.Append(kwElipsis);
3119 AddSpaceAtTheEnd::Yes);
3136 if(
const auto value = stmt->getAPValueResult(); value.isInt()) {
3148 const auto& underlyingType = stmt->getUnderlyingType();
3151 P0315Visitor dt{*
this};
3152 dt.TraverseType(underlyingType);
3156 if(
auto* templateSpecializationType = underlyingType->getAs<TemplateSpecializationType>()) {
3157 const bool carriesNamespace{[&] {
3158 if(
const auto tn = templateSpecializationType->getTemplateName();
3159 (TemplateName::QualifiedTemplate == tn.getKind()) or (TemplateName::DependentTemplate == tn.getKind())) {
3160 const auto* qtn = tn.getAsQualifiedTemplateName();
3162 return qtn->getQualifier() !=
nullptr;
3168 if(
const auto* elaboratedType = underlyingType->getAs<ElaboratedType>()) {
3169 if(templateSpecializationType->isSugared() and not carriesNamespace) {
3175 StringStream stream{};
3176 stream.Print(*templateSpecializationType);
3181 }
else if(
auto* dependentTemplateSpecializationType =
3182 underlyingType->getAs<DependentTemplateSpecializationType>()) {
3212 CXXConstructorDecl* cxxInheritedCtorDecl{
nullptr};
3216 if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
3223 for(
OnceTrue first{};
const auto* init : ctor->inits()) {
3226 initOutputFormatHelper.
Append(
": "sv);
3228 initOutputFormatHelper.
Append(
", "sv);
3233 if(
const auto* member = init->getMember()) {
3234 initOutputFormatHelper.
Append(member->getName());
3237 const auto* inlineInit = init->getInit();
3238 bool useCurlies{
false};
3240 if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3241 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3245 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3253 const auto* inlineInit = init->getInit();
3256 if(
const auto* member = init->getMember()) {
3257 initOutputFormatHelper.
Append(member->getName());
3259 if(isa<ParenListExpr>(inlineInit)) {
3265 }
else if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3266 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3272 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3299 if(not stmt->isUserProvided() or stmt->isExplicitlyDefaulted()) {
3306 if(isa<CXXConversionDecl>(stmt)) {
3307 if(stmt->getParent()->isLambda() and not stmt->doesThisDeclarationHaveABody()) {
3312 if(
const auto* invoker = stmt->getParent()->getLambdaStaticInvoker()) {
3313 mOutputFormatHelper.AppendSemiNewLine(invoker->getName());
3315 mOutputFormatHelper.AppendSemiNewLine(kwOperator,
"()"sv);
3321 if((SkipBody::No == skipBody) and stmt->doesThisDeclarationHaveABody() and not stmt->isLambdaStaticInvoker()) {
3330 if(SkipBody::No == skipBody) {
3342 not stmt->isExplicitlyDefaulted() and not stmt->isDeleted());
3352 if(stmt->isScoped()) {
3353 if(stmt->isScopedUsingClassTag()) {
3362 if(stmt->isFixed()) {
3374 ForEachArg(stmt->enumerators(), [&](
const auto* value) {
3376 mOutputFormatHelper.AppendNewLine();
3387 AddSpaceAtTheEnd::No);
3389 mOutputFormatHelper.AppendSemiNewLine();
3390 mOutputFormatHelper.AppendNewLine();
3400 if(
const auto* initExpr = stmt->getInitExpr()) {
3417 static const std::string_view spaces{
" "sv};
3419 if(offset >= spaces.size()) {
3422 return spaces.substr(0, spaces.size() - offset);
3430 P0315Visitor dt{*
this};
3432 auto type =
GetType(stmt->getType());
3433 dt.TraverseType(type);
3438 if(stmt->isMutable()) {
3442 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getParent())) {
3443 std::string name{
GetName(*stmt)};
3446 name = std::move(fieldName.value());
3451 if(
const auto* constantExpr = dyn_cast_or_null<ConstantExpr>(stmt->getBitWidth())) {
3457 if(
const auto* initializer = stmt->getInClassInitializer();
3458 stmt->hasInClassInitializer() and initializer and cxxRecordDecl->isAggregate()) {
3459 const bool isConstructorExpr{isa<CXXConstructExpr>(initializer) or isa<ExprWithCleanups>(initializer)};
3460 if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) {
3471 const auto* fieldClass = stmt->getParent();
3473 auto effectiveFieldSize{
GetGlobalAST().getTypeInfoInChars(type).Width.getQuantity()};
3474 auto getFieldOffsetInBytes = [&recordLayout](
const FieldDecl* field) {
3475 return recordLayout.getFieldOffset(field->getFieldIndex()) / 8;
3477 auto fieldOffset = getFieldOffsetInBytes(stmt);
3489 const auto expectedOffset = fieldOffset + effectiveFieldSize;
3490 const auto nextOffset = [&]() -> uint64_t {
3492 if(
const auto next = stmt->getFieldIndex() + 1; recordLayout.getFieldCount() > next) {
3494 const auto* field = *std::next(fieldClass->fields().begin(), next);
3496 return getFieldOffsetInBytes(field);
3500 return recordLayout.getSize().getQuantity();
3503 if(expectedOffset < nextOffset) {
3504 const auto padding = nextOffset - expectedOffset;
3529 if(not stmt->isFailed()) {
3541 if(stmt->getMessage()) {
3554 if(
const auto& name =
GetName(*stmt->getNominatedNamespace()); not name.empty()) {
3564 if(stmt->isInline()) {
3572 if(not stmt->isAnonymousNamespace()) {
3580 for(
const auto* decl : stmt->decls()) {
3603 if(stmt->shadow_size()) {
3604 for(
const auto* shadow : stmt->shadows()) {
3605 RETURN_IF(isa<ConstructorUsingShadowDecl>(shadow));
3607 if(
const auto* shadowUsing = dyn_cast_or_null<UsingShadowDecl>(shadow)) {
3608 if(
const auto* targetDecl = shadowUsing->getTargetDecl(); not isa<TypeAliasDecl>(targetDecl)) {
3609 UsingCodeGenerator codeGenerator{ofm};
3623 if(not ofm.empty()) {
3648 if(
const auto* typeInfo = stmt->getFriendType()) {
3651 }
else if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(stmt->getFriendDecl())) {
3654 }
else if(
const auto* fdt = dyn_cast_or_null<FunctionTemplateDecl>(stmt->getFriendDecl())) {
3659 if(
const auto* ctd = dyn_cast_or_null<ClassTemplateDecl>(stmt->getFriendDecl())) {
3680 RETURN_IF(DeductionCandidate::Copy == stmt->getDeductionCandidateKind());
3682 const bool isImplicit{stmt->isImplicit()};
3683 const bool noSpecializations = [&] {
3684 if(
const auto* dt = stmt->getDescribedFunctionTemplate()) {
3685 return dt->specializations().empty();
3692 RETURN_IF(not stmt->isUsed() and isImplicit and noSpecializations);
3694 const bool isSpecialization{stmt->isFunctionTemplateSpecialization()};
3695 const bool needsTemplateGuard{isImplicit or isSpecialization};
3697 if(needsTemplateGuard) {
3701 const auto* deducedTemplate = stmt->getDeducedTemplate();
3703 if(isSpecialization) {
3705 }
else if(
const auto* e = stmt->getDescribedFunctionTemplate()) {
3711 if(stmt->getNumParams()) {
3719 if(needsTemplateGuard) {
3738 for(
const auto* spec : stmt->specializations()) {
3740 if(spec->getPreviousDecl()) {
3767 for(
const auto& attr : stmt->getAttrs()) {
3777 if(stmt->hasAttrs()) {
3788 for(
const auto& attr : attrs) {
3797 RETURN_IF(attr::Override == attr.getKind());
3800 RETURN_IF(attr::Final == attr.getKind());
3803 RETURN_IF(attr::NoInline == attr.getKind());
3806 if(
const auto* alignedAttr = dyn_cast_or_null<AlignedAttr>(&attr)) {
3807 auto insert = [&](
const QualType type,
const TemplateTypeParmType* tmplTypeParam) {
3814 Ellipsis(tmplTypeParam->isParameterPack()),
3818 if(alignedAttr->isAlignmentExpr()) {
3819 if(
const auto* unaryExpr = dyn_cast_or_null<UnaryExprOrTypeTraitExpr>(alignedAttr->getAlignmentExpr())) {
3820 if(
const auto* tmplTypeParam =
3821 dyn_cast_or_null<TemplateTypeParmType>(unaryExpr->getArgumentType().getTypePtrOrNull())) {
3822 insert(unaryExpr->getArgumentType(), tmplTypeParam);
3826 }
else if(
const auto* tmplTypeParam =
3827 alignedAttr->getAlignmentType()->getType()->getAs<TemplateTypeParmType>()) {
3828 insert(alignedAttr->getAlignmentType()->getType(), tmplTypeParam);
3835 pp.adjustForCPlusPlus();
3837 attr.printPretty(stream, pp);
3840 std::string_view start{stream.str()};
3856 const auto* classTemplatePartialSpecializationDecl = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(stmt);
3857 const auto* classTemplateSpecializationDecl = dyn_cast_or_null<ClassTemplateSpecializationDecl>(stmt);
3861 const bool isClassTemplateSpecialization{classTemplatePartialSpecializationDecl or classTemplateSpecializationDecl};
3862 const bool tmplRequiresIfDef{[&] {
3863 if(classTemplatePartialSpecializationDecl) {
3864 return classTemplatePartialSpecializationDecl->isImplicit();
3866 }
else if(classTemplateSpecializationDecl) {
3867 return not classTemplateSpecializationDecl->isExplicitInstantiationOrSpecialization();
3874 if(tmplRequiresIfDef) {
3879 if(isClassTemplateSpecialization) {
3880 if(tmplRequiresIfDef) {
3882 classTemplateSpecializationDecl->getPointOfInstantiation());
3886 if(classTemplatePartialSpecializationDecl) {
3892 }
else if(stmt->getLexicalDeclContext() != stmt->getDeclContext()) {
3893 if(
const auto* parent = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
3894 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
3906 if(classTemplateSpecializationDecl) {
3910 if(stmt->hasAttr<FinalAttr>()) {
3915 if(not stmt->hasDefinition() or not stmt->isCompleteDefinition()) {
3920 if(stmt->getNumBases()) {
3923 ForEachArg(stmt->bases(), [&](
const auto& base) {
3924 mOutputFormatHelper.Append(getAccessSpelling(base.getAccessSpecifier()),
3926 ValueOrDefault(base.isVirtual(), kwVirtualSpace),
3927 GetName(base.getType()),
3928 Ellipsis(base.isPackExpansion()));
3935 " /* size: "sv, recordLayout.getSize(),
", align: "sv, recordLayout.getAlignment(),
" */"sv);
3944 for(
size_t offset{};
const auto& base : stmt->bases()) {
3945 const auto& baseRecordLayout =
GetRecordLayout(base.getType()->getAsRecordDecl());
3946 const auto baseVar =
StrCat(
"/* base ("sv,
GetName(base.getType()),
")"sv);
3947 const auto size = baseRecordLayout.getSize().getQuantity();
3950 baseVar,
GetSpaces(baseVar.size()),
" offset: "sv, offset,
", size: "sv, size,
" */"sv);
3960 Decl::Kind formerKind{};
3961 AccessSpecifier lastAccess{stmt->isClass() ? AS_private : AS_public};
3962 for(
const auto* d : stmt->decls()) {
3963 if(isa<CXXRecordDecl>(d) and firstRecordDecl) {
3969 if(not firstDecl and (d->getKind() != formerKind)) {
3973 if((stmt->isLambda() and isa<CXXDestructorDecl>(d)) and not d->isUsed()) {
3979 if(lastAccess != d->getAccess()) {
3980 lastAccess = d->getAccess();
3983 if(not isa<AccessSpecDecl>(d)) {
3990 formerKind = d->getKind();
3993 if(stmt->isLambda()) {
3995 const bool ctorRequired{stmt->capture_size() or stmt->lambdaIsDefaultConstructibleAndAssignable()};
3998 if(AS_public != lastAccess) {
4002 std::string_view p{pub};
4007 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
4010 if(stmt->hasConstexprDefaultConstructor()) {
4018 SmallVector<std::string, 5> ctorInitializerList{};
4019 std::string ctorArguments{
'{'};
4023 [&](std::string_view name,
const FieldDecl* fd,
bool isThis,
const Expr* expr,
bool ) {
4024 if(firstCtorArgument) {
4027 ctorArguments.append(
", "sv);
4030 bool byConstRef{
false};
4032 auto fieldDeclType{fd->getType()};
4035 std::string fname =
StrCat(
"_"sv, name);
4039 if(
const auto* cxxConstructExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4040 cxxConstructExpr and cxxConstructExpr->getConstructor()->isMoveConstructor()) {
4042 OutputFormatHelper ofm{};
4043 LambdaInitCaptureCodeGenerator codeGenerator{ofm,
mLambdaStack, name};
4045 if(cxxConstructExpr->getNumArgs()) {
4047 [&](
const auto& arg) { codeGenerator.InsertArg(arg); });
4050 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4056 }
else if(not fieldDeclType->isReferenceType() and not fieldDeclType->isAnyPointerType() and
4057 not fieldDeclType->isUndeducedAutoType()) {
4059 const auto* exprWithoutImpCasts = expr->IgnoreParenImpCasts();
4062 if(exprWithoutImpCasts->isXValue()) {
4065 OutputFormatHelper ofm{};
4066 LambdaInitCaptureCodeGenerator codeGenerator{ofm,
mLambdaStack, name};
4071 }
else if(exprWithoutImpCasts
4073 or exprWithoutImpCasts->getType().isConstQualified()
4080 if(exprWithoutImpCasts->isPRValue() and isa<CXXBindTemporaryExpr>(exprWithoutImpCasts) and
4081 not exprWithoutImpCasts->getType().isConstQualified()) {
4082 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4084 fname =
StrCat(
"std::move("sv, fname,
")"sv);
4088 fieldDeclType.addConst();
4092 if(exprWithoutImpCasts->isXValue()) {
4093 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4095 }
else if(not isMoved) {
4096 fieldDeclType = stmt->getASTContext().getLValueReferenceType(fieldDeclType);
4100 const std::string_view elips{
4101 Ellipsis(isa_and_nonnull<PackExpansionType>(fieldDeclType->getPointeeType().getTypePtrOrNull()))};
4104 fieldDeclType = fieldDeclType.getCanonicalType();
4106 ctorInitializerList.push_back(
StrCat(fieldName,
"{"sv, fname, elips,
"}"sv));
4108 if(not isThis and expr) {
4110 OutputFormatHelper ofmLambdaInCtor{};
4111 ofmLambdaInCtor.SetIndent(indentAtInsertPosBeforeClass);
4112 CodeGenerator cgLambdaInCtor{ofmLambdaInCtor, LambdaInInitCapture::Yes};
4114 if(P0315Visitor dt{cgLambdaInCtor}; dt.TraverseStmt(
const_cast<Expr*
>(expr))) {
4116 OutputFormatHelper ofm{};
4119 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4120 ctorExpr and byConstRef and (1 == ctorExpr->getNumArgs())) {
4121 codeGenerator->
InsertArg(ctorExpr->getArg(0));
4131 ctorArguments.append(ofm);
4134 OutputFormatHelper ofm{};
4135 LambdaNameOnlyCodeGenerator ccg{ofm};
4136 ccg.InsertArg(expr);
4138 ctorArguments.append(ofm.GetString());
4143 if(isThis and not fieldDeclType->isPointerType()) {
4144 ctorArguments.append(
"*"sv);
4147 ctorArguments.append(name);
4153 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
4154 FieldDecl* thisCapture{};
4156 stmt->getCaptureFields(captures, thisCapture);
4160 const auto* captureInit =
mLambdaExpr->capture_init_begin();
4162 addToInits(
kwThis, thisCapture,
true, *captureInit,
false);
4169 if(not c.capturesVariable()) {
4173 const auto* capturedVar = c.getCapturedVar();
4174 if(
const auto* value = captures[capturedVar]) {
4176 if(
const auto* bindingDecl = dyn_cast_or_null<BindingDecl>(capturedVar)) {
4177 const auto* decompositionDecl = cast<DecompositionDecl>(bindingDecl->getDecomposedDecl());
4178 addToInits(
GetName(*capturedVar),
4182 VarDecl::ListInit == decompositionDecl->getInitStyle());
4186 addToInits(
GetName(*capturedVar),
4190 VarDecl::ListInit == dyn_cast_or_null<VarDecl>(capturedVar)->getInitStyle());
4194 ctorArguments.append(
"}"sv);
4201 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
4207 for(
OnceTrue firstCtorInitializer{};
const auto& initializer : ctorInitializerList) {
4208 if(firstCtorInitializer) {
4249 for(
const auto* decl : stmt->decls()) {
4263 if(stmt->isPartiallySubstituted()) {
4265 }
else if(not stmt->isValueDependent()) {
4280 TemporaryDeclFinder temporaryFinder{*
this, stmt->getRetValue(),
true};
4284 if(
const auto* retVal = stmt->getRetValue()) {
4287 if(not temporaryFinder.Found()) {
4288 if(
const auto* nrvoVD = stmt->getNRVOCandidate()) {
4329 if(
const auto* namedConcept = stmt->getNamedConcept()) {
4334 if(not stmt->isValueDependent()) {
4346 const auto localParameters = stmt->getLocalParameters();
4348 not localParameters.empty(),
4349 [&] { mOutputFormatHelper.AppendParameterList(localParameters); },
4350 AddSpaceAtTheEnd::Yes);
4358 for(
const auto& requirement : stmt->getRequirements()) {
4359 if(
const auto* typeRequirement = dyn_cast_or_null<concepts::TypeRequirement>(requirement)) {
4360 if(typeRequirement->isSubstitutionFailure()) {
4367 }
else if(
const auto* exprRequirement = dyn_cast_or_null<concepts::ExprRequirement>(requirement)) {
4368 if(exprRequirement->isExprSubstitutionFailure()) {
4373 WrapInCurliesIfNeeded(exprRequirement->isCompound(), [&] { InsertArg(exprRequirement->getExpr()); });
4375 if(exprRequirement->hasNoexceptRequirement()) {
4379 if(
const auto& returnTypeRequirement = exprRequirement->getReturnTypeRequirement();
4380 not returnTypeRequirement.isEmpty()) {
4382 not typeConstraint.empty()) {
4387 }
else if(
const auto* nestedRequirement = dyn_cast_or_null<concepts::NestedRequirement>(requirement)) {
4390 if(nestedRequirement->hasInvalidConstraint()) {
4395 InsertArg(nestedRequirement->getConstraintExpr());
4416 const auto typeName{
GetName(stmt->getType(), Unqualified::Yes)};
4422 const auto* subExpr = stmt->getSubExpr();
4424 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(subExpr); dref and
GetInsightsOptions().ShowLifetime) {
4425 const auto size =
GetSize(dyn_cast_or_null<ConstantArrayType>(subExpr->getType()));
4431 std::string modifiers{};
4435 auto& ofmToInsert = [&]() ->
decltype(
auto) {
4447 OutputFormatHelper ofm{};
4448 ofm.SetIndent(ofmToInsert, OutputFormatHelper::SkipIndenting::Yes);
4450 const auto size = [&]() ->
size_t {
4451 if(
const auto* mat = dyn_cast<MaterializeTemporaryExpr>(subExpr)) {
4452 if(
const auto* list = dyn_cast_or_null<InitListExpr>(mat->getSubExpr())) {
4453 return list->getNumInits();
4460 auto internalListName =
4466 ofm.AppendSemiNewLine();
4468 ofmToInsert.InsertAt(variableInsertPos, ofm);
4503#define SUPPORTED_DECL(type) \
4504 if(isa<type>(stmt)) { \
4505 InsertArg(static_cast<const type*>(stmt)); \
4509#define IGNORED_DECL SUPPORTED_DECL