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()) {
1391 stmt->getType(), stmt,
ArgsToExprVector(ctorExpr), DoCast::No, AsReference::Yes);
1407 if(MyOptional<const InitListExpr*> initList{dyn_cast_or_null<InitListExpr>(init)};
1409 initList.and_then(CanonicalType).and_then(Isa<RecordType>).and_not(IsPointer).and_then(IsPOD) and
1410 not isa<ArrayType>(stmt->getType())) {
1415 if(stmt->hasGlobalStorage()) {
1424 initList.and_then(CanonicalType)
1425 .and_then(Isa<RecordType>)
1428 (0 == initList.value()->getNumInits()))) {
1432 if(not(ctorExpr and ctorExpr->getConstructor()->isDefaultConstructor() and
1433 ctorExpr->getConstructor()->getParent()->hasTrivialDefaultConstructor())) {
1435 const bool isPrimaryTemplatePackExpansionExpr{
1438 if(not isa<CXXParenListInitExpr>(init) and not isPrimaryTemplatePackExpansionExpr) {
1444 stmt->getType()->isRValueReferenceType()) {
1446 if(GetInsightsOptions().UseShow2C) {
1447 mOutputFormatHelper.Append(
"&");
1461 if(stmt->isNRVOVariable()) {
1470 if(
const auto* decompDecl = dyn_cast_or_null<DecompositionDecl>(stmt)) {
1473 codeGenerator.InsertDecompositionBindings(*decompDecl);
1478 mOutputFormatHelper.InsertEndIfTemplateGuard();
1485 if(not(cxxMethodDecl and cxxMethodDecl->isLambdaStaticInvoker())) {
1498 if(not cxxMethodDecl->getReturnType()->isVoidType()) {
1504 if(cxxMethodDecl->isFunctionTemplateSpecialization()) {
1508 if(cxxMethodDecl->isTemplated()) {
1509 if(cxxMethodDecl->getDescribedTemplate()) {
1511 TemplateParamsOnly::Yes);
1520 OutputFormatHelper::NameOnly::Yes,
1521 OutputFormatHelper::GenMissingParamName::Yes);
1536 const SourceLocation& instLoc,
1537 std::string_view text)
1539 const auto lineNo = sm.getSpellingLineNumber(instLoc);
1540 const auto& fileId = sm.getFileID(instLoc);
1541 if(
const auto file = sm.getFileEntryRefForID(fileId)) {
1542 const auto fileWithDirName = file->getName();
1543 const auto fileName = llvm::sys::path::filename(fileWithDirName);
1546 text =
"First instantiated from: "sv;
1556 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1565 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1588 if(isa<CoyieldExpr>(stmt)) {
1595 if(
const auto* matTemp = dyn_cast_or_null<MaterializeTemporaryExpr>(stmt->getCommonExpr())) {
1596 const auto* temporary = matTemp->getSubExpr();
1598 if(
const auto* memExpr = dyn_cast_or_null<CXXMemberCallExpr>(temporary)) {
1599 ForEachArg(memExpr->arguments(), [&](
const auto& arg) { InsertArg(arg); });
1605 }
else if(
const auto* unaryexpr = dyn_cast_or_null<UnaryOperator>(stmt->getOperand())) {
1606 if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(unaryexpr->getSubExpr())) {
1622 auto IsPrimaryTemplate = [&] {
1624 if(
const auto* cxxMethod = dyn_cast_or_null<CXXMethodDecl>(stmt)) {
1625 if(
const auto* tmpl = cxxMethod->getParent()->getDescribedClassTemplate();
1626 tmpl and not isa<ClassTemplateSpecializationDecl>(cxxMethod->getParent())) {
1631 return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind()) or
1635 if(stmt->doesThisDeclarationHaveABody()) {
1640 if(
const auto* corBody = dyn_cast_or_null<CoroutineBodyStmt>(stmt->getBody());
1641 (
nullptr != corBody) and not IsPrimaryTemplate() and
GetInsightsOptions().ShowCoroutineTransformation) {
1644 codeGenerator.InsertCoroutine(*stmt, corBody);
1646 const auto exSpec = stmt->getExceptionSpecType();
1647 const bool showNoexcept =
1651 if(stmt->hasImplicitReturnZero()) {
1653 [](
const Stmt* e) { return isa<ReturnStmt>(e); });
1656 const auto* body = stmt->getBody();
1665 for(
const auto* param : stmt->parameters()) {
1666 auto paramType = param->getType();
1667 const bool isPassByValue{not paramType->isPointerType() and not paramType->isReferenceType()};
1668 if(
const auto* rd = paramType->getAsRecordDecl(); rd and isPassByValue) {
1692 dt.TraverseType(stmt->getReturnType());
1695 for(
const auto& param : stmt->parameters()) {
1696 P0315Visitor dt{*
this};
1697 dt.TraverseType(param->getType());
1701 if(
const auto* deductionGuide = dyn_cast_or_null<CXXDeductionGuideDecl>(stmt)) {
1703 }
else if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
1708 RETURN_IF(isa<CXXConversionDecl>(stmt) and not stmt->hasBody());
1726 if(typeConstraint) {
1728 sstream.
Print(*typeConstraint);
1730 return sstream.str();
1754 expr = expr->IgnoreParenImpCasts();
1757 if(Expr::EvalResult evalResult{};
1758 isa<CXXFunctionalCastExpr>(expr) and
1759 expr->EvaluateAsConstantExpr(evalResult,
GetGlobalAST(), ConstantExprKind::Normal)) {
1760 return std::pair<QualType, APValue>{expr->getType(), evalResult.Val};
1768 const TemplateParamsOnly templateParamsOnly)
1770 const bool full{TemplateParamsOnly::No == templateParamsOnly};
1773 for(
const auto* param : list) {
1774 if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param);
1775 nonTmplParam and nonTmplParam->hasDefaultArgument()) {
1778 auto* init =
GetGlobalAST().getTemplateParamObjectDecl(val->first, val->second);
1790 for(
OnceFalse needsComma{};
const auto* param : list) {
1793 const auto& typeName =
GetName(*param);
1795 if(
const auto* tt = dyn_cast_or_null<TemplateTypeParmDecl>(param)) {
1797 if(tt->wasDeclaredWithTypename()) {
1799 }
else if(not tt->hasTypeConstraint()) {
1806 if(0 == typeName.size() or tt->isImplicit() ) {
1811 not typeConstraint.empty()) {
1820 if(tt->hasDefaultArgument() and not tt->defaultArgumentWasInherited()) {
1821 const auto& defaultArg = tt->getDefaultArgument();
1823 if(
const auto decltypeType = dyn_cast_or_null<DecltypeType>(defaultArg.getArgument().getAsType())) {
1826 InsertArg(decltypeType->getUnderlyingExpr());
1834 }
else if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param)) {
1836 if(
const auto nttpType = nonTmplParam->getType();
1837 nttpType->isFunctionPointerType() or nttpType->isMemberFunctionPointerType()) {
1842 GetName(nttpType),
" "sv,
Ellipsis(nonTmplParam->isParameterPack()), typeName);
1845 if(nonTmplParam->hasDefaultArgument()) {
1852 }
else if(
const auto* tmplTmplParam = dyn_cast_or_null<TemplateTemplateParmDecl>(param)) {
1857 if(tmplTmplParam->hasDefaultArgument()) {
1884 SmallVector<const ClassTemplateSpecializationDecl*, 10> specializations{};
1887 for(
const auto* spec : stmt->specializations()) {
1890 if(TSK_ImplicitInstantiation == spec->getSpecializationKind()) {
1891 specializations.push_back(spec);
1896 ranges::sort(specializations,
1897 [](
const ClassTemplateSpecializationDecl* a,
const ClassTemplateSpecializationDecl* b) {
1898 return a->getPointOfInstantiation() < b->getPointOfInstantiation();
1901 for(
const auto* spec : specializations) {
1909 for(
OnceFalse needsComma{};
const auto& expr : stmt->children()) {
1929 OnceFalse needsComma{uint64_t{0} != startAt};
1930 for_each(startAt, size, [&](
auto) {
1931 ret.AppendComma(needsComma);
1936 return ret.GetString();
1947 ((stmt->getNumInits() > 1) or stmt->getArrayFiller() or
1948 ((0 < stmt->getNumInits()) and isa<ImplicitValueInitExpr>(stmt->getInit(0))))),
1950 mOutputFormatHelper.IncreaseIndent();
1952 ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); });
1955 if(stmt->getType().getCanonicalType()->isScalarType()) {
1966 if(
const auto* filler = stmt->getArrayFiller()) {
1967 OutputFormatHelper ofm{};
1972 dyn_cast_or_null<ConstantArrayType>(stmt->getType().getTypePtrOrNull()),
1974 stmt->getNumInits());
1980 mOutputFormatHelper.DecreaseIndent();
1986 const auto* subExpr = stmt->getExpr();
1996 if(stmt->isArrayForm()) {
2012 dt.TraverseType(stmt->getType());
2026 if(
const auto& arguments = stmt->arguments(); not arguments.empty()) {
2027 ForEachArg(stmt->arguments(), [&](
const auto& arg) { InsertArg(arg); });
2055 if(stmt->getNumTemplateArgs()) {
2070 auto operatorStr = BinaryOperator::getOpcodeStr(stmt->getOperator());
2074 const auto* init = stmt->getInit();
2076 if(stmt->isLeftFold()) {
2079 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2087 if(stmt->isRightFold()) {
2101 const auto& constructorDecl = *stmt->getConstructor();
2106 OutputFormatHelper::NameOnly::Yes,
2107 OutputFormatHelper::GenMissingParamName::Yes);
2150 StringRef opCodeName = UnaryOperator::getOpcodeStr(stmt->getOpcode());
2151 const bool insertBefore{not stmt->isPostfix()};
2159 if(not insertBefore) {
2167 StringStream stream{};
2168 stream.Print(*stmt);
2176 Error(stmt,
"ArrayInitIndexExpr should not be reached in CodeGenerator");
2182 if((not
GetInsightsOptions().UseAltArraySubscriptionSyntax) or stmt->getLHS()->isLValue()) {
2203 const uint64_t size = stmt->getArraySize().getZExtValue();
2207 codeGenerator.
InsertArg(stmt->getSubExpr());
2224 if(insideDecltype) {
2232 if(
const auto* declRefExpr = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts())) {
2233 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(declRefExpr->getDecl())) {
2234 if((not declRefExpr->getNumTemplateArgs() and
GetInsightsOptions().ShowAllCallExprTemplateParameters) or
2235 isa<UserDefinedLiteral>(stmt)) {
2242 auto* funcDecl = dyn_cast_or_null<FunctionDecl>(stmt->getCalleeDecl());
2245 ForEachArg(stmt->arguments(), [&](
const auto* arg) {
2248 if(const auto* tmpExpr = dyn_cast_or_null<CXXBindTemporaryExpr>(arg)) {
2249 if(const auto* tmp = dyn_cast_or_null<CXXTemporaryObjectExpr>(tmpExpr->getSubExpr())) {
2250 if(GetInsightsOptions().UseShow2C) {
2255 } else if(GetInsightsOptions().ShowLifetime) {
2256 mOutputFormatHelper.Append(GetName(*tmp));
2262 if(
GetInsightsOptions().UseShow2C and funcDecl and (funcDecl->getNumParams() >= parmIdx) and
2264 if(auto* unop = dyn_cast_or_null<UnaryOperator>(arg); not unop or (unop->getOpcode() != UO_AddrOf)) {
2273 if(insideDecltype) {
2274 mLambdaStack.back().setInsertName(
false);
2277 mCurrentCallExprPos.reset();
2283 const QualType castDestType = stmt->getTypeAsWritten();
2284 const Expr* subExpr = stmt->getSubExpr();
2286 FormatCast(stmt->getCastName(), castDestType, subExpr, stmt->getCastKind());
2292 const Expr* subExpr = stmt->getSubExpr();
2293 const auto castKind = stmt->getCastKind();
2296 auto isMatchingCast = [](
const CastKind kind,
const bool hideImplicitCasts,
const bool showXValueCasts) {
2298 case CastKind::CK_Dependent: [[fallthrough]];
2299 case CastKind::CK_IntegralCast: [[fallthrough]];
2300 case CastKind::CK_IntegralToBoolean: [[fallthrough]];
2301 case CastKind::CK_IntegralToPointer: [[fallthrough]];
2302 case CastKind::CK_PointerToIntegral: [[fallthrough]];
2303 case CastKind::CK_BitCast: [[fallthrough]];
2304 case CastKind::CK_UncheckedDerivedToBase: [[fallthrough]];
2305 case CastKind::CK_ToUnion:
2308 case CastKind::CK_AtomicToNonAtomic: [[fallthrough]];
2309 case CastKind::CK_DerivedToBase: [[fallthrough]];
2310 case CastKind::CK_FloatingCast: [[fallthrough]];
2311 case CastKind::CK_IntegralToFloating: [[fallthrough]];
2312 case CastKind::CK_FloatingToIntegral: [[fallthrough]];
2313 case CastKind::CK_NonAtomicToAtomic:
return true;
2316 if((showXValueCasts or not hideImplicitCasts) and (CastKind::CK_NoOp == kind)) {
2321 if(not hideImplicitCasts) {
2323 case CastKind::CK_NullToPointer: [[fallthrough]];
2324 case CastKind::CK_NullToMemberPointer: [[fallthrough]];
2327 case CastKind::CK_NoOp: [[fallthrough]];
2328 case CastKind::CK_ArrayToPointerDecay:
return true;
2335 }(castKind, hideImplicitCasts, stmt->isXValue() or
ShowXValueCasts());
2337 if(not isMatchingCast) {
2345 }
else if(isa<IntegerLiteral>(subExpr) and hideImplicitCasts) {
2350 }
else if(stmt->isPartOfExplicitCast()) {
2359 if(isa<CStyleCastExpr>(subExpr) or isa<CXXNamedCastExpr>(subExpr)) {
2367 const QualType castDestType{[&] {
2368 const auto type{stmt->getType()};
2372 if(VK_XValue == stmt->getValueKind()) {
2373 return GetGlobalAST().getRValueReferenceType(type.getCanonicalType());
2374 }
else if(type->isDependentType()) {
2379 return type.getCanonicalType();
2382 FormatCast(castName, castDestType, subExpr, castKind);
2389 if(
const auto* tmplObjParam = dyn_cast_or_null<TemplateParamObjectDecl>(stmt->getDecl())) {
2392 }
else if(
const auto* vd = dyn_cast_or_null<VarDecl>(stmt->getDecl());
2394 const auto* init = vd->getInit();
2396 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(init)) {
2400 }
else if(
const auto* inList = dyn_cast_or_null<InitListExpr>(init)) {
2406 if(
const auto* ctx = stmt->getDecl()->getDeclContext(); not ctx->isFunctionOrMethod() and
2407 not isa<NonTypeTemplateParmDecl>(stmt->getDecl()) and
2409 if(
const auto* qualifier = stmt->getQualifier();
2410 qualifier and (qualifier->getKind() == NestedNameSpecifier::SpecifierKind::Global)) {
2417 OutputFormatHelper ofm{};
2429 if(
const auto* varTmplSpecDecl = dyn_cast_or_null<VarTemplateSpecializationDecl>(stmt->getDecl())) {
2448 if(requiresImplicitReturnZero) {
2462template<
typename... Args>
2465 return (... and not isa<Args>(stmt));
2471 for(
const auto* item : stmt->body()) {
2499 if(
const auto* conditionVar = stmt->getConditionVariable()) {
2503 if(
const auto* init = stmt->getInit()) {
2506 if(not isa<DeclStmt>(init)) {
2515 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
2526 not stmt->isConsteval(),
2528 mShowConstantExprValue = ShowConstantExprValue::Yes;
2530 InsertArg(stmt->getCond());
2532 mShowConstantExprValue = ShowConstantExprValue::No;
2534 AddSpaceAtTheEnd::Yes);
2542 if(
const auto* elsePart = stmt->getElse()) {
2566 std::string_view mContinueLabel{};
2573 , mContinueLabel{continueLabel}
2594 auto* tmp = mPrevStmt;
2597 for(
auto* child : stmt->children()) {
2613 auto* rwStmt =
const_cast<ForStmt*
>(stmt);
2615 StmtsContainer bodyStmts{};
2617 auto continueLabel =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"__continue_"sv);
2618 const bool insertLabel = ContinueASTTransformer{rwStmt->getBody(), continueLabel}.found;
2620 bodyStmts.AddBodyStmts(rwStmt->getBody());
2624 bodyStmts.Add(
Label(continueLabel));
2627 bodyStmts.Add(rwStmt->getInc());
2629 auto* condition = [&]() -> Expr* {
2630 if(rwStmt->getCond()) {
2631 return rwStmt->getCond();
2637 auto* outerBody =
mkCompoundStmt(bodyStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2638 auto* whileStmt = WhileStmt::Create(
2639 ctx,
nullptr, condition, outerBody, stmt->getBeginLoc(), stmt->getLParenLoc(), stmt->getRParenLoc());
2641 StmtsContainer outerScopeStmts{};
2642 outerScopeStmts.Add(rwStmt->getInit());
2643 outerScopeStmts.Add(whileStmt);
2645 auto* outerScopeBody =
mkCompoundStmt(outerScopeStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2659 if(
const auto* init = stmt->getInit()) {
2660 MultiStmtDeclCodeGenerator codeGenerator{
2661 mOutputFormatHelper, mLambdaStack, InsertVarDecl(nullptr)};
2673 AddSpaceAtTheEnd::Yes);
2679 mOutputFormatHelper.AppendNewLine();
2685 if(not type.isNull()) {
2686 if(
auto* typePtr = type.getTypePtrOrNull()) {
2687 if(
auto pointee = typePtr->getPointeeType(); not pointee.isNull()) {
2688 return pointee.isConstQualified();
2699 const auto castKind = stmt->getCastKind();
2700 const QualType castDestType = stmt->getType().getCanonicalType();
2704 FormatCast(castName, castDestType, stmt->getSubExpr(), castKind);
2716 if(stmt->getNumPlacementArgs()) {
2720 ForEachArg(stmt->placement_arguments(), [&](
const auto& placementArg) { InsertArg(placementArg); });
2724 if(
const auto* ctorExpr = stmt->getConstructExpr()) {
2728 auto name =
GetName(stmt->getAllocatedType());
2731 if(stmt->isArray()) {
2732 OutputFormatHelper ofm{};
2736 codeGenerator->
InsertArg(stmt->getArraySize().value());
2751 if(stmt->hasInitializer()) {
2761 const auto* temporary = stmt->getSubExpr();
2770 const auto* callee = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts());
2771 const bool isCXXMethod{callee and isa<CXXMethodDecl>(callee->getDecl())};
2773 if(2 == stmt->getNumArgs()) {
2774 auto getArg = [&](
unsigned idx) {
2775 const auto* arg = stmt->getArg(idx);
2780 arg = arg->IgnoreImpCasts();
2783 return dyn_cast_or_null<DeclRefExpr>(arg);
2786 const auto* param1 = getArg(0);
2787 const auto* param2 = getArg(1);
2789 if(callee and param1 and param2) {
2790 const std::string replace = [&]() {
2792 auto nameWithTmplArguments = [](
const auto param) {
2796 if(isa<CXXMethodDecl>(callee->getDecl())) {
2797 return StrCat(nameWithTmplArguments(param1),
2801 nameWithTmplArguments(param2),
2806 nameWithTmplArguments(param1),
2808 nameWithTmplArguments(param2),
2819 auto cb = stmt->child_begin();
2820 const auto* fallbackArg0 = stmt->getArg(0);
2824 std::advance(cb, 1);
2826 const auto* arg1 = *cb;
2828 std::advance(cb, 1);
2831 if(not isCXXMethod) {
2834 if(
const auto* adl = dyn_cast_or_null<UnresolvedLookupExpr>(stmt->getCallee())) {
2845 if(isa<DeclRefExpr>(fallbackArg0)) {
2854 const OverloadedOperatorKind opKind = stmt->getOperator();
2862 const auto childRange = llvm::make_range(cb, stmt->child_end());
2865 ForEachArg(childRange, [&](
const auto& child) {
2866 if(not isCXXMethod) {
2919 const bool isConstructor{isa<CXXConstructExpr>(stmt->getSubExpr())};
2920 const bool isStdListInit{isa<CXXStdInitializerListExpr>(stmt->getSubExpr())};
2921 const bool isListInitialization{stmt->getLParenLoc().isInvalid()};
2922 const bool needsParens{not isConstructor and not isListInitialization and not isStdListInit};
2925 if(not isConstructor and not isStdListInit) {
2947 StringStream stream{};
2948 stream.Print(*stmt);
2950 auto str = std::move(stream.str());
2952 if(str ==
"'\\x00'"sv) {
2954 }
else if(str ==
"'\\xff'"sv) {
2966 if(
const auto* functionName = stmt->getFunctionName()) {
2969 const auto name = PredefinedExpr::getIdentKindName(stmt->getIdentKind());
2979 TemporaryDeclFinder temporaryFinder{*
this, not
mProcessingVarDecl ? stmt->getSubExpr() :
nullptr};
2993 const QualType& type = t.getCanonicalType();
2995 if(type->isScalarType()) {
2996 switch(type->getScalarTypeKind()) {
2997 case Type::STK_CPointer:
2998 case Type::STK_BlockPointer:
2999 case Type::STK_ObjCObjectPointer:
3000 case Type::STK_MemberPointer:
return std::string{
kwNullptr};
3002 case Type::STK_Bool:
return std::string{
kwFalse};
3004 case Type::STK_Integral:
3005 case Type::STK_Floating:
3006 if(
const auto* bt = type->getAs<BuiltinType>()) {
3007 switch(bt->getKind()) {
3009 case BuiltinType::Char_U:
3010 case BuiltinType::UChar:
3011 case BuiltinType::Char_S:
3012 case BuiltinType::SChar:
return "'\\0'";
3013 case BuiltinType::WChar_U:
3014 case BuiltinType::WChar_S:
return "L'\\0'";
3015 case BuiltinType::Char16:
return "u'\\0'";
3016 case BuiltinType::Char32:
return "U'\\0'";
3018 case BuiltinType::Half:
3019 case BuiltinType::Float:
return "0.0f";
3020 case BuiltinType::Double:
return "0.0";
3027 case Type::STK_FloatingComplex:
3028 case Type::STK_IntegralComplex:
3029 if(
const auto* complexType = type->getAs<ComplexType>()) {
3035 case Type::STK_FixedPoint:
Error(
"STK_FixedPoint is not implemented");
break;
3038 }
else if(
const auto* tt = dyn_cast_or_null<ConstantArrayType>(t.getTypePtrOrNull())) {
3039 const auto& elementType{tt->getElementType()};
3045 return std::string{
"0"sv};
3081 if(not stmt->getCaughtType().isNull()) {
3082 mOutputFormatHelper.Append(
3083 GetTypeNameAsParameter(stmt->getCaughtType(), stmt->getExceptionDecl()->getName()));
3085 mOutputFormatHelper.Append(kwElipsis);
3088 AddSpaceAtTheEnd::Yes);
3105 if(
const auto value = stmt->getAPValueResult(); value.isInt()) {
3117 const auto& underlyingType = stmt->getUnderlyingType();
3120 P0315Visitor dt{*
this};
3121 dt.TraverseType(underlyingType);
3125 if(
auto* templateSpecializationType = underlyingType->getAs<TemplateSpecializationType>()) {
3126 const bool carriesNamespace{[&] {
3127 if(
const auto tn = templateSpecializationType->getTemplateName();
3128 (TemplateName::QualifiedTemplate == tn.getKind()) or (TemplateName::DependentTemplate == tn.getKind())) {
3129 const auto* qtn = tn.getAsQualifiedTemplateName();
3131 return qtn->getQualifier() !=
nullptr;
3137 if(
const auto* elaboratedType = underlyingType->getAs<ElaboratedType>()) {
3138 if(templateSpecializationType->isSugared() and not carriesNamespace) {
3144 StringStream stream{};
3145 stream.Print(*templateSpecializationType);
3150 }
else if(
auto* dependentTemplateSpecializationType =
3151 underlyingType->getAs<DependentTemplateSpecializationType>()) {
3181 CXXConstructorDecl* cxxInheritedCtorDecl{
nullptr};
3185 if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
3192 for(
OnceTrue first{};
const auto* init : ctor->inits()) {
3195 initOutputFormatHelper.
Append(
": "sv);
3197 initOutputFormatHelper.
Append(
", "sv);
3202 if(
const auto* member = init->getMember()) {
3203 initOutputFormatHelper.
Append(member->getName());
3206 const auto* inlineInit = init->getInit();
3207 bool useCurlies{
false};
3209 if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3210 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3214 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3222 const auto* inlineInit = init->getInit();
3225 if(
const auto* member = init->getMember()) {
3226 initOutputFormatHelper.
Append(member->getName());
3228 if(isa<ParenListExpr>(inlineInit)) {
3234 }
else if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3235 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3241 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3268 if(not stmt->isUserProvided() or stmt->isExplicitlyDefaulted()) {
3275 if(isa<CXXConversionDecl>(stmt)) {
3276 if(stmt->getParent()->isLambda() and not stmt->doesThisDeclarationHaveABody()) {
3281 if(
const auto* invoker = stmt->getParent()->getLambdaStaticInvoker()) {
3282 mOutputFormatHelper.AppendSemiNewLine(invoker->getName());
3284 mOutputFormatHelper.AppendSemiNewLine(kwOperator,
"()"sv);
3290 if((SkipBody::No == skipBody) and stmt->doesThisDeclarationHaveABody() and not stmt->isLambdaStaticInvoker()) {
3299 if(SkipBody::No == skipBody) {
3311 not stmt->isExplicitlyDefaulted() and not stmt->isDeleted());
3321 if(stmt->isScoped()) {
3322 if(stmt->isScopedUsingClassTag()) {
3331 if(stmt->isFixed()) {
3343 ForEachArg(stmt->enumerators(), [&](
const auto* value) {
3345 mOutputFormatHelper.AppendNewLine();
3356 AddSpaceAtTheEnd::No);
3358 mOutputFormatHelper.AppendSemiNewLine();
3359 mOutputFormatHelper.AppendNewLine();
3369 if(
const auto* initExpr = stmt->getInitExpr()) {
3386 static const std::string_view spaces{
" "sv};
3388 if(offset >= spaces.size()) {
3391 return spaces.substr(0, spaces.size() - offset);
3399 P0315Visitor dt{*
this};
3401 auto type =
GetType(stmt->getType());
3402 dt.TraverseType(type);
3407 if(stmt->isMutable()) {
3411 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getParent())) {
3412 std::string name{
GetName(*stmt)};
3415 name = std::move(fieldName.value());
3420 if(
const auto* constantExpr = dyn_cast_or_null<ConstantExpr>(stmt->getBitWidth())) {
3426 if(
const auto* initializer = stmt->getInClassInitializer();
3427 stmt->hasInClassInitializer() and initializer and cxxRecordDecl->isAggregate()) {
3428 const bool isConstructorExpr{isa<CXXConstructExpr>(initializer) or isa<ExprWithCleanups>(initializer)};
3429 if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) {
3440 const auto* fieldClass = stmt->getParent();
3442 auto effectiveFieldSize{
GetGlobalAST().getTypeInfoInChars(type).Width.getQuantity()};
3443 auto getFieldOffsetInBytes = [&recordLayout](
const FieldDecl* field) {
3444 return recordLayout.getFieldOffset(field->getFieldIndex()) / 8;
3446 auto fieldOffset = getFieldOffsetInBytes(stmt);
3458 const auto expectedOffset = fieldOffset + effectiveFieldSize;
3459 const auto nextOffset = [&]() -> uint64_t {
3461 if(
const auto next = stmt->getFieldIndex() + 1; recordLayout.getFieldCount() > next) {
3463 const auto* field = *std::next(fieldClass->fields().begin(), next);
3465 return getFieldOffsetInBytes(field);
3469 return recordLayout.getSize().getQuantity();
3472 if(expectedOffset < nextOffset) {
3473 const auto padding = nextOffset - expectedOffset;
3498 if(not stmt->isFailed()) {
3510 if(stmt->getMessage()) {
3523 if(
const auto& name =
GetName(*stmt->getNominatedNamespace()); not name.empty()) {
3533 if(stmt->isInline()) {
3541 if(not stmt->isAnonymousNamespace()) {
3549 for(
const auto* decl : stmt->decls()) {
3572 if(stmt->shadow_size()) {
3573 for(
const auto* shadow : stmt->shadows()) {
3574 RETURN_IF(isa<ConstructorUsingShadowDecl>(shadow));
3576 if(
const auto* shadowUsing = dyn_cast_or_null<UsingShadowDecl>(shadow)) {
3577 if(
const auto* targetDecl = shadowUsing->getTargetDecl(); not isa<TypeAliasDecl>(targetDecl)) {
3578 UsingCodeGenerator codeGenerator{ofm};
3592 if(not ofm.empty()) {
3617 if(
const auto* typeInfo = stmt->getFriendType()) {
3620 }
else if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(stmt->getFriendDecl())) {
3623 }
else if(
const auto* fdt = dyn_cast_or_null<FunctionTemplateDecl>(stmt->getFriendDecl())) {
3628 if(
const auto* ctd = dyn_cast_or_null<ClassTemplateDecl>(stmt->getFriendDecl())) {
3649 RETURN_IF(DeductionCandidate::Copy == stmt->getDeductionCandidateKind());
3651 const bool isImplicit{stmt->isImplicit()};
3652 const bool noSpecializations = [&] {
3653 if(
const auto* dt = stmt->getDescribedFunctionTemplate()) {
3654 return dt->specializations().empty();
3661 RETURN_IF(not stmt->isUsed() and isImplicit and noSpecializations);
3663 const bool isSpecialization{stmt->isFunctionTemplateSpecialization()};
3664 const bool needsTemplateGuard{isImplicit or isSpecialization};
3666 if(needsTemplateGuard) {
3670 const auto* deducedTemplate = stmt->getDeducedTemplate();
3672 if(isSpecialization) {
3674 }
else if(
const auto* e = stmt->getDescribedFunctionTemplate()) {
3680 if(stmt->getNumParams()) {
3688 if(needsTemplateGuard) {
3707 for(
const auto* spec : stmt->specializations()) {
3709 if(spec->getPreviousDecl()) {
3736 for(
const auto& attr : stmt->getAttrs()) {
3746 if(stmt->hasAttrs()) {
3757 for(
const auto& attr : attrs) {
3766 RETURN_IF(attr::Override == attr.getKind());
3769 RETURN_IF(attr::Final == attr.getKind());
3772 RETURN_IF(attr::NoInline == attr.getKind());
3775 if(
const auto* alignedAttr = dyn_cast_or_null<AlignedAttr>(&attr)) {
3776 auto insert = [&](
const QualType type,
const TemplateTypeParmType* tmplTypeParam) {
3783 Ellipsis(tmplTypeParam->isParameterPack()),
3787 if(alignedAttr->isAlignmentExpr()) {
3788 if(
const auto* unaryExpr = dyn_cast_or_null<UnaryExprOrTypeTraitExpr>(alignedAttr->getAlignmentExpr())) {
3789 if(
const auto* tmplTypeParam =
3790 dyn_cast_or_null<TemplateTypeParmType>(unaryExpr->getArgumentType().getTypePtrOrNull())) {
3791 insert(unaryExpr->getArgumentType(), tmplTypeParam);
3795 }
else if(
const auto* tmplTypeParam =
3796 alignedAttr->getAlignmentType()->getType()->getAs<TemplateTypeParmType>()) {
3797 insert(alignedAttr->getAlignmentType()->getType(), tmplTypeParam);
3804 pp.adjustForCPlusPlus();
3806 attr.printPretty(stream, pp);
3809 std::string_view start{stream.str()};
3825 const auto* classTemplatePartialSpecializationDecl = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(stmt);
3826 const auto* classTemplateSpecializationDecl = dyn_cast_or_null<ClassTemplateSpecializationDecl>(stmt);
3830 const bool isClassTemplateSpecialization{classTemplatePartialSpecializationDecl or classTemplateSpecializationDecl};
3831 const bool tmplRequiresIfDef{[&] {
3832 if(classTemplatePartialSpecializationDecl) {
3833 return classTemplatePartialSpecializationDecl->isImplicit();
3835 }
else if(classTemplateSpecializationDecl) {
3836 return not classTemplateSpecializationDecl->isExplicitInstantiationOrSpecialization();
3843 if(tmplRequiresIfDef) {
3848 if(isClassTemplateSpecialization) {
3849 if(tmplRequiresIfDef) {
3851 classTemplateSpecializationDecl->getPointOfInstantiation());
3855 if(classTemplatePartialSpecializationDecl) {
3861 }
else if(stmt->getLexicalDeclContext() != stmt->getDeclContext()) {
3862 if(
const auto* parent = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
3863 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
3875 if(classTemplateSpecializationDecl) {
3879 if(stmt->hasAttr<FinalAttr>()) {
3884 if(not stmt->hasDefinition() or not stmt->isCompleteDefinition()) {
3889 if(stmt->getNumBases()) {
3892 ForEachArg(stmt->bases(), [&](
const auto& base) {
3893 mOutputFormatHelper.Append(getAccessSpelling(base.getAccessSpecifier()),
3895 ValueOrDefault(base.isVirtual(), kwVirtualSpace),
3896 GetName(base.getType()),
3897 Ellipsis(base.isPackExpansion()));
3904 " /* size: "sv, recordLayout.getSize(),
", align: "sv, recordLayout.getAlignment(),
" */"sv);
3913 for(
size_t offset{};
const auto& base : stmt->bases()) {
3914 const auto& baseRecordLayout =
GetRecordLayout(base.getType()->getAsRecordDecl());
3915 const auto baseVar =
StrCat(
"/* base ("sv,
GetName(base.getType()),
")"sv);
3916 const auto size = baseRecordLayout.getSize().getQuantity();
3919 baseVar,
GetSpaces(baseVar.size()),
" offset: "sv, offset,
", size: "sv, size,
" */"sv);
3929 Decl::Kind formerKind{};
3930 AccessSpecifier lastAccess{stmt->isClass() ? AS_private : AS_public};
3931 for(
const auto* d : stmt->decls()) {
3932 if(isa<CXXRecordDecl>(d) and firstRecordDecl) {
3938 if(not firstDecl and (d->getKind() != formerKind)) {
3942 if((stmt->isLambda() and isa<CXXDestructorDecl>(d)) and not d->isUsed()) {
3948 if(lastAccess != d->getAccess()) {
3949 lastAccess = d->getAccess();
3952 if(not isa<AccessSpecDecl>(d)) {
3959 formerKind = d->getKind();
3962 if(stmt->isLambda()) {
3964 const bool ctorRequired{stmt->capture_size() or stmt->lambdaIsDefaultConstructibleAndAssignable()};
3967 if(AS_public != lastAccess) {
3971 std::string_view p{pub};
3976 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
3979 if(stmt->hasConstexprDefaultConstructor()) {
3987 SmallVector<std::string, 5> ctorInitializerList{};
3988 std::string ctorArguments{
'{'};
3992 [&](std::string_view name,
const FieldDecl* fd,
bool isThis,
const Expr* expr,
bool ) {
3993 if(firstCtorArgument) {
3996 ctorArguments.append(
", "sv);
3999 bool byConstRef{
false};
4001 auto fieldDeclType{fd->getType()};
4004 std::string fname =
StrCat(
"_"sv, name);
4008 if(
const auto* cxxConstructExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4009 cxxConstructExpr and cxxConstructExpr->getConstructor()->isMoveConstructor()) {
4011 OutputFormatHelper ofm{};
4012 LambdaInitCaptureCodeGenerator codeGenerator{ofm,
mLambdaStack, name};
4014 if(cxxConstructExpr->getNumArgs()) {
4016 [&](
const auto& arg) { codeGenerator.InsertArg(arg); });
4019 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4025 }
else if(not fieldDeclType->isReferenceType() and not fieldDeclType->isAnyPointerType() and
4026 not fieldDeclType->isUndeducedAutoType()) {
4028 const auto* exprWithoutImpCasts = expr->IgnoreParenImpCasts();
4031 if(exprWithoutImpCasts->isXValue()) {
4034 OutputFormatHelper ofm{};
4035 LambdaInitCaptureCodeGenerator codeGenerator{ofm,
mLambdaStack, name};
4040 }
else if(exprWithoutImpCasts
4042 or exprWithoutImpCasts->getType().isConstQualified()
4049 if(exprWithoutImpCasts->isPRValue() and isa<CXXBindTemporaryExpr>(exprWithoutImpCasts) and
4050 not exprWithoutImpCasts->getType().isConstQualified()) {
4051 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4053 fname =
StrCat(
"std::move("sv, fname,
")"sv);
4057 fieldDeclType.addConst();
4061 if(exprWithoutImpCasts->isXValue()) {
4062 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4064 }
else if(not isMoved) {
4065 fieldDeclType = stmt->getASTContext().getLValueReferenceType(fieldDeclType);
4069 const std::string_view elips{
4070 Ellipsis(isa_and_nonnull<PackExpansionType>(fieldDeclType->getPointeeType().getTypePtrOrNull()))};
4073 fieldDeclType = fieldDeclType.getCanonicalType();
4075 ctorInitializerList.push_back(
StrCat(fieldName,
"{"sv, fname, elips,
"}"sv));
4077 if(not isThis and expr) {
4079 OutputFormatHelper ofmLambdaInCtor{};
4080 ofmLambdaInCtor.SetIndent(indentAtInsertPosBeforeClass);
4081 CodeGenerator cgLambdaInCtor{ofmLambdaInCtor, LambdaInInitCapture::Yes};
4083 if(P0315Visitor dt{cgLambdaInCtor}; dt.TraverseStmt(
const_cast<Expr*
>(expr))) {
4085 OutputFormatHelper ofm{};
4088 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4089 ctorExpr and byConstRef and (1 == ctorExpr->getNumArgs())) {
4090 codeGenerator->
InsertArg(ctorExpr->getArg(0));
4100 ctorArguments.append(ofm);
4103 OutputFormatHelper ofm{};
4104 LambdaNameOnlyCodeGenerator ccg{ofm};
4105 ccg.InsertArg(expr);
4107 ctorArguments.append(ofm.GetString());
4112 if(isThis and not fieldDeclType->isPointerType()) {
4113 ctorArguments.append(
"*"sv);
4116 ctorArguments.append(name);
4122 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
4123 FieldDecl* thisCapture{};
4125 stmt->getCaptureFields(captures, thisCapture);
4129 const auto* captureInit =
mLambdaExpr->capture_init_begin();
4131 addToInits(
kwThis, thisCapture,
true, *captureInit,
false);
4138 if(not c.capturesVariable()) {
4142 const auto* capturedVar = c.getCapturedVar();
4143 if(
const auto* value = captures[capturedVar]) {
4145 if(
const auto* bindingDecl = dyn_cast_or_null<BindingDecl>(capturedVar)) {
4146 const auto* decompositionDecl = cast<DecompositionDecl>(bindingDecl->getDecomposedDecl());
4147 addToInits(
GetName(*capturedVar),
4151 VarDecl::ListInit == decompositionDecl->getInitStyle());
4155 addToInits(
GetName(*capturedVar),
4159 VarDecl::ListInit == dyn_cast_or_null<VarDecl>(capturedVar)->getInitStyle());
4163 ctorArguments.append(
"}"sv);
4170 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
4176 for(
OnceTrue firstCtorInitializer{};
const auto& initializer : ctorInitializerList) {
4177 if(firstCtorInitializer) {
4218 for(
const auto* decl : stmt->decls()) {
4232 if(stmt->isPartiallySubstituted()) {
4234 }
else if(not stmt->isValueDependent()) {
4249 TemporaryDeclFinder temporaryFinder{*
this, stmt->getRetValue(),
true};
4253 if(
const auto* retVal = stmt->getRetValue()) {
4256 if(not temporaryFinder.Found()) {
4257 if(
const auto* nrvoVD = stmt->getNRVOCandidate()) {
4298 if(
const auto* namedConcept = stmt->getNamedConcept()) {
4303 if(not stmt->isValueDependent()) {
4315 const auto localParameters = stmt->getLocalParameters();
4317 not localParameters.empty(),
4318 [&] { mOutputFormatHelper.AppendParameterList(localParameters); },
4319 AddSpaceAtTheEnd::Yes);
4327 for(
const auto& requirement : stmt->getRequirements()) {
4328 if(
const auto* typeRequirement = dyn_cast_or_null<concepts::TypeRequirement>(requirement)) {
4329 if(typeRequirement->isSubstitutionFailure()) {
4336 }
else if(
const auto* exprRequirement = dyn_cast_or_null<concepts::ExprRequirement>(requirement)) {
4337 if(exprRequirement->isExprSubstitutionFailure()) {
4342 WrapInCurliesIfNeeded(exprRequirement->isCompound(), [&] { InsertArg(exprRequirement->getExpr()); });
4344 if(exprRequirement->hasNoexceptRequirement()) {
4348 if(
const auto& returnTypeRequirement = exprRequirement->getReturnTypeRequirement();
4349 not returnTypeRequirement.isEmpty()) {
4351 not typeConstraint.empty()) {
4356 }
else if(
const auto* nestedRequirement = dyn_cast_or_null<concepts::NestedRequirement>(requirement)) {
4359 if(nestedRequirement->hasInvalidConstraint()) {
4364 InsertArg(nestedRequirement->getConstraintExpr());
4385 const auto typeName{
GetName(stmt->getType(), Unqualified::Yes)};
4391 const auto* subExpr = stmt->getSubExpr();
4393 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(subExpr); dref and
GetInsightsOptions().ShowLifetime) {
4394 const auto size =
GetSize(dyn_cast_or_null<ConstantArrayType>(subExpr->getType()));
4400 std::string modifiers{};
4404 auto& ofmToInsert = [&]() ->
decltype(
auto) {
4416 OutputFormatHelper ofm{};
4417 ofm.SetIndent(ofmToInsert, OutputFormatHelper::SkipIndenting::Yes);
4419 const auto size = [&]() ->
size_t {
4420 if(
const auto* mat = dyn_cast<MaterializeTemporaryExpr>(subExpr)) {
4421 if(
const auto* list = dyn_cast_or_null<InitListExpr>(mat->getSubExpr())) {
4422 return list->getNumInits();
4429 auto internalListName =
4435 ofm.AppendSemiNewLine();
4437 ofmToInsert.InsertAt(variableInsertPos, ofm);
4472#define SUPPORTED_DECL(type) \
4473 if(isa<type>(stmt)) { \
4474 InsertArg(static_cast<const type*>(stmt)); \
4478#define IGNORED_DECL SUPPORTED_DECL