21 #include "clang/AST/RecordLayout.h"
22 #include "clang/Frontend/CompilerInstance.h"
23 #include "clang/Sema/Sema.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/Support/Path.h"
29 #define LAMBDA_SCOPE_HELPER(type) \
30 LambdaScopeHandler lambdaScopeHandler{mLambdaStack, mOutputFormatHelper, LambdaCallerType::type};
34 #define CONDITIONAL_LAMBDA_SCOPE_HELPER(type, cond) \
35 std::optional<LambdaScopeHandler> lambdaScopeHandler; \
37 lambdaScopeHandler.emplace(mLambdaStack, mOutputFormatHelper, LambdaCallerType::type); \
41 namespace ranges = std::ranges;
45 #define BUILD_OPT_AND(name, param) std::function name = [](param t) -> MyOptional<param>
46 #define BUILD_OPT_AND_O(name, param, ret) std::function name = [](param t) -> MyOptional<ret>
50 if(t->isPointerType()) {
68 if(isa<T>(t.getTypePtrOrNull())) {
77 return t.getType().getCanonicalType();
82 std::string accessStr{getAccessSpelling(access)};
83 if(not accessStr.empty()) {
91 using namespace asthelpers;
93 static std::string_view
GetCastName(
const CastKind castKind,
bool constnessChange =
false)
95 if(
is{castKind}.
any_of(CastKind::CK_BitCast, CastKind::CK_IntegralToPointer, CastKind::CK_PointerToIntegral)) {
99 if((CastKind::CK_NoOp == castKind) and constnessChange) {
100 return "const_cast"sv;
112 }
else if(decl.isUnion()) {
123 const uint64_t mIndex;
133 void InsertArg(
const ArrayInitIndexExpr*)
override { mOutputFormatHelper.Append(mIndex); }
143 std::string mVarName;
148 , mVarName{std::move(varName)}
153 void InsertArg(
const DeclRefExpr* stmt)
override;
154 void InsertArg(
const BindingDecl* stmt)
override;
157 void InsertDecompositionBindings(
const DecompositionDecl& decompositionDeclStmt);
178 InsertCXXMethodDecl(stmt, SkipBody::Yes);
204 std::string_view varName)
205 :
CodeGenerator{outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
217 if(isa<VarDecl>(stmt->getDecl())) {
218 mOutputFormatHelper.Append(
"_"sv, mVarName);
227 std::string_view mVarName;
245 , mHelper{lambdaCallerType, GetBuffer(outputFormatHelper)}
247 mStack.
push(mHelper);
253 if(not mStack.empty()) {
254 mStack.pop()->finish();
264 for(
auto& l : mStack) {
265 switch(l.callerType()) {
277 return outputFormatHelper;
283 return isArrow ?
"->"sv :
"."sv;
311 if(not stmt->isImplicitAccess()) {
325 auto& langOpts{
GetLangOpts(*rangeForStmt->getLoopVariable())};
326 const bool onlyCpp11{not langOpts.CPlusPlus17};
328 auto* rwStmt =
const_cast<CXXForRangeStmt*
>(rangeForStmt);
330 StmtsContainer outerScopeStmts{};
333 outerScopeStmts.Add(rangeForStmt->getInit());
336 outerScopeStmts.Add(rangeForStmt->getRangeStmt());
339 outerScopeStmts.Add(rangeForStmt->getBeginStmt());
340 outerScopeStmts.Add(rangeForStmt->getEndStmt());
344 StmtsContainer bodyStmts{};
345 bodyStmts.Add(rangeForStmt->getLoopVarStmt());
348 bodyStmts.AddBodyStmts(rwStmt->getBody());
350 const auto& ctx = rangeForStmt->getLoopVariable()->getASTContext();
354 auto* declStmt = [&]() -> DeclStmt* {
356 return mkDeclStmt(rwStmt->getBeginStmt() ? rwStmt->getBeginStmt()->getSingleDecl() :
nullptr,
357 rwStmt->getEndStmt() ? rwStmt->getEndStmt()->getSingleDecl() :
nullptr);
363 auto* innerScope =
mkCompoundStmt(bodyStmts, rangeForStmt->getBeginLoc(), rangeForStmt->getEndLoc());
365 auto* forStmt =
new(ctx) ForStmt(ctx,
368 rwStmt->getLoopVariable(),
371 rangeForStmt->getBeginLoc(),
372 rangeForStmt->getEndLoc(),
373 rangeForStmt->getEndLoc());
375 outerScopeStmts.Add(forStmt);
377 auto* outerScope =
mkCompoundStmt(outerScopeStmts, rangeForStmt->getBeginLoc(), rangeForStmt->getEndLoc());
386 const NestedNameSpecifier* qualifier,
387 const bool hasTemplateKeyword)
391 declName.getAsString());
415 const auto* templatedDecl = stmt->getTemplatedDecl();
435 for(
OnceTrue first{};
const auto* spec : stmt->specializations()) {
436 if(TSK_ExplicitSpecialization == spec->getSpecializationKind()) {
526 if(stmt->getSubStmt()) {
534 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
558 auto* rwStmt =
const_cast<WhileStmt*
>(stmt);
559 auto* conditionVar{rwStmt->getConditionVariable()};
575 if(not conditionVar) {
579 StmtsContainer bodyStmts{};
581 bodyStmts.AddBodyStmts(rwStmt->getBody());
582 bodyStmts.AddBodyStmts(
Assign(conditionVar, conditionVar->getInit()));
598 const CXXRecordDecl& cxxRecordDecl)
600 if(cxxRecordDecl.isLambda()) {
601 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
603 FieldDecl* thisCapture{};
605 cxxRecordDecl.getCaptureFields(captures, thisCapture);
607 if(&fieldDecl == thisCapture) {
610 for(
const auto& [key, value] : captures) {
611 if(&fieldDecl == value) {
630 const auto* base = stmt->getBase();
631 const bool skipBase{[&] {
632 if(
const auto* implicitCast = dyn_cast_or_null<ImplicitCastExpr>(base)) {
633 if(CastKind::CK_UncheckedDerivedToBase == implicitCast->getCastKind()) {
635 return isa<CXXThisExpr>(implicitCast->IgnoreImpCasts());
648 const auto* meDecl = stmt->getMemberDecl();
649 bool skipTemplateArgs{
false};
650 const auto name = [&]() -> std::string {
653 if(
const auto* m = dyn_cast_or_null<CXXMethodDecl>(meDecl)) {
654 if(
const auto* rd = m->getParent(); rd and rd->isLambda() and isa<CXXConversionDecl>(m)) {
655 skipTemplateArgs =
true;
662 else if(
const auto* fd = dyn_cast_or_null<FieldDecl>(meDecl)) {
663 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(fd->getParent())) {
665 return fieldName.value();
673 if(
const auto* convDecl = dyn_cast_or_null<CXXConversionDecl>(meDecl)) {
677 return stmt->getMemberNameInfo().getName().getAsString();
690 if(
const auto cxxMethod = dyn_cast_or_null<CXXMethodDecl>(meDecl)) {
691 if(
const auto* tmplArgs = cxxMethod->getTemplateSpecializationArgs()) {
692 OutputFormatHelper ofm{};
697 for(
OnceFalse needsComma{};
const auto& arg : tmplArgs->asArray()) {
698 if(arg.getKind() == TemplateArgument::Integral) {
699 ofm.AppendComma(needsComma);
701 ofm.Append(arg.getAsIntegral());
712 }
else if(not isa<CXXConversionDecl>(meDecl)) {
725 if(not stmt->isArgumentType()) {
726 const auto* argExpr = stmt->getArgumentExpr();
727 const bool needsParens{not isa<ParenExpr>(argExpr)};
739 const auto& type = stmt->getType();
740 const bool isSigned = type->isSignedIntegerType();
759 if(stmt->isTypeOperand()) {
760 mOutputFormatHelper.Append(GetName(stmt->getTypeOperand(const_cast<ASTContext&>(GetGlobalAST()))));
762 InsertArg(stmt->getExprOperand());
772 BackupAndRestore _{
mLastExpr, stmt->getLHS()};
774 const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
779 const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
788 const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
794 const bool needCast{stmt->getLHS()->getType() != stmt->getComputationLHSType()};
800 clang::ExprResult res = stmt->getLHS();
804 if(
const auto resultingType =
GetGlobalCI().getSema().PrepareScalarCast(res, stmt->getComputationLHSType());
805 resultingType != CK_NoOp) {
806 const QualType castDestType = stmt->getComputationLHSType();
807 FormatCast(kwStaticCast, castDestType, stmt->getLHS(), resultingType);
809 InsertArg(stmt->getLHS());
814 " "sv, BinaryOperator::getOpcodeStr(BinaryOperator::getOpForCompoundAssignment(stmt->getOpcode())),
" "sv);
816 const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
836 return VarDecl::getStorageClassSpecifierString(sc);
847 if(not ret.empty()) {
857 std::string qualifiers{};
859 if(vd.isInline() or vd.isInlineSpecified()) {
865 if(vd.isConstexpr()) {
875 std::string name{std::move(defaultName)};
877 if(
const auto* tvd = dyn_cast_or_null<VarTemplateSpecializationDecl>(decl)) {
881 codeGenerator->InsertTemplateArgs(tvd->getTemplateArgs());
883 name += outputFormatHelper;
900 if(isa<DecompositionDecl>(expr->getDecl())) {
907 for(
const auto* child : stmt->children()) {
932 bool mHaveTemporary{};
934 std::string mTempName{};
935 std::vector<VarDecl*> mDecls{};
939 : codeGenerator{_codeGenerator}
940 , mPrevStmt{const_cast<
Stmt*>(stmt)}
946 for(
auto d : mDecls) {
952 if(
auto* expr = dyn_cast_or_null<CXXConstructExpr>(stmt)) {
957 auto* vd =
Variable(mTempName, expr->getType(), dummy->getDeclContext());
958 dummy->getDeclContext()->addDecl(vd);
959 vd->setInit(
const_cast<CXXConstructExpr*
>(expr));
960 vd->setStorageClass(SC_None);
964 auto* vd = ImplicitParamDecl::Create(
const_cast<ASTContext&
>(ctx),
965 ctx.getTranslationUnitDecl(),
967 &ctx.Idents.get(mTempName),
969 ImplicitParamKind::Other);
976 }
else if(
auto* expr = dyn_cast_or_null<InitListExpr>(stmt)) {
978 auto* vd =
Variable(mTempName, expr->getType());
979 vd->setInit(
const_cast<InitListExpr*
>(expr));
992 bool Found()
const {
return mFound; }
994 std::string
Name()
const {
return mTempName; }
1001 auto* vd =
Variable(mTempName, expr->getType());
1007 auto* ctorConstructExpr = CXXConstructExpr::Create(
GetGlobalAST(),
1009 expr->getBeginLoc(),
1010 expr->getConstructor(),
1012 {expr->getArgs(), expr->getNumArgs()},
1013 expr->hadMultipleCandidates(),
1014 expr->isListInitialization(),
1015 expr->isStdInitListInitialization(),
1016 expr->requiresZeroInitialization(),
1017 expr->getConstructionKind(),
1018 expr->getParenOrBraceRange());
1020 vd->setInit(ctorConstructExpr);
1026 mDecls.push_back(vd);
1030 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr* stmt)
1034 const auto name =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"temp"sv);
1037 auto* vd =
Variable(name, stmt->getType());
1051 vd->setInit(stmt->getSubExpr());
1056 if(SD_FullExpression == stmt->getStorageDuration() and not mHaveTemporary) {
1058 mHaveTemporary =
true;
1059 }
else if(
const auto* extending = stmt->getExtendingDecl()) {
1063 mDecls.push_back(vd);
1068 auto* tmp = mPrevStmt;
1071 for(
auto* child : stmt->children()) {
1087 static SmallVector<std::pair<std::pair<const CXXRecordDecl*, const CXXRecordDecl*>, VarDecl*>, 10>
1095 auto iter = std::ranges::find_if(
1096 gVtables, [&](
const auto& e) {
return (e.first.first == record) and (e.first.second == recordB); });
1099 iter = std::ranges::find_if(
gVtables, [&](
const auto& e) {
return e.first.first == record; });
1102 return std::distance(
gVtables.begin(), iter);
1106 void PushVtableEntry(
const CXXRecordDecl* record,
const CXXRecordDecl* recordB, VarDecl* decl)
1108 gVtables.push_back({{record, recordB}, decl});
1137 ofm.AppendNewLine();
1141 SmallVector<Expr*, 16> mInitExprs{};
1148 ofm.AppendNewLine();
1152 vtable->setInit(
InitList(mInitExprs, vtable->getType()));
1154 cg->InsertArg(vtable);
1156 ofm.AppendNewLine();
1159 cg->InsertArg(cxaStartFun);
1170 ofm.AppendNewLine();
1171 cg->InsertArg(cxaAtExitFun);
1173 return ofm.GetString();
1198 return stmt and stmt->getNumExprs() and isa_and_nonnull<PackExpansionExpr>(stmt->getExpr(0)) and
1199 stmt->getType().isNull();
1208 for(
const auto* decl : stmt->decls()) {
1220 pp.adjustForCPlusPlus();
1224 ::llvm::raw_string_ostream stream{init};
1225 param.printAsInit(stream, pp);
1233 "static constexpr ",
GetName(param.getType().getUnqualifiedType()),
" ", varName, init);
1241 for(
const auto& arg : array) {
1242 if(TemplateArgument::Declaration != arg.getKind()) {
1244 }
else if(
const auto decl = dyn_cast_or_null<TemplateParamObjectDecl>(arg.getAsDecl())) {
1253 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(&decl)) {
1254 if(
const auto* specArgs = fd->getTemplateSpecializationArgs()) {
1257 }
else if(
const auto* vd = dyn_cast_or_null<VarTemplateSpecializationDecl>(&decl)) {
1259 }
else if(
const auto* clsTemplateSpe = dyn_cast_or_null<ClassTemplateSpecializationDecl>(&decl)) {
1269 if(
auto* init = stmt->getInit();
1271 (not(isa<CallExpr>(init) or
1272 (isa<ExprWithCleanups>(init) and
1273 (isa<CallExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr()) or
1274 isa<MaterializeTemporaryExpr>(dyn_cast_or_null<ExprWithCleanups>(init)->getSubExpr())))))) {
1282 if(BindingDeclFinder isBindingDecl{}; isBindingDecl.Find(stmt->getInit())) {
1289 TemporaryDeclFinder temporaryFinder{*
this, stmt->getInit()};
1297 const bool needsGuard = stmt->isOutOfLine() and isTemplateInstantiation(stmt->getTemplateSpecializationKind());
1301 if(stmt->isOutOfLine()) {
1302 if(
const auto* recordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
1303 if(
const auto* classTmpl = recordDecl->getDescribedClassTemplate()) {
1309 if(isa<VarTemplateSpecializationDecl>(stmt)) {
1311 }
else if(needsGuard) {
1325 const bool isMemberPointer{isa<MemberPointerType>(desugaredType.getTypePtrOrNull())};
1326 if(desugaredType->isFunctionPointerType() or isMemberPointer) {
1327 const auto lineNo =
GetSM(*stmt).getSpellingLineNumber(stmt->getSourceRange().getBegin());
1329 const auto funcPtrName{
StrCat(ptrPrefix, lineNo)};
1337 const auto scope = [&] {
1338 if(
const auto* ctx = stmt->getDeclContext(); stmt->getLexicalDeclContext() != ctx) {
1339 OutputFormatHelper scopeOfm{};
1340 scopeOfm.Append(
GetDeclContext(ctx, WithTemplateParameters::Yes));
1345 return std::string{};
1354 const std::string_view pointer = [&]() {
1359 if(stmt->getType()->isAnyPointerType()) {
1368 if(
const auto* init = stmt->getInit()) {
1369 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init);
1384 if(stmt->hasGlobalStorage()) {
1387 stmt->getType(), stmt,
ArgsToExprVector(ctorExpr), DoCast::No, AsReference::Yes);
1403 if(MyOptional<const InitListExpr*> initList{dyn_cast_or_null<InitListExpr>(init)};
1405 initList.and_then(CanonicalType).and_then(Isa<RecordType>).and_not(IsPointer).and_then(IsPOD) and
1406 not isa<ArrayType>(stmt->getType())) {
1411 if(stmt->hasGlobalStorage()) {
1420 initList.and_then(CanonicalType)
1421 .and_then(Isa<RecordType>)
1424 (0 == initList.value()->getNumInits()))) {
1428 if(not(ctorExpr and ctorExpr->getConstructor()->isDefaultConstructor() and
1429 ctorExpr->getConstructor()->getParent()->hasTrivialDefaultConstructor())) {
1431 const bool isPrimaryTemplatePackExpansionExpr{
1434 if(not isa<CXXParenListInitExpr>(init) and not isPrimaryTemplatePackExpansionExpr) {
1440 stmt->getType()->isRValueReferenceType()) {
1442 if(GetInsightsOptions().UseShow2C) {
1443 mOutputFormatHelper.Append(
"&");
1457 if(stmt->isNRVOVariable()) {
1466 if(
const auto* decompDecl = dyn_cast_or_null<DecompositionDecl>(stmt)) {
1469 codeGenerator.InsertDecompositionBindings(*decompDecl);
1481 if(not(cxxMethodDecl and cxxMethodDecl->isLambdaStaticInvoker())) {
1494 if(not cxxMethodDecl->getReturnType()->isVoidType()) {
1500 if(cxxMethodDecl->isFunctionTemplateSpecialization()) {
1504 if(cxxMethodDecl->isTemplated()) {
1505 if(cxxMethodDecl->getDescribedTemplate()) {
1507 TemplateParamsOnly::Yes);
1516 OutputFormatHelper::NameOnly::Yes,
1517 OutputFormatHelper::GenMissingParamName::Yes);
1532 const SourceLocation& instLoc,
1533 std::string_view text)
1535 const auto lineNo = sm.getSpellingLineNumber(instLoc);
1536 const auto& fileId = sm.getFileID(instLoc);
1537 if(
const auto file = sm.getFileEntryRefForID(fileId)) {
1538 const auto fileWithDirName = file->getName();
1539 const auto fileName = llvm::sys::path::filename(fileWithDirName);
1542 text =
"First instantiated from: "sv;
1552 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1561 if(stmt->isTemplateInstantiation() and stmt->isFunctionTemplateSpecialization()) {
1584 if(isa<CoyieldExpr>(stmt)) {
1591 if(
const auto* matTemp = dyn_cast_or_null<MaterializeTemporaryExpr>(stmt->getCommonExpr())) {
1592 const auto* temporary = matTemp->getSubExpr();
1594 if(
const auto* memExpr = dyn_cast_or_null<CXXMemberCallExpr>(temporary)) {
1595 ForEachArg(memExpr->arguments(), [&](
const auto& arg) { InsertArg(arg); });
1601 }
else if(
const auto* unaryexpr = dyn_cast_or_null<UnaryOperator>(stmt->getOperand())) {
1602 if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(unaryexpr->getSubExpr())) {
1618 auto IsPrimaryTemplate = [&] {
1620 if(
const auto* cxxMethod = dyn_cast_or_null<CXXMethodDecl>(stmt)) {
1621 if(
const auto* tmpl = cxxMethod->getParent()->getDescribedClassTemplate();
1622 tmpl and not isa<ClassTemplateSpecializationDecl>(cxxMethod->getParent())) {
1627 return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind()) or
1631 if(stmt->doesThisDeclarationHaveABody()) {
1636 if(
const auto* corBody = dyn_cast_or_null<CoroutineBodyStmt>(stmt->getBody());
1637 (
nullptr != corBody) and not IsPrimaryTemplate() and
GetInsightsOptions().ShowCoroutineTransformation) {
1640 codeGenerator.InsertCoroutine(*stmt, corBody);
1642 const auto exSpec = stmt->getExceptionSpecType();
1643 const bool showNoexcept =
1647 if(stmt->hasImplicitReturnZero()) {
1649 [](
const Stmt* e) { return isa<ReturnStmt>(e); });
1652 const auto* body = stmt->getBody();
1661 for(
const auto* param : stmt->parameters()) {
1662 auto paramType = param->getType();
1663 const bool isPassByValue{not paramType->isPointerType() and not paramType->isReferenceType()};
1664 if(
const auto* rd = paramType->getAsRecordDecl(); rd and isPassByValue) {
1688 dt.TraverseType(stmt->getReturnType());
1691 for(
const auto& param : stmt->parameters()) {
1692 P0315Visitor dt{*
this};
1693 dt.TraverseType(param->getType());
1697 if(
const auto* deductionGuide = dyn_cast_or_null<CXXDeductionGuideDecl>(stmt)) {
1699 }
else if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
1704 RETURN_IF(isa<CXXConversionDecl>(stmt) and not stmt->hasBody());
1722 if(typeConstraint) {
1724 sstream.
Print(*typeConstraint);
1726 return sstream.str();
1750 expr = expr->IgnoreParenImpCasts();
1753 if(Expr::EvalResult evalResult{};
1754 isa<CXXFunctionalCastExpr>(expr) and
1755 expr->EvaluateAsConstantExpr(evalResult,
GetGlobalAST(), ConstantExprKind::Normal)) {
1756 return std::pair<QualType, APValue>{expr->getType(), evalResult.Val};
1764 const TemplateParamsOnly templateParamsOnly)
1766 const bool full{TemplateParamsOnly::No == templateParamsOnly};
1769 for(
const auto* param : list) {
1770 if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param);
1771 nonTmplParam and nonTmplParam->hasDefaultArgument()) {
1774 auto* init =
GetGlobalAST().getTemplateParamObjectDecl(val->first, val->second);
1786 for(
OnceFalse needsComma{};
const auto* param : list) {
1789 const auto& typeName =
GetName(*param);
1791 if(
const auto* tt = dyn_cast_or_null<TemplateTypeParmDecl>(param)) {
1793 if(tt->wasDeclaredWithTypename()) {
1795 }
else if(not tt->hasTypeConstraint()) {
1802 if(0 == typeName.size() or tt->isImplicit() ) {
1807 not typeConstraint.empty()) {
1816 if(tt->hasDefaultArgument() and not tt->defaultArgumentWasInherited()) {
1817 const auto& defaultArg = tt->getDefaultArgument();
1819 if(
const auto decltypeType = dyn_cast_or_null<DecltypeType>(defaultArg.getArgument().getAsType())) {
1822 InsertArg(decltypeType->getUnderlyingExpr());
1830 }
else if(
const auto* nonTmplParam = dyn_cast_or_null<NonTypeTemplateParmDecl>(param)) {
1832 if(
const auto nttpType = nonTmplParam->getType();
1833 nttpType->isFunctionPointerType() or nttpType->isMemberFunctionPointerType()) {
1838 GetName(nttpType),
" "sv,
Ellipsis(nonTmplParam->isParameterPack()), typeName);
1841 if(nonTmplParam->hasDefaultArgument()) {
1848 }
else if(
const auto* tmplTmplParam = dyn_cast_or_null<TemplateTemplateParmDecl>(param)) {
1853 if(tmplTmplParam->hasDefaultArgument()) {
1880 SmallVector<const ClassTemplateSpecializationDecl*, 10> specializations{};
1883 for(
const auto* spec : stmt->specializations()) {
1886 if(TSK_ImplicitInstantiation == spec->getSpecializationKind()) {
1887 specializations.push_back(spec);
1892 ranges::sort(specializations,
1893 [](
const ClassTemplateSpecializationDecl* a,
const ClassTemplateSpecializationDecl* b) {
1894 return a->getPointOfInstantiation() < b->getPointOfInstantiation();
1897 for(
const auto* spec : specializations) {
1905 for(
OnceFalse needsComma{};
const auto& expr : stmt->children()) {
1925 OnceFalse needsComma{uint64_t{0} != startAt};
1926 for_each(startAt, size, [&](
auto) {
1927 ret.AppendComma(needsComma);
1932 return ret.GetString();
1943 ((stmt->getNumInits() > 1) or stmt->getArrayFiller() or
1944 ((0 < stmt->getNumInits()) and isa<ImplicitValueInitExpr>(stmt->getInit(0))))),
1946 mOutputFormatHelper.IncreaseIndent();
1948 ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); });
1951 if(stmt->getType().getCanonicalType()->isScalarType()) {
1962 if(
const auto* filler = stmt->getArrayFiller()) {
1963 OutputFormatHelper ofm{};
1968 dyn_cast_or_null<ConstantArrayType>(stmt->getType().getTypePtrOrNull()),
1970 stmt->getNumInits());
1976 mOutputFormatHelper.DecreaseIndent();
1980 void CodeGenerator::InsertArg(
const CXXDefaultInitExpr* stmt)
1982 const auto* subExpr = stmt->getExpr();
1984 InsertCurlysIfRequired(subExpr);
1988 void CodeGenerator::InsertArg(
const CXXDeleteExpr* stmt)
1990 mOutputFormatHelper.Append(
kwDelete);
1992 if(stmt->isArrayForm()) {
1993 mOutputFormatHelper.Append(
"[]"sv);
1996 mOutputFormatHelper.Append(
' ');
1998 InsertArg(stmt->getArgument());
2002 void CodeGenerator::InsertConstructorExpr(
const auto* stmt)
2008 dt.TraverseType(stmt->getType());
2010 if(not mLambdaStack.empty()) {
2011 for(
const auto& e : mLambdaStack) {
2012 RETURN_IF((LambdaCallerType::MemberCallExpr == e.callerType()) and isa<DecltypeType>(stmt->getType()));
2017 mOutputFormatHelper.Append(
GetName(stmt->getType(), Unqualified::Yes));
2019 const BraceKind braceKind =
ValueOr(stmt->isListInitialization(), BraceKind::Curlys, BraceKind::Parens);
2021 WrapInParensOrCurlys(braceKind, [&]() {
2022 if(
const auto& arguments = stmt->arguments(); not arguments.empty()) {
2023 ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); });
2029 void CodeGenerator::InsertArg(
const CXXConstructExpr* stmt)
2031 InsertConstructorExpr(stmt);
2035 void CodeGenerator::InsertArg(
const CXXUnresolvedConstructExpr* stmt)
2037 BackupAndRestore _{mNoEmptyInitList, NoEmptyInitList::Yes};
2039 InsertConstructorExpr(stmt);
2043 void CodeGenerator::InsertArg(
const UnresolvedMemberExpr* stmt)
2049 mOutputFormatHelper.Append(stmt->getMemberNameInfo().getAsString());
2051 if(stmt->getNumTemplateArgs()) {
2052 InsertTemplateArgs(*stmt);
2057 void CodeGenerator::InsertArg(
const PackExpansionExpr* stmt)
2059 InsertArg(stmt->getPattern());
2064 void CodeGenerator::InsertArg(
const CXXFoldExpr* stmt)
2066 auto operatorStr = BinaryOperator::getOpcodeStr(stmt->getOperator());
2070 const auto* init = stmt->getInit();
2072 if(stmt->isLeftFold()) {
2075 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2081 InsertArg(stmt->getPattern());
2083 if(stmt->isRightFold()) {
2084 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv,
kwElipsis);
2087 mOutputFormatHelper.Append(
" "sv, operatorStr,
" "sv);
2095 void CodeGenerator::InsertArg(
const CXXInheritedCtorInitExpr* stmt)
2097 const auto& constructorDecl = *stmt->getConstructor();
2100 WrapInParens([&]() {
2101 mOutputFormatHelper.AppendParameterList(constructorDecl.parameters(),
2102 OutputFormatHelper::NameOnly::Yes,
2103 OutputFormatHelper::GenMissingParamName::Yes);
2108 bool CodeGenerator::InsideDecltype()
const
2110 return (not mLambdaStack.empty()) and (LambdaCallerType::Decltype == mLambdaStack.back().callerType());
2114 void CodeGenerator::InsertArg(
const CXXPseudoDestructorExpr* stmt)
2116 InsertArg(stmt->getBase());
2118 mOutputFormatHelper.Append(
ArrowOrDot(stmt->isArrow()),
"~",
GetName(stmt->getDestroyedType()));
2122 void CodeGenerator::InsertArg(
const CXXMemberCallExpr* stmt)
2126 InsertArg(stmt->getCallee());
2128 WrapInParens([&]() { ForEachArg(stmt->arguments(), [&](
const auto& arg) { InsertArg(arg); }); });
2132 void CodeGenerator::InsertArg(
const ParenExpr* stmt)
2134 WrapInParens([&]() { InsertArg(stmt->getSubExpr()); });
2138 void CodeGenerator::InsertArg(
const CXXParenListInitExpr* stmt)
2140 WrapInParens([&]() { ForEachArg(stmt->getInitExprs(), [&](
const auto& init) { InsertArg(init); }); });
2144 void CodeGenerator::InsertArg(
const UnaryOperator* stmt)
2146 StringRef opCodeName = UnaryOperator::getOpcodeStr(stmt->getOpcode());
2147 const bool insertBefore{not stmt->isPostfix()};
2150 mOutputFormatHelper.Append(opCodeName);
2153 InsertArg(stmt->getSubExpr());
2155 if(not insertBefore) {
2156 mOutputFormatHelper.Append(opCodeName);
2161 void CodeGenerator::InsertArg(
const StringLiteral* stmt)
2163 StringStream stream{};
2164 stream.Print(*stmt);
2166 mOutputFormatHelper.Append(stream.str());
2170 void CodeGenerator::InsertArg(
const ArrayInitIndexExpr* stmt)
2172 Error(stmt,
"ArrayInitIndexExpr should not be reached in CodeGenerator");
2176 void CodeGenerator::InsertArg(
const ArraySubscriptExpr* stmt)
2178 if((not
GetInsightsOptions().UseAltArraySubscriptionSyntax) or stmt->getLHS()->isLValue()) {
2179 InsertArg(stmt->getLHS());
2181 mOutputFormatHelper.Append(
'[');
2182 InsertArg(stmt->getRHS());
2183 mOutputFormatHelper.Append(
']');
2186 mOutputFormatHelper.Append(
"(*("sv);
2187 InsertArg(stmt->getLHS());
2188 mOutputFormatHelper.Append(
" + "sv);
2190 InsertArg(stmt->getRHS());
2191 mOutputFormatHelper.Append(
"))"sv);
2196 void CodeGenerator::InsertArg(
const ArrayInitLoopExpr* stmt)
2198 WrapInCurlys([&]() {
2199 const uint64_t size = stmt->getArraySize().getZExtValue();
2202 ArrayInitCodeGenerator codeGenerator{mOutputFormatHelper, i};
2203 codeGenerator.
InsertArg(stmt->getSubExpr());
2209 void CodeGenerator::InsertArg(
const OpaqueValueExpr* stmt)
2211 InsertArg(stmt->getSourceExpr());
2215 void CodeGenerator::InsertArg(
const CallExpr* stmt)
2217 const bool insideDecltype{InsideDecltype()};
2220 if(insideDecltype) {
2221 mLambdaStack.back().setInsertName(
true);
2224 UpdateCurrentPos(mCurrentCallExprPos);
2226 InsertArg(stmt->getCallee());
2228 if(
const auto* declRefExpr = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts())) {
2229 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(declRefExpr->getDecl())) {
2230 if((not declRefExpr->getNumTemplateArgs() and
GetInsightsOptions().ShowAllCallExprTemplateParameters) or
2231 isa<UserDefinedLiteral>(stmt)) {
2232 InsertTemplateArgs(*fd);
2237 WrapInParens([&]() {
2238 auto* funcDecl = dyn_cast_or_null<FunctionDecl>(stmt->getCalleeDecl());
2241 ForEachArg(stmt->arguments(), [&](
const auto* arg) {
2244 if(const auto* tmpExpr = dyn_cast_or_null<CXXBindTemporaryExpr>(arg)) {
2245 if(const auto* tmp = dyn_cast_or_null<CXXTemporaryObjectExpr>(tmpExpr->getSubExpr())) {
2246 if(GetInsightsOptions().UseShow2C) {
2251 } else if(GetInsightsOptions().ShowLifetime) {
2252 mOutputFormatHelper.Append(GetName(*tmp));
2258 if(
GetInsightsOptions().UseShow2C and funcDecl and (funcDecl->getNumParams() >= parmIdx) and
2260 if(auto* unop = dyn_cast_or_null<UnaryOperator>(arg); not unop or (unop->getOpcode() != UO_AddrOf)) {
2269 if(insideDecltype) {
2270 mLambdaStack.back().setInsertName(
false);
2273 mCurrentCallExprPos.reset();
2277 void CodeGenerator::InsertArg(
const CXXNamedCastExpr* stmt)
2279 const QualType castDestType = stmt->getTypeAsWritten();
2280 const Expr* subExpr = stmt->getSubExpr();
2282 FormatCast(stmt->getCastName(), castDestType, subExpr, stmt->getCastKind());
2286 void CodeGenerator::InsertArg(
const ImplicitCastExpr* stmt)
2288 const Expr* subExpr = stmt->getSubExpr();
2289 const auto castKind = stmt->getCastKind();
2292 auto isMatchingCast = [](
const CastKind kind,
const bool hideImplicitCasts,
const bool showXValueCasts) {
2294 case CastKind::CK_Dependent: [[fallthrough]];
2295 case CastKind::CK_IntegralCast: [[fallthrough]];
2296 case CastKind::CK_IntegralToBoolean: [[fallthrough]];
2297 case CastKind::CK_IntegralToPointer: [[fallthrough]];
2298 case CastKind::CK_PointerToIntegral: [[fallthrough]];
2299 case CastKind::CK_BitCast: [[fallthrough]];
2300 case CastKind::CK_UncheckedDerivedToBase: [[fallthrough]];
2301 case CastKind::CK_ToUnion:
2304 case CastKind::CK_AtomicToNonAtomic: [[fallthrough]];
2305 case CastKind::CK_DerivedToBase: [[fallthrough]];
2306 case CastKind::CK_FloatingCast: [[fallthrough]];
2307 case CastKind::CK_IntegralToFloating: [[fallthrough]];
2308 case CastKind::CK_FloatingToIntegral: [[fallthrough]];
2309 case CastKind::CK_NonAtomicToAtomic:
return true;
2312 if((showXValueCasts or not hideImplicitCasts) and (CastKind::CK_NoOp == kind)) {
2317 if(not hideImplicitCasts) {
2319 case CastKind::CK_NullToPointer: [[fallthrough]];
2320 case CastKind::CK_NullToMemberPointer: [[fallthrough]];
2323 case CastKind::CK_NoOp: [[fallthrough]];
2324 case CastKind::CK_ArrayToPointerDecay:
return true;
2331 }(castKind, hideImplicitCasts, stmt->isXValue() or ShowXValueCasts());
2333 if(not isMatchingCast) {
2336 mOutputFormatHelper.Append(
"*"sv);
2341 }
else if(isa<IntegerLiteral>(subExpr) and hideImplicitCasts) {
2342 InsertArg(stmt->IgnoreCasts());
2346 }
else if(stmt->isPartOfExplicitCast()) {
2355 if(isa<CStyleCastExpr>(subExpr) or isa<CXXNamedCastExpr>(subExpr)) {
2358 InsertArg(stmt->IgnoreCasts());
2363 const QualType castDestType{[&] {
2364 const auto type{stmt->getType()};
2368 if(VK_XValue == stmt->getValueKind()) {
2369 return GetGlobalAST().getRValueReferenceType(type.getCanonicalType());
2370 }
else if(type->isDependentType()) {
2375 return type.getCanonicalType();
2378 FormatCast(castName, castDestType, subExpr, castKind);
2383 void CodeGenerator::InsertArg(
const DeclRefExpr* stmt)
2385 if(
const auto* tmplObjParam = dyn_cast_or_null<TemplateParamObjectDecl>(stmt->getDecl())) {
2386 mOutputFormatHelper.Append(
GetName(*tmplObjParam));
2388 }
else if(
const auto* vd = dyn_cast_or_null<VarDecl>(stmt->getDecl());
2390 const auto* init = vd->getInit();
2392 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(init)) {
2393 mOutputFormatHelper.Append(
GetName(*dref));
2396 }
else if(
const auto* inList = dyn_cast_or_null<InitListExpr>(init)) {
2397 mOutputFormatHelper.Append(
GetName(*dyn_cast_or_null<DeclRefExpr>(inList->getInit(0))));
2402 if(
const auto* ctx = stmt->getDecl()->getDeclContext(); not ctx->isFunctionOrMethod() and
2403 not isa<NonTypeTemplateParmDecl>(stmt->getDecl()) and
2405 if(
const auto* qualifier = stmt->getQualifier();
2406 qualifier and (qualifier->getKind() == NestedNameSpecifier::SpecifierKind::Global)) {
2410 mOutputFormatHelper.Append(
"::"sv,
GetPlainName(*stmt));
2413 OutputFormatHelper ofm{};
2414 CodeGeneratorVariant codeGenerator{ofm};
2418 mOutputFormatHelper.Append(ScopeHandler::RemoveCurrentScope(ofm.GetString()),
GetPlainName(*stmt));
2422 mOutputFormatHelper.Append(
GetName(*stmt));
2425 if(
const auto* varTmplSpecDecl = dyn_cast_or_null<VarTemplateSpecializationDecl>(stmt->getDecl())) {
2426 InsertTemplateArgs(*varTmplSpecDecl);
2428 InsertTemplateArgs(*stmt);
2433 void CodeGenerator::InsertArg(
const CompoundStmt* stmt)
2435 mOutputFormatHelper.OpenScope();
2436 mLifeTimeTracker.StartScope(isa_and_nonnull<FunctionDecl>(mLastDecl));
2440 const bool requiresImplicitReturnZero{std::exchange(mRequiresImplicitReturnZero,
false)};
2442 HandleCompoundStmt(stmt);
2444 if(requiresImplicitReturnZero) {
2452 mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper, isa_and_nonnull<ReturnStmt>(mLastStmt));
2454 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
2458 template<
typename... Args>
2461 return (... and not isa<Args>(stmt));
2465 void CodeGenerator::HandleCompoundStmt(
const CompoundStmt* stmt)
2467 for(
const auto* item : stmt->body()) {
2472 const bool skipSemiForLambda{mLambdaStack.empty() and isa<LambdaExpr>(item)};
2484 InsertSemi() and not skipSemiForLambda and not mSkipSemi) {
2485 mOutputFormatHelper.AppendSemiNewLine();
2493 void CodeGenerator::InsertIfOrSwitchInitVariables(same_as_any_of<const IfStmt, const SwitchStmt>
auto* stmt)
2495 if(
const auto* conditionVar = stmt->getConditionVariable()) {
2496 InsertArg(conditionVar);
2499 if(
const auto* init = stmt->getInit()) {
2502 if(not isa<DeclStmt>(init)) {
2503 mOutputFormatHelper.AppendSemiNewLine();
2509 void CodeGenerator::InsertArg(
const IfStmt* stmt)
2511 const bool hasInit{stmt->getInit() or stmt->getConditionVariable()};
2514 mOutputFormatHelper.OpenScope();
2516 InsertIfOrSwitchInitVariables(stmt);
2521 WrapInParensIfNeeded(
2522 not stmt->isConsteval(),
2524 mShowConstantExprValue = ShowConstantExprValue::Yes;
2526 InsertArg(stmt->getCond());
2528 mShowConstantExprValue = ShowConstantExprValue::No;
2530 AddSpaceAtTheEnd::Yes);
2532 mOutputFormatHelper.Append(
ValueOrDefault(stmt->isNegatedConsteval(),
" !"sv),
2535 WrapInCompoundIfNeeded(stmt->getThen(), AddNewLineAfter::No);
2538 if(
const auto* elsePart = stmt->getElse()) {
2539 mOutputFormatHelper.Append(
2543 WrapInCompoundIfNeeded(elsePart, AddNewLineAfter::No);
2547 mOutputFormatHelper.AppendNewLine();
2550 mOutputFormatHelper.CloseScope();
2551 mOutputFormatHelper.AppendNewLine();
2555 mOutputFormatHelper.AppendNewLine();
2562 std::string_view mContinueLabel{};
2569 , mContinueLabel{continueLabel}
2590 auto* tmp = mPrevStmt;
2593 for(
auto* child : stmt->children()) {
2602 void CodeGenerator::InsertArg(
const ForStmt* stmt)
2609 auto* rwStmt =
const_cast<ForStmt*
>(stmt);
2611 StmtsContainer bodyStmts{};
2613 auto continueLabel =
MakeLineColumnName(ctx.getSourceManager(), stmt->getBeginLoc(),
"__continue_"sv);
2614 const bool insertLabel = ContinueASTTransformer{rwStmt->getBody(), continueLabel}.found;
2616 bodyStmts.AddBodyStmts(rwStmt->getBody());
2620 bodyStmts.Add(
Label(continueLabel));
2623 bodyStmts.Add(rwStmt->getInc());
2625 auto* condition = [&]() -> Expr* {
2626 if(rwStmt->getCond()) {
2627 return rwStmt->getCond();
2633 auto* outerBody =
mkCompoundStmt(bodyStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2634 auto* whileStmt = WhileStmt::Create(
2635 ctx,
nullptr, condition, outerBody, stmt->getBeginLoc(), stmt->getLParenLoc(), stmt->getRParenLoc());
2637 StmtsContainer outerScopeStmts{};
2638 outerScopeStmts.Add(rwStmt->getInit());
2639 outerScopeStmts.Add(whileStmt);
2641 auto* outerScopeBody =
mkCompoundStmt(outerScopeStmts, stmt->getBeginLoc(), stmt->getEndLoc());
2643 InsertArg(outerScopeBody);
2644 mOutputFormatHelper.AppendNewLine();
2651 mOutputFormatHelper.Append(
"for"sv);
2655 if(
const auto* init = stmt->getInit()) {
2656 MultiStmtDeclCodeGenerator codeGenerator{
2657 mOutputFormatHelper, mLambdaStack, InsertVarDecl(nullptr)};
2661 mOutputFormatHelper.Append(
"; "sv);
2664 InsertArg(stmt->getCond());
2665 mOutputFormatHelper.Append(
"; "sv);
2667 InsertArg(stmt->getInc());
2669 AddSpaceAtTheEnd::Yes);
2672 WrapInCompoundIfNeeded(stmt->getBody(), AddNewLineAfter::Yes);
2675 mOutputFormatHelper.AppendNewLine();
2681 if(not type.isNull()) {
2682 if(
auto* typePtr = type.getTypePtrOrNull()) {
2683 if(
auto pointee = typePtr->getPointeeType(); not pointee.isNull()) {
2684 return pointee.isConstQualified();
2693 void CodeGenerator::InsertArg(
const CStyleCastExpr* stmt)
2695 const auto castKind = stmt->getCastKind();
2696 const QualType castDestType = stmt->getType().getCanonicalType();
2700 FormatCast(castName, castDestType, stmt->getSubExpr(), castKind);
2704 void CodeGenerator::InsertArg(
const CXXNewExpr* stmt)
2706 const auto noEmptyInitList = mNoEmptyInitList;
2707 FinalAction _{[&] { mNoEmptyInitList = noEmptyInitList; }};
2708 mNoEmptyInitList =
GetInsightsOptions().UseShow2C ? NoEmptyInitList::Yes : NoEmptyInitList::No;
2710 mOutputFormatHelper.Append(
"new "sv);
2712 if(stmt->getNumPlacementArgs()) {
2715 WrapInParens([&]() {
2716 ForEachArg(stmt->placement_arguments(), [&](
const auto& placementArg) { InsertArg(placementArg); });
2720 if(
const auto* ctorExpr = stmt->getConstructExpr()) {
2721 InsertArg(ctorExpr);
2724 auto name =
GetName(stmt->getAllocatedType());
2727 if(stmt->isArray()) {
2728 OutputFormatHelper ofm{};
2729 CodeGeneratorVariant codeGenerator{ofm};
2732 codeGenerator->
InsertArg(stmt->getArraySize().value());
2745 mOutputFormatHelper.Append(name);
2747 if(stmt->hasInitializer()) {
2748 InsertCurlysIfRequired(stmt->getInitializer());
2754 void CodeGenerator::InsertArg(
const MaterializeTemporaryExpr* stmt)
2757 const auto* temporary = stmt->getSubExpr();
2758 WrapInParensIfNeeded(isa_and_nonnull<ConditionalOperator>(temporary), [&] { InsertArg(temporary); });
2762 void CodeGenerator::InsertArg(
const CXXOperatorCallExpr* stmt)
2766 const auto* callee = dyn_cast_or_null<DeclRefExpr>(stmt->getCallee()->IgnoreImpCasts());
2767 const bool isCXXMethod{callee and isa<CXXMethodDecl>(callee->getDecl())};
2769 if(2 == stmt->getNumArgs()) {
2770 auto getArg = [&](
unsigned idx) {
2771 const auto* arg = stmt->getArg(idx);
2776 arg = arg->IgnoreImpCasts();
2779 return dyn_cast_or_null<DeclRefExpr>(arg);
2782 const auto* param1 = getArg(0);
2783 const auto* param2 = getArg(1);
2785 if(callee and param1 and param2) {
2786 const std::string replace = [&]() {
2788 auto nameWithTmplArguments = [](
const auto param) {
2792 if(isa<CXXMethodDecl>(callee->getDecl())) {
2793 return StrCat(nameWithTmplArguments(param1),
2797 nameWithTmplArguments(param2),
2802 nameWithTmplArguments(param1),
2804 nameWithTmplArguments(param2),
2809 mOutputFormatHelper.Append(replace);
2815 auto cb = stmt->child_begin();
2816 const auto* fallbackArg0 = stmt->getArg(0);
2820 std::advance(cb, 1);
2822 const auto* arg1 = *cb;
2824 std::advance(cb, 1);
2827 if(not isCXXMethod) {
2830 if(
const auto* adl = dyn_cast_or_null<UnresolvedLookupExpr>(stmt->getCallee())) {
2834 mOutputFormatHelper.Append(
GetName(*callee));
2837 mOutputFormatHelper.Append(
"("sv);
2841 if(isa<DeclRefExpr>(fallbackArg0)) {
2842 InsertArgWithParensIfNeeded(fallbackArg0);
2845 InsertArgWithParensIfNeeded(arg1);
2850 const OverloadedOperatorKind opKind = stmt->getOperator();
2854 mOutputFormatHelper.Append(
"."sv, operatorKw, getOperatorSpelling(opKind),
"("sv);
2858 const auto childRange = llvm::make_range(cb, stmt->child_end());
2861 ForEachArg(childRange, [&](
const auto& child) {
2862 if(not isCXXMethod) {
2864 mOutputFormatHelper.Append(
", "sv);
2870 mOutputFormatHelper.Append(
')');
2874 void CodeGenerator::InsertArg(
const LambdaExpr* stmt)
2876 if(not mLambdaStack.empty()) {
2877 const bool insertName{mLambdaStack.back().insertName()};
2879 HandleLambdaExpr(stmt, mLambdaStack.back());
2885 }
else if(LambdaInInitCapture::Yes == mLambdaInitCapture) {
2887 HandleLambdaExpr(stmt, mLambdaStack.back());
2890 HandleLambdaExpr(stmt, mLambdaStack.back());
2893 if(not mLambdaStack.empty()) {
2894 mLambdaStack.back().insertInits(mOutputFormatHelper);
2899 void CodeGenerator::InsertArg(
const CXXThisExpr* stmt)
2903 mOutputFormatHelper.Append(
kwThis);
2907 void CodeGenerator::InsertArg(
const CXXBindTemporaryExpr* stmt)
2909 InsertArg(stmt->getSubExpr());
2913 void CodeGenerator::InsertArg(
const CXXFunctionalCastExpr* stmt)
2915 const bool isConstructor{isa<CXXConstructExpr>(stmt->getSubExpr())};
2916 const bool isStdListInit{isa<CXXStdInitializerListExpr>(stmt->getSubExpr())};
2917 const bool isListInitialization{stmt->getLParenLoc().isInvalid()};
2918 const bool needsParens{not isConstructor and not isListInitialization and not isStdListInit};
2921 if(not isConstructor and not isStdListInit) {
2922 mOutputFormatHelper.Append(
GetName(stmt->getTypeAsWritten()));
2925 WrapInParensIfNeeded(needsParens, [&] { InsertArg(stmt->getSubExpr()); });
2929 void CodeGenerator::InsertArg(
const CXXBoolLiteralExpr* stmt)
2935 void CodeGenerator::InsertArg(
const GNUNullExpr* )
2937 mOutputFormatHelper.Append(
kwNull);
2941 void CodeGenerator::InsertArg(
const CharacterLiteral* stmt)
2943 StringStream stream{};
2944 stream.Print(*stmt);
2946 auto str = std::move(stream.str());
2948 if(str ==
"'\\x00'"sv) {
2950 }
else if(str ==
"'\\xff'"sv) {
2954 mOutputFormatHelper.Append(str);
2958 void CodeGenerator::InsertArg(
const PredefinedExpr* stmt)
2962 if(
const auto* functionName = stmt->getFunctionName()) {
2963 InsertArg(functionName);
2965 const auto name = PredefinedExpr::getIdentKindName(stmt->getIdentKind());
2967 mOutputFormatHelper.Append(name);
2972 void CodeGenerator::InsertArg(
const ExprWithCleanups* stmt)
2974 mLifeTimeTracker.StartScope(
false);
2975 TemporaryDeclFinder temporaryFinder{*
this, not mProcessingVarDecl ? stmt->getSubExpr() :
nullptr};
2977 InsertArg(stmt->getSubExpr());
2980 mOutputFormatHelper.AppendSemiNewLine();
2983 mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper,
false);
2987 std::string CodeGenerator::GetValueOfValueInit(
const QualType& t)
2989 const QualType& type = t.getCanonicalType();
2991 if(type->isScalarType()) {
2992 switch(type->getScalarTypeKind()) {
2993 case Type::STK_CPointer:
2994 case Type::STK_BlockPointer:
2995 case Type::STK_ObjCObjectPointer:
2996 case Type::STK_MemberPointer:
return std::string{
kwNullptr};
2998 case Type::STK_Bool:
return std::string{
kwFalse};
3000 case Type::STK_Integral:
3001 case Type::STK_Floating:
3002 if(
const auto* bt = type->getAs<BuiltinType>()) {
3003 switch(bt->getKind()) {
3005 case BuiltinType::Char_U:
3006 case BuiltinType::UChar:
3007 case BuiltinType::Char_S:
3008 case BuiltinType::SChar:
return "'\\0'";
3009 case BuiltinType::WChar_U:
3010 case BuiltinType::WChar_S:
return "L'\\0'";
3011 case BuiltinType::Char16:
return "u'\\0'";
3012 case BuiltinType::Char32:
return "U'\\0'";
3014 case BuiltinType::Half:
3015 case BuiltinType::Float:
return "0.0f";
3016 case BuiltinType::Double:
return "0.0";
3023 case Type::STK_FloatingComplex:
3024 case Type::STK_IntegralComplex:
3025 if(
const auto* complexType = type->getAs<ComplexType>()) {
3026 return GetValueOfValueInit(complexType->getElementType());
3031 case Type::STK_FixedPoint:
Error(
"STK_FixedPoint is not implemented");
break;
3034 }
else if(
const auto* tt = dyn_cast_or_null<ConstantArrayType>(t.getTypePtrOrNull())) {
3035 const auto& elementType{tt->getElementType()};
3036 const std::string elementTypeInitValue{GetValueOfValueInit(elementType)};
3038 return FillConstantArray(tt, elementTypeInitValue, uint64_t{0});
3041 return std::string{
"0"sv};
3045 void CodeGenerator::InsertArg(
const ImplicitValueInitExpr* stmt)
3047 mOutputFormatHelper.Append(GetValueOfValueInit(stmt->getType()));
3051 void CodeGenerator::InsertArg(
const CXXScalarValueInitExpr* stmt)
3053 mOutputFormatHelper.Append(
GetName(stmt->getType()),
"()"sv);
3057 void CodeGenerator::InsertArg(
const CXXTryStmt* stmt)
3059 mOutputFormatHelper.AppendNewLine(
kwTrySpace);
3061 InsertArg(stmt->getTryBlock());
3064 InsertArg(stmt->getHandler(i));
3067 mOutputFormatHelper.AppendNewLine();
3071 void CodeGenerator::InsertArg(
const CXXCatchStmt* stmt)
3073 mOutputFormatHelper.Append(
" catch"sv);
3077 if(not stmt->getCaughtType().isNull()) {
3078 mOutputFormatHelper.Append(
3079 GetTypeNameAsParameter(stmt->getCaughtType(), stmt->getExceptionDecl()->getName()));
3081 mOutputFormatHelper.Append(kwElipsis);
3084 AddSpaceAtTheEnd::Yes);
3086 InsertArg(stmt->getHandlerBlock());
3090 void CodeGenerator::InsertArg(
const CXXThrowExpr* stmt)
3092 mOutputFormatHelper.Append(
"throw "sv);
3094 InsertArg(stmt->getSubExpr());
3098 void CodeGenerator::InsertArg(
const ConstantExpr* stmt)
3100 if((ShowConstantExprValue::Yes == mShowConstantExprValue) and stmt->hasAPValueResult()) {
3101 if(
const auto value = stmt->getAPValueResult(); value.isInt()) {
3102 mOutputFormatHelper.Append(value.getInt());
3107 InsertArg(stmt->getSubExpr());
3111 void CodeGenerator::InsertArg(
const TypeAliasDecl* stmt)
3113 const auto& underlyingType = stmt->getUnderlyingType();
3116 P0315Visitor dt{*
this};
3117 dt.TraverseType(underlyingType);
3121 if(
auto* templateSpecializationType = underlyingType->getAs<TemplateSpecializationType>()) {
3122 const bool carriesNamespace{[&] {
3123 if(
const auto tn = templateSpecializationType->getTemplateName();
3124 (TemplateName::QualifiedTemplate == tn.getKind()) or (TemplateName::DependentTemplate == tn.getKind())) {
3125 const auto* qtn = tn.getAsQualifiedTemplateName();
3127 return qtn->getQualifier() !=
nullptr;
3133 if(
const auto* elaboratedType = underlyingType->getAs<ElaboratedType>()) {
3134 if(templateSpecializationType->isSugared() and not carriesNamespace) {
3136 InsertNamespace(elaboratedType->getQualifier());
3140 StringStream stream{};
3141 stream.Print(*templateSpecializationType);
3143 mOutputFormatHelper.Append(stream.str());
3145 InsertTemplateArgs(*templateSpecializationType);
3146 }
else if(
auto* dependentTemplateSpecializationType =
3147 underlyingType->getAs<DependentTemplateSpecializationType>()) {
3151 InsertNamespace(dependentTemplateSpecializationType->getQualifier());
3153 mOutputFormatHelper.Append(
kwTemplateSpace, dependentTemplateSpecializationType->getIdentifier()->getName());
3155 InsertTemplateArgs(*dependentTemplateSpecializationType);
3158 mOutputFormatHelper.Append(
GetName(underlyingType));
3161 mOutputFormatHelper.AppendSemiNewLine();
3165 void CodeGenerator::InsertArg(
const TypedefDecl* stmt)
3174 void CodeGenerator::InsertCXXMethodHeader(
const CXXMethodDecl* stmt,
OutputFormatHelper& initOutputFormatHelper)
3177 CXXConstructorDecl* cxxInheritedCtorDecl{
nullptr};
3181 if(
const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
3182 CodeGeneratorVariant codeGenerator{initOutputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
3188 for(
OnceTrue first{};
const auto* init : ctor->inits()) {
3191 initOutputFormatHelper.
Append(
": "sv);
3193 initOutputFormatHelper.
Append(
", "sv);
3198 if(
const auto* member = init->getMember()) {
3199 initOutputFormatHelper.
Append(member->getName());
3202 const auto* inlineInit = init->getInit();
3203 bool useCurlies{
false};
3205 if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3206 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3210 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3218 const auto* inlineInit = init->getInit();
3221 if(
const auto* member = init->getMember()) {
3222 initOutputFormatHelper.
Append(member->getName());
3224 if(isa<ParenListExpr>(inlineInit)) {
3230 }
else if(
const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
3231 cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();
3237 }
else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
3240 const auto braceKind = isa<ParenListExpr>(inlineInit) ? BraceKind::Parens : BraceKind::Curlys;
3250 InsertTemplateGuardBegin(stmt);
3251 InsertFunctionNameWithReturnType(*stmt, cxxInheritedCtorDecl);
3255 void CodeGenerator::InsertCXXMethodDecl(
const CXXMethodDecl* stmt, SkipBody skipBody)
3258 initOutputFormatHelper.
SetIndent(mOutputFormatHelper, OutputFormatHelper::SkipIndenting::Yes);
3260 const auto posBeforeFunc = mOutputFormatHelper.CurrentPos();
3262 InsertCXXMethodHeader(stmt, initOutputFormatHelper);
3264 if(not stmt->isUserProvided() or stmt->isExplicitlyDefaulted()) {
3265 InsertTemplateGuardEnd(stmt);
3269 mOutputFormatHelper.Append(initOutputFormatHelper);
3271 if(isa<CXXConversionDecl>(stmt)) {
3272 if(stmt->getParent()->isLambda() and not stmt->doesThisDeclarationHaveABody()) {
3273 mOutputFormatHelper.AppendNewLine();
3274 WrapInCurlys([&]() {
3275 mOutputFormatHelper.AppendNewLine();
3276 mOutputFormatHelper.Append(
" "sv,
kwReturn,
" "sv);
3277 if(
const auto* invoker = stmt->getParent()->getLambdaStaticInvoker()) {
3278 mOutputFormatHelper.AppendSemiNewLine(invoker->getName());
3280 mOutputFormatHelper.AppendSemiNewLine(kwOperator,
"()"sv);
3286 if((SkipBody::No == skipBody) and stmt->doesThisDeclarationHaveABody() and not stmt->isLambdaStaticInvoker()) {
3287 InsertMethodBody(stmt, posBeforeFunc);
3289 }
else if(not InsertLambdaStaticInvoker(stmt) or (SkipBody::Yes == skipBody)) {
3290 mOutputFormatHelper.AppendSemiNewLine();
3293 InsertTemplateGuardEnd(stmt);
3295 if(SkipBody::No == skipBody) {
3296 mOutputFormatHelper.AppendNewLine();
3301 void CodeGenerator::InsertArg(
const CXXMethodDecl* stmt)
3307 not stmt->isExplicitlyDefaulted() and not stmt->isDeleted());
3309 InsertCXXMethodDecl(stmt, SkipBody::No);
3313 void CodeGenerator::InsertArg(
const EnumDecl* stmt)
3317 if(stmt->isScoped()) {
3318 if(stmt->isScopedUsingClassTag()) {
3325 mOutputFormatHelper.Append(stmt->getName());
3327 if(stmt->isFixed()) {
3328 mOutputFormatHelper.Append(
" : "sv,
GetName(stmt->getIntegerType()));
3331 mOutputFormatHelper.AppendNewLine();
3335 mOutputFormatHelper.IncreaseIndent();
3336 mOutputFormatHelper.AppendNewLine();
3339 ForEachArg(stmt->enumerators(), [&](
const auto* value) {
3341 mOutputFormatHelper.AppendNewLine();
3347 InsertArg(stmt->getBody());
3349 mOutputFormatHelper.DecreaseIndent();
3350 mOutputFormatHelper.AppendNewLine();
3352 AddSpaceAtTheEnd::No);
3354 mOutputFormatHelper.AppendSemiNewLine();
3355 mOutputFormatHelper.AppendNewLine();
3359 void CodeGenerator::InsertArg(
const EnumConstantDecl* stmt)
3361 mOutputFormatHelper.Append(stmt->getName());
3363 InsertAttributes(stmt);
3365 if(
const auto* initExpr = stmt->getInitExpr()) {
3368 InsertArg(initExpr);
3382 static const std::string_view spaces{
" "sv};
3384 if(offset >= spaces.size()) {
3387 return spaces.substr(0, spaces.size() - offset);
3392 void CodeGenerator::InsertArg(
const FieldDecl* stmt)
3395 P0315Visitor dt{*
this};
3397 auto type =
GetType(stmt->getType());
3398 dt.TraverseType(type);
3400 const auto initialSize{mOutputFormatHelper.size()};
3401 InsertAttributes(stmt->attrs());
3403 if(stmt->isMutable()) {
3407 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(stmt->getParent())) {
3408 std::string name{
GetName(*stmt)};
3411 name = std::move(fieldName.value());
3416 if(
const auto* constantExpr = dyn_cast_or_null<ConstantExpr>(stmt->getBitWidth())) {
3417 mOutputFormatHelper.Append(
':');
3418 InsertArg(constantExpr);
3422 if(
const auto* initializer = stmt->getInClassInitializer();
3423 stmt->hasInClassInitializer() and initializer and cxxRecordDecl->isAggregate()) {
3424 const bool isConstructorExpr{isa<CXXConstructExpr>(initializer) or isa<ExprWithCleanups>(initializer)};
3425 if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) {
3429 InsertArg(initializer);
3433 mOutputFormatHelper.Append(
';');
3436 const auto* fieldClass = stmt->getParent();
3438 auto effectiveFieldSize{
GetGlobalAST().getTypeInfoInChars(type).Width.getQuantity()};
3439 auto getFieldOffsetInBytes = [&recordLayout](
const FieldDecl* field) {
3440 return recordLayout.getFieldOffset(field->getFieldIndex()) / 8;
3442 auto fieldOffset = getFieldOffsetInBytes(stmt);
3443 const auto offset = mOutputFormatHelper.size() - initialSize;
3445 mOutputFormatHelper.Append(
GetSpaces(offset),
" /* offset: "sv, fieldOffset,
", size: "sv, effectiveFieldSize);
3454 const auto expectedOffset = fieldOffset + effectiveFieldSize;
3455 const auto nextOffset = [&]() -> uint64_t {
3457 if(
const auto next = stmt->getFieldIndex() + 1; recordLayout.getFieldCount() > next) {
3459 const auto* field = *std::next(fieldClass->fields().begin(), next);
3461 return getFieldOffsetInBytes(field);
3465 return recordLayout.getSize().getQuantity();
3468 if(expectedOffset < nextOffset) {
3469 const auto padding = nextOffset - expectedOffset;
3470 mOutputFormatHelper.AppendNewLine();
3472 mOutputFormatHelper.Append(s,
GetSpaces(s.length()),
" size: ", padding);
3475 mOutputFormatHelper.AppendNewLine(
" */"sv);
3478 mOutputFormatHelper.AppendNewLine();
3483 void CodeGenerator::InsertArg(
const AccessSpecDecl* stmt)
3485 mOutputFormatHelper.AppendNewLine();
3490 void CodeGenerator::InsertArg(
const StaticAssertDecl* stmt)
3494 if(not stmt->isFailed()) {
3495 mOutputFormatHelper.Append(
"/* PASSED: "sv);
3497 mOutputFormatHelper.Append(
"/* FAILED: "sv);
3504 InsertArg(stmt->getAssertExpr());
3506 if(stmt->getMessage()) {
3507 mOutputFormatHelper.Append(
", "sv);
3508 InsertArg(stmt->getMessage());
3516 void CodeGenerator::InsertArg(
const UsingDirectiveDecl* stmt)
3519 if(
const auto& name =
GetName(*stmt->getNominatedNamespace()); not name.empty()) {
3525 void CodeGenerator::InsertArg(
const NamespaceDecl* stmt)
3529 if(stmt->isInline()) {
3535 if(not stmt->isAnonymousNamespace()) {
3536 mOutputFormatHelper.Append(
" "sv, stmt->getName());
3539 InsertAttributes(stmt);
3541 mOutputFormatHelper.AppendNewLine();
3543 mOutputFormatHelper.OpenScope();
3545 for(
const auto* decl : stmt->decls()) {
3549 mOutputFormatHelper.CloseScope();
3550 mOutputFormatHelper.AppendNewLine();
3554 void CodeGenerator::ParseDeclContext(
const DeclContext* ctx)
3560 void CodeGenerator::InsertArg(
const UsingDecl* stmt)
3563 ofm.
SetIndent(mOutputFormatHelper, OutputFormatHelper::SkipIndenting::Yes);
3568 if(stmt->shadow_size()) {
3569 for(
const auto* shadow : stmt->shadows()) {
3570 RETURN_IF(isa<ConstructorUsingShadowDecl>(shadow));
3572 if(
const auto* shadowUsing = dyn_cast_or_null<UsingShadowDecl>(shadow)) {
3573 if(
const auto* targetDecl = shadowUsing->getTargetDecl(); not isa<TypeAliasDecl>(targetDecl)) {
3574 UsingCodeGenerator codeGenerator{ofm};
3583 InsertQualifierAndName(stmt->getDeclName(), stmt->getQualifier(),
false);
3585 mOutputFormatHelper.AppendSemiNewLine();
3588 if(not ofm.empty()) {
3589 mOutputFormatHelper.AppendNewLine(ofm);
3594 void CodeGenerator::InsertArg(
const UnresolvedUsingValueDecl* stmt)
3598 InsertQualifierAndName(stmt->getDeclName(), stmt->getQualifier(),
false);
3600 mOutputFormatHelper.AppendSemiNewLine(
Ellipsis(stmt->isPackExpansion()));
3604 void CodeGenerator::InsertArg(
const NamespaceAliasDecl* stmt)
3606 mOutputFormatHelper.AppendNewLine(
3611 void CodeGenerator::InsertArg(
const FriendDecl* stmt)
3613 if(
const auto* typeInfo = stmt->getFriendType()) {
3616 }
else if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(stmt->getFriendDecl())) {
3619 }
else if(
const auto* fdt = dyn_cast_or_null<FunctionTemplateDecl>(stmt->getFriendDecl())) {
3624 if(
const auto* ctd = dyn_cast_or_null<ClassTemplateDecl>(stmt->getFriendDecl())) {
3625 InsertTemplateParameters(*ctd->getTemplateParameters());
3635 void CodeGenerator::InsertArg(
const CXXNoexceptExpr* stmt)
3643 void CodeGenerator::InsertArg(
const CXXDeductionGuideDecl* stmt)
3645 RETURN_IF(DeductionCandidate::Copy == stmt->getDeductionCandidateKind());
3647 const bool isImplicit{stmt->isImplicit()};
3648 const bool noSpecializations = [&] {
3649 if(
const auto* dt = stmt->getDescribedFunctionTemplate()) {
3650 return dt->specializations().empty();
3657 RETURN_IF(not stmt->isUsed() and isImplicit and noSpecializations);
3659 const bool isSpecialization{stmt->isFunctionTemplateSpecialization()};
3660 const bool needsTemplateGuard{isImplicit or isSpecialization};
3662 if(needsTemplateGuard) {
3663 InsertTemplateGuardBegin(stmt);
3666 const auto* deducedTemplate = stmt->getDeducedTemplate();
3668 if(isSpecialization) {
3669 InsertTemplateSpecializationHeader(*stmt);
3670 }
else if(
const auto* e = stmt->getDescribedFunctionTemplate()) {
3671 InsertTemplateParameters(*e->getTemplateParameters());
3674 mOutputFormatHelper.Append(
GetName(*deducedTemplate));
3676 if(stmt->getNumParams()) {
3677 WrapInParens([&] { mOutputFormatHelper.AppendParameterList(stmt->parameters()); });
3679 mOutputFormatHelper.Append(
"()"sv);
3682 mOutputFormatHelper.AppendSemiNewLine(
hlpArrow,
GetName(stmt->getReturnType()));
3684 if(needsTemplateGuard) {
3685 InsertTemplateGuardEnd(stmt);
3690 void CodeGenerator::InsertTemplate(
const FunctionTemplateDecl* stmt,
bool withSpec)
3694 mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::Yes;
3697 InsertArg(stmt->getTemplatedDecl());
3699 mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::No;
3703 for(
const auto* spec : stmt->specializations()) {
3705 if(spec->getPreviousDecl()) {
3709 mOutputFormatHelper.AppendNewLine();
3711 mOutputFormatHelper.AppendNewLine();
3716 void CodeGenerator::InsertArg(
const FunctionTemplateDecl* stmt)
3718 InsertTemplate(stmt,
true);
3722 void CodeGenerator::InsertArg(
const TypeAliasTemplateDecl* stmt)
3724 InsertTemplateParameters(*stmt->getTemplateParameters());
3726 InsertArg(stmt->getTemplatedDecl());
3730 void CodeGenerator::InsertArg(
const AttributedStmt* stmt)
3732 for(
const auto& attr : stmt->getAttrs()) {
3733 InsertAttribute(*attr);
3736 InsertArg(stmt->getSubStmt());
3740 void CodeGenerator::InsertAttributes(
const Decl* stmt)
3742 if(stmt->hasAttrs()) {
3743 mOutputFormatHelper.Append(
" "sv);
3745 InsertAttributes(stmt->attrs());
3750 void CodeGenerator::InsertAttributes(
const Decl::attr_range& attrs)
3753 for(
const auto& attr : attrs) {
3754 InsertAttribute(*attr);
3759 void CodeGenerator::InsertAttribute(
const Attr& attr)
3762 RETURN_IF(attr::Override == attr.getKind());
3765 RETURN_IF(attr::Final == attr.getKind());
3768 RETURN_IF(attr::NoInline == attr.getKind());
3771 if(
const auto* alignedAttr = dyn_cast_or_null<AlignedAttr>(&attr)) {
3772 auto insert = [&](
const QualType type,
const TemplateTypeParmType* tmplTypeParam) {
3773 mOutputFormatHelper.Append(attr.getSpelling(),
3779 Ellipsis(tmplTypeParam->isParameterPack()),
3783 if(alignedAttr->isAlignmentExpr()) {
3784 if(
const auto* unaryExpr = dyn_cast_or_null<UnaryExprOrTypeTraitExpr>(alignedAttr->getAlignmentExpr())) {
3785 if(
const auto* tmplTypeParam =
3786 dyn_cast_or_null<TemplateTypeParmType>(unaryExpr->getArgumentType().getTypePtrOrNull())) {
3787 insert(unaryExpr->getArgumentType(), tmplTypeParam);
3791 }
else if(
const auto* tmplTypeParam =
3792 alignedAttr->getAlignmentType()->getType()->getAs<TemplateTypeParmType>()) {
3793 insert(alignedAttr->getAlignmentType()->getType(), tmplTypeParam);
3800 pp.adjustForCPlusPlus();
3802 attr.printPretty(stream, pp);
3805 std::string_view start{stream.str()};
3807 mOutputFormatHelper.Append(start,
" "sv);
3811 void CodeGenerator::InsertArg(
const CXXRecordDecl* stmt)
3813 const size_t insertPosBeforeClass{mOutputFormatHelper.CurrentPos()};
3814 const auto indentAtInsertPosBeforeClass{mOutputFormatHelper.GetIndent()};
3819 RETURN_IF(stmt->isLambda() and (mLambdaStack.empty() or (
nullptr == mLambdaExpr)));
3821 const auto* classTemplatePartialSpecializationDecl = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(stmt);
3822 const auto* classTemplateSpecializationDecl = dyn_cast_or_null<ClassTemplateSpecializationDecl>(stmt);
3826 const bool isClassTemplateSpecialization{classTemplatePartialSpecializationDecl or classTemplateSpecializationDecl};
3827 const bool tmplRequiresIfDef{[&] {
3828 if(classTemplatePartialSpecializationDecl) {
3829 return classTemplatePartialSpecializationDecl->isImplicit();
3831 }
else if(classTemplateSpecializationDecl) {
3832 return not classTemplateSpecializationDecl->isExplicitInstantiationOrSpecialization();
3839 if(tmplRequiresIfDef) {
3840 mOutputFormatHelper.InsertEndIfTemplateGuard();
3844 if(isClassTemplateSpecialization) {
3845 if(tmplRequiresIfDef) {
3846 InsertInstantiationPoint(
GetSM(*classTemplateSpecializationDecl),
3847 classTemplateSpecializationDecl->getPointOfInstantiation());
3848 mOutputFormatHelper.InsertIfDefTemplateGuard();
3851 if(classTemplatePartialSpecializationDecl) {
3852 InsertTemplateParameters(*classTemplatePartialSpecializationDecl->getTemplateParameters());
3854 InsertTemplateSpecializationHeader(*stmt);
3857 }
else if(stmt->getLexicalDeclContext() != stmt->getDeclContext()) {
3858 if(
const auto* parent = dyn_cast_or_null<CXXRecordDecl>(stmt->getDeclContext())) {
3859 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
3860 InsertTemplateParameters(*outerClasTemplateDecl->getTemplateParameters());
3867 InsertAttributes(stmt->attrs());
3869 mOutputFormatHelper.Append(
GetName(*stmt));
3871 if(classTemplateSpecializationDecl) {
3872 InsertTemplateArgs(*classTemplateSpecializationDecl);
3875 if(stmt->hasAttr<FinalAttr>()) {
3880 if(not stmt->hasDefinition() or not stmt->isCompleteDefinition()) {
3881 mOutputFormatHelper.AppendSemiNewLine();
3885 if(stmt->getNumBases()) {
3886 mOutputFormatHelper.Append(
" : "sv);
3888 ForEachArg(stmt->bases(), [&](
const auto& base) {
3889 mOutputFormatHelper.Append(getAccessSpelling(base.getAccessSpecifier()),
3891 ValueOrDefault(base.isVirtual(), kwVirtualSpace),
3892 GetName(base.getType()),
3893 Ellipsis(base.isPackExpansion()));
3899 mOutputFormatHelper.AppendNewLine(
3900 " /* size: "sv, recordLayout.getSize(),
", align: "sv, recordLayout.getAlignment(),
" */"sv);
3903 mOutputFormatHelper.AppendNewLine();
3906 mOutputFormatHelper.OpenScope();
3909 for(
size_t offset{};
const auto& base : stmt->bases()) {
3910 const auto& baseRecordLayout =
GetRecordLayout(base.getType()->getAsRecordDecl());
3911 const auto baseVar =
StrCat(
"/* base ("sv,
GetName(base.getType()),
")"sv);
3912 const auto size = baseRecordLayout.getSize().getQuantity();
3914 mOutputFormatHelper.AppendNewLine(
3915 baseVar,
GetSpaces(baseVar.size()),
" offset: "sv, offset,
", size: "sv, size,
" */"sv);
3921 UpdateCurrentPos(mCurrentFieldPos);
3925 Decl::Kind formerKind{};
3926 AccessSpecifier lastAccess{stmt->isClass() ? AS_private : AS_public};
3927 for(
const auto* d : stmt->decls()) {
3928 if(isa<CXXRecordDecl>(d) and firstRecordDecl) {
3934 if(not firstDecl and (d->getKind() != formerKind)) {
3938 if((stmt->isLambda() and isa<CXXDestructorDecl>(d)) and not d->isUsed()) {
3944 if(lastAccess != d->getAccess()) {
3945 lastAccess = d->getAccess();
3948 if(not isa<AccessSpecDecl>(d)) {
3955 formerKind = d->getKind();
3958 if(stmt->isLambda()) {
3959 const LambdaCallerType lambdaCallerType = mLambdaStack.back().callerType();
3960 const bool ctorRequired{stmt->capture_size() or stmt->lambdaIsDefaultConstructibleAndAssignable()};
3963 if(AS_public != lastAccess) {
3964 mOutputFormatHelper.AppendNewLine();
3967 std::string_view p{pub};
3969 mOutputFormatHelper.AppendNewLine(p);
3972 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
3975 if(stmt->hasConstexprDefaultConstructor()) {
3980 mOutputFormatHelper.Append(
GetName(*stmt),
"("sv);
3983 SmallVector<std::string, 5> ctorInitializerList{};
3984 std::string ctorArguments{
'{'};
3988 [&](std::string_view name,
const FieldDecl* fd,
bool isThis,
const Expr* expr,
bool ) {
3989 if(firstCtorArgument) {
3991 mOutputFormatHelper.Append(
", "sv);
3992 ctorArguments.append(
", "sv);
3995 bool byConstRef{
false};
3997 auto fieldDeclType{fd->getType()};
4000 std::string fname =
StrCat(
"_"sv, name);
4004 if(
const auto* cxxConstructExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4005 cxxConstructExpr and cxxConstructExpr->getConstructor()->isMoveConstructor()) {
4007 OutputFormatHelper ofm{};
4008 LambdaInitCaptureCodeGenerator codeGenerator{ofm, mLambdaStack, name};
4010 if(cxxConstructExpr->getNumArgs()) {
4011 ForEachArg(cxxConstructExpr->arguments(),
4012 [&](
const auto& arg) { codeGenerator.InsertArg(arg); });
4015 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4021 }
else if(not fieldDeclType->isReferenceType() and not fieldDeclType->isAnyPointerType() and
4022 not fieldDeclType->isUndeducedAutoType()) {
4024 const auto* exprWithoutImpCasts = expr->IgnoreParenImpCasts();
4027 if(exprWithoutImpCasts->isXValue()) {
4030 OutputFormatHelper ofm{};
4031 LambdaInitCaptureCodeGenerator codeGenerator{ofm, mLambdaStack, name};
4036 }
else if(exprWithoutImpCasts
4038 or exprWithoutImpCasts->getType().isConstQualified()
4045 if(exprWithoutImpCasts->isPRValue() and isa<CXXBindTemporaryExpr>(exprWithoutImpCasts) and
4046 not exprWithoutImpCasts->getType().isConstQualified()) {
4047 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4049 fname =
StrCat(
"std::move("sv, fname,
")"sv);
4053 fieldDeclType.addConst();
4057 if(exprWithoutImpCasts->isXValue()) {
4058 fieldDeclType = stmt->getASTContext().getRValueReferenceType(fieldDeclType);
4060 }
else if(not isMoved) {
4061 fieldDeclType = stmt->getASTContext().getLValueReferenceType(fieldDeclType);
4065 const std::string_view elips{
4066 Ellipsis(isa_and_nonnull<PackExpansionType>(fieldDeclType->getPointeeType().getTypePtrOrNull()))};
4069 fieldDeclType = fieldDeclType.getCanonicalType();
4071 ctorInitializerList.push_back(
StrCat(fieldName,
"{"sv, fname, elips,
"}"sv));
4073 if(not isThis and expr) {
4075 OutputFormatHelper ofmLambdaInCtor{};
4076 ofmLambdaInCtor.SetIndent(indentAtInsertPosBeforeClass);
4077 CodeGenerator cgLambdaInCtor{ofmLambdaInCtor, LambdaInInitCapture::Yes};
4079 if(P0315Visitor dt{cgLambdaInCtor}; dt.TraverseStmt(
const_cast<Expr*
>(expr))) {
4081 OutputFormatHelper ofm{};
4082 CodeGeneratorVariant codeGenerator{ofm, mLambdaStack, mProcessingPrimaryTemplate};
4084 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
4085 ctorExpr and byConstRef and (1 == ctorExpr->getNumArgs())) {
4086 codeGenerator->
InsertArg(ctorExpr->getArg(0));
4096 ctorArguments.append(ofm);
4099 OutputFormatHelper ofm{};
4100 LambdaNameOnlyCodeGenerator ccg{ofm};
4101 ccg.InsertArg(expr);
4103 ctorArguments.append(ofm.GetString());
4105 mOutputFormatHelper.InsertAt(insertPosBeforeClass, ofmLambdaInCtor);
4108 if(isThis and not fieldDeclType->isPointerType()) {
4109 ctorArguments.append(
"*"sv);
4112 ctorArguments.append(name);
4118 llvm::DenseMap<const ValueDecl*, FieldDecl*> captures{};
4119 FieldDecl* thisCapture{};
4121 stmt->getCaptureFields(captures, thisCapture);
4125 const auto* captureInit = mLambdaExpr->capture_init_begin();
4127 addToInits(
kwThis, thisCapture,
true, *captureInit,
false);
4133 for(
const auto& [c, cinit] : zip(mLambdaExpr->captures(), mLambdaExpr->capture_inits())) {
4134 if(not c.capturesVariable()) {
4138 const auto* capturedVar = c.getCapturedVar();
4139 if(
const auto* value = captures[capturedVar]) {
4141 if(
const auto* bindingDecl = dyn_cast_or_null<BindingDecl>(capturedVar)) {
4142 const auto* decompositionDecl = cast<DecompositionDecl>(bindingDecl->getDecomposedDecl());
4143 addToInits(
GetName(*capturedVar),
4147 VarDecl::ListInit == decompositionDecl->getInitStyle());
4151 addToInits(
GetName(*capturedVar),
4155 VarDecl::ListInit == dyn_cast_or_null<VarDecl>(capturedVar)->getInitStyle());
4159 ctorArguments.append(
"}"sv);
4164 mOutputFormatHelper.Append(
")"sv);
4166 if(stmt->lambdaIsDefaultConstructibleAndAssignable()) {
4170 mOutputFormatHelper.AppendNewLine();
4172 for(
OnceTrue firstCtorInitializer{};
const auto& initializer : ctorInitializerList) {
4173 if(firstCtorInitializer) {
4174 mOutputFormatHelper.Append(
": "sv);
4176 mOutputFormatHelper.Append(
", "sv);
4179 mOutputFormatHelper.AppendNewLine(initializer);
4182 mOutputFormatHelper.AppendNewLine(
"{}"sv);
4187 mOutputFormatHelper.CloseScope();
4189 if(not
is{lambdaCallerType}.any_of(LambdaCallerType::VarDecl,
4190 LambdaCallerType::InitCapture,
4191 LambdaCallerType::CallExpr,
4192 LambdaCallerType::MemberCallExpr,
4193 LambdaCallerType::TemplateHead,
4194 LambdaCallerType::Decltype)) {
4195 mOutputFormatHelper.Append(
" "sv,
GetLambdaName(*stmt), ctorArguments);
4196 }
else if(not
is{lambdaCallerType}.any_of(LambdaCallerType::TemplateHead, LambdaCallerType::Decltype)) {
4197 mLambdaStack.back().inits().append(ctorArguments);
4200 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
4204 mOutputFormatHelper.Append(
" "sv,
GetName(*stmt));
4207 mOutputFormatHelper.AppendSemiNewLine();
4208 mOutputFormatHelper.AppendNewLine();
4212 void CodeGenerator::InsertArg(
const DeclStmt* stmt)
4214 for(
const auto* decl : stmt->decls()) {
4220 void CodeGenerator::InsertArg(
const SubstNonTypeTemplateParmExpr* stmt)
4222 InsertArg(stmt->getReplacement());
4226 void CodeGenerator::InsertArg(
const SizeOfPackExpr* stmt)
4228 if(stmt->isPartiallySubstituted()) {
4229 mOutputFormatHelper.Append(stmt->getPartialArguments().size());
4230 }
else if(not stmt->isValueDependent()) {
4231 mOutputFormatHelper.Append(stmt->getPackLength());
4238 void CodeGenerator::InsertArg(
const ReturnStmt* stmt)
4242 UpdateCurrentPos(mCurrentReturnPos);
4245 TemporaryDeclFinder temporaryFinder{*
this, stmt->getRetValue(),
true};
4247 mOutputFormatHelper.Append(
kwReturn);
4249 if(
const auto* retVal = stmt->getRetValue()) {
4250 mOutputFormatHelper.Append(
' ');
4252 if(not temporaryFinder.Found()) {
4253 if(
const auto* nrvoVD = stmt->getNRVOCandidate()) {
4254 mOutputFormatHelper.Append(
GetName(*nrvoVD));
4259 mOutputFormatHelper.Append(temporaryFinder.Name());
4264 mSkipSemi = mLifeTimeTracker.Return(mOutputFormatHelper);
4269 mCurrentReturnPos.reset();
4273 void CodeGenerator::InsertArg(
const NullStmt* )
4275 mOutputFormatHelper.AppendSemiNewLine();
4280 void CodeGenerator::InsertArg(
const StmtExpr* stmt)
4282 WrapInParens([&] { InsertArg(stmt->getSubStmt()); });
4286 void CodeGenerator::InsertArg(
const CppInsightsCommentStmt* stmt)
4288 mOutputFormatHelper.AppendCommentNewLine(stmt->Comment());
4292 void CodeGenerator::InsertArg(
const ConceptSpecializationExpr* stmt)
4294 if(
const auto* namedConcept = stmt->getNamedConcept()) {
4295 mOutputFormatHelper.Append(
GetName(*namedConcept));
4296 InsertTemplateArgs(stmt->getTemplateArgsAsWritten()->arguments());
4299 if(not stmt->isValueDependent()) {
4307 void CodeGenerator::InsertArg(
const RequiresExpr* stmt)
4311 const auto localParameters = stmt->getLocalParameters();
4312 WrapInParensIfNeeded(
4313 not localParameters.empty(),
4314 [&] { mOutputFormatHelper.AppendParameterList(localParameters); },
4315 AddSpaceAtTheEnd::Yes);
4317 mOutputFormatHelper.OpenScope();
4319 const auto noEmptyInitList = mNoEmptyInitList;
4320 FinalAction _{[&] { mNoEmptyInitList = noEmptyInitList; }};
4321 mNoEmptyInitList = NoEmptyInitList::Yes;
4323 for(
const auto& requirement : stmt->getRequirements()) {
4324 if(
const auto* typeRequirement = dyn_cast_or_null<concepts::TypeRequirement>(requirement)) {
4325 if(typeRequirement->isSubstitutionFailure()) {
4328 mOutputFormatHelper.Append(
GetName(typeRequirement->getType()->getType()));
4332 }
else if(
const auto* exprRequirement = dyn_cast_or_null<concepts::ExprRequirement>(requirement)) {
4333 if(exprRequirement->isExprSubstitutionFailure()) {
4338 WrapInCurliesIfNeeded(exprRequirement->isCompound(), [&] { InsertArg(exprRequirement->getExpr()); });
4340 if(exprRequirement->hasNoexceptRequirement()) {
4344 if(
const auto& returnTypeRequirement = exprRequirement->getReturnTypeRequirement();
4345 not returnTypeRequirement.isEmpty()) {
4347 not typeConstraint.empty()) {
4348 mOutputFormatHelper.Append(
hlpArrow, std::move(typeConstraint));
4352 }
else if(
const auto* nestedRequirement = dyn_cast_or_null<concepts::NestedRequirement>(requirement)) {
4355 if(nestedRequirement->hasInvalidConstraint()) {
4358 mOutputFormatHelper.Append(
kwFalse);
4360 InsertArg(nestedRequirement->getConstraintExpr());
4364 mOutputFormatHelper.AppendSemiNewLine();
4367 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
4371 void CodeGenerator::InsertArg(
const CXXDefaultArgExpr* stmt)
4373 InsertArg(stmt->getExpr());
4377 void CodeGenerator::InsertArg(
const CXXStdInitializerListExpr* stmt)
4381 const auto typeName{
GetName(stmt->getType(), Unqualified::Yes)};
4384 RETURN_IF(not mCurrentVarDeclPos.has_value() and not mCurrentFieldPos.has_value() and
4385 not mCurrentReturnPos.has_value() and not mCurrentCallExprPos.has_value());
4387 const auto* subExpr = stmt->getSubExpr();
4389 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(subExpr); dref and
GetInsightsOptions().ShowLifetime) {
4390 const auto size =
GetSize(dyn_cast_or_null<ConstantArrayType>(subExpr->getType()));
4392 mOutputFormatHelper.Append(typeName,
"{"sv,
GetName(*dref),
", "sv, size,
"}"sv);
4396 std::string modifiers{};
4397 size_t variableInsertPos = mCurrentReturnPos.value_or(
4398 mCurrentVarDeclPos.value_or(mCurrentCallExprPos.value_or(0)));
4400 auto& ofmToInsert = [&]() -> decltype(
auto) {
4401 if(not mCurrentVarDeclPos.has_value() and not mCurrentReturnPos.has_value() and
4402 not mCurrentCallExprPos.has_value()) {
4403 variableInsertPos = mCurrentFieldPos.value_or(0);
4404 mCurrentVarDeclPos = variableInsertPos;
4406 return (*mOutputFormatHelperOutside);
4409 return (mOutputFormatHelper);
4412 OutputFormatHelper ofm{};
4413 ofm.SetIndent(ofmToInsert, OutputFormatHelper::SkipIndenting::Yes);
4415 const auto size = [&]() ->
size_t {
4416 if(
const auto* mat = dyn_cast<MaterializeTemporaryExpr>(subExpr)) {
4417 if(
const auto* list = dyn_cast_or_null<InitListExpr>(mat->getSubExpr())) {
4418 return list->getNumInits();
4425 auto internalListName =
4429 CodeGeneratorVariant codeGenerator{ofm};
4431 ofm.AppendSemiNewLine();
4433 ofmToInsert.InsertAt(variableInsertPos, ofm);
4435 mOutputFormatHelper.Append(typeName,
"{"sv, internalListName,
", "sv, size,
"}"sv);
4437 if(mCurrentReturnPos.has_value()) {
4438 mCurrentReturnPos = mCurrentReturnPos.value() + ofm.size();
4439 }
else if(mCurrentVarDeclPos.has_value()) {
4440 mCurrentVarDeclPos = mCurrentVarDeclPos.value() + ofm.size();
4442 mCurrentCallExprPos = mCurrentCallExprPos.value() + ofm.size();
4446 mOutputFormatHelper.Append(typeName);
4447 InsertArg(stmt->getSubExpr());
4452 void CodeGenerator::InsertArg(
const CXXNullPtrLiteralExpr* )
4458 void CodeGenerator::InsertArg(
const LabelDecl* stmt)
4460 mOutputFormatHelper.Append(stmt->getName());
4464 void CodeGenerator::InsertArg(
const Decl* stmt)
4468 #define SUPPORTED_DECL(type) \
4469 if(isa<type>(stmt)) { \
4470 InsertArg(static_cast<const type*>(stmt)); \
4474 #define IGNORED_DECL SUPPORTED_DECL
4478 ToDo(stmt, mOutputFormatHelper);
4482 void CodeGenerator::InsertArg(
const Stmt* stmt)
4491 #define SUPPORTED_STMT(type) \
4492 if(isa<type>(stmt)) { \
4493 InsertArg(dyn_cast_or_null<type>(stmt)); \
4497 #define IGNORED_STMT SUPPORTED_STMT
4501 ToDo(stmt, mOutputFormatHelper);
4505 void CodeGenerator::FormatCast(
const std::string_view castName,
4506 const QualType& castDestType,
4507 const Expr* subExpr,
4508 const CastKind& castKind)
4510 const bool isCastToBase{
is{castKind}.
any_of(CK_DerivedToBase, CK_UncheckedDerivedToBase) and
4511 castDestType->isRecordType()};
4512 const std::string castDestTypeText{
4513 StrCat(
GetName(castDestType), ((isCastToBase and not castDestType->isAnyPointerType()) ?
"&"sv :
""sv))};
4515 mOutputFormatHelper.Append(castName,
"<"sv, castDestTypeText,
">("sv);
4517 mOutputFormatHelper.Append(
')');
4521 void CodeGenerator::InsertArgWithParensIfNeeded(
const Stmt* stmt)
4523 const bool needsParens = [&]() {
4524 if(
const auto* expr = dyn_cast_or_null<Expr>(stmt)) {
4525 if(
const auto* dest = dyn_cast_or_null<UnaryOperator>(expr->IgnoreImplicit())) {
4526 return (dest->getOpcode() == clang::UO_Deref);
4533 WrapInParensIfNeeded(needsParens, [&] { InsertArg(stmt); });
4537 void CodeGenerator::InsertSuffix(
const QualType& type)
4539 if(
const auto* typePtr = type.getTypePtrOrNull(); typePtr and typePtr->isBuiltinType()) {
4540 if(
const auto* bt = dyn_cast_or_null<BuiltinType>(typePtr)) {
4541 const auto kind = bt->getKind();
4543 mOutputFormatHelper.Append(GetBuiltinTypeSuffix(kind));
4549 void CodeGenerator::InsertTemplateArgs(
const ClassTemplateSpecializationDecl& clsTemplateSpe)
4551 if(
const auto* ar = clsTemplateSpe.getTemplateArgsAsWritten()) {
4552 InsertTemplateArgs(ar->arguments());
4554 InsertTemplateArgs(clsTemplateSpe.getTemplateArgs());
4559 void CodeGenerator::HandleTemplateParameterPack(
const ArrayRef<TemplateArgument>& args)
4561 ForEachArg(args, [&](
const auto& arg) { InsertTemplateArg(arg); });
4565 void CodeGenerator::InsertTemplateArg(
const TemplateArgument& arg)
4567 switch(arg.getKind()) {
4568 case TemplateArgument::Type: mOutputFormatHelper.Append(
GetName(arg.getAsType()));
break;
4569 case TemplateArgument::Declaration:
4571 if(
const auto decl = dyn_cast_or_null<TemplateParamObjectDecl>(arg.getAsDecl())) {
4572 mOutputFormatHelper.Append(
GetName(*decl));
4574 mOutputFormatHelper.Append(
"&"sv,
GetName(*arg.getAsDecl(), QualifiedName::Yes));
4577 case TemplateArgument::NullPtr: mOutputFormatHelper.Append(
kwNullptr);
break;
4578 case TemplateArgument::Integral:
4580 if(
const auto& integral = arg.getAsIntegral(); arg.getIntegralType()->isCharType()) {
4581 const char c{
static_cast<char>(integral.getZExtValue())};
4582 mOutputFormatHelper.Append(
"'"sv, std::string{c},
"'"sv);
4584 mOutputFormatHelper.Append(integral);
4588 case TemplateArgument::Expression: {
4590 mOutputFormatHelper.Append(
4594 InsertArg(arg.getAsExpr());
4599 case TemplateArgument::Pack: HandleTemplateParameterPack(arg.pack_elements());
break;
4600 case TemplateArgument::Template:
4601 mOutputFormatHelper.Append(
GetName(*arg.getAsTemplate().getAsTemplateDecl()));
4603 case TemplateArgument::TemplateExpansion:
4604 mOutputFormatHelper.Append(
GetName(*arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()));
4606 case TemplateArgument::Null: mOutputFormatHelper.Append(
"null"sv);
break;
4607 case TemplateArgument::StructuralValue: mOutputFormatHelper.Append(arg.getAsStructuralValue());
break;
4612 void CodeGenerator::HandleLocalStaticNonTrivialClass(
const VarDecl* stmt)
4619 const bool threadSafe{langOpts.ThreadsafeStatics and langOpts.CPlusPlus11 and
4620 (stmt->isLocalVarDecl() ) and not stmt->getTLSKind()};
4623 const std::string compilerBoolVarName{
StrCat(internalVarName,
"Guard"sv)};
4626 auto* compilerGuardVar =
4627 Variable(compilerBoolVarName, threadSafe ?
Typedef(
"uint64_t"sv, ctx.UnsignedLongTy) : ctx.BoolTy);
4628 compilerGuardVar->setStorageClass(StorageClass::SC_Static);
4629 InsertArg(compilerGuardVar);
4632 auto* compilerStorageVar =
Variable(internalVarName,
4633 ctx.getConstantArrayType(ctx.CharTy,
4634 llvm::APInt(ctx.getTypeSize(ctx.getSizeType()), 0),
4636 ArraySizeModifier::Normal,
4639 compilerStorageVar->setStorageClass(StorageClass::SC_Static);
4642 AlignedAttr::CreateImplicit(
const_cast<ASTContext&
>(ctx),
4646 AlignedAttr::Spelling::Keyword_alignas);
4648 compilerStorageVar->addAttr(alignedAttr);
4650 const std::string typeName{
GetName(stmt->getType())};
4651 mOutputFormatHelper.AppendSemiNewLine(
4652 "alignas("sv, typeName,
") static char "sv, internalVarName,
"[sizeof("sv, typeName,
")]"sv);
4655 mOutputFormatHelper.AppendNewLine();
4659 const bool canThrow{[&] {
4660 const ValueDecl* decl = [&]() ->
const ValueDecl* {
4661 const auto* init = stmt->getInit()->IgnoreCasts();
4662 if(
const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init)) {
4663 return ctorExpr->getConstructor();
4664 }
else if(
const auto* callExpr = dyn_cast_or_null<CallExpr>(init)) {
4665 return callExpr->getDirectCallee();
4672 if(
const auto* func = decl->getType()->castAs<FunctionProtoType>()) {
4673 return not func->isNothrow();
4681 auto* init =
const_cast<Expr*
>(stmt->getInit());
4683 if(
const bool isCallExpr{not isa<CXXConstructExpr>(init->IgnoreCasts())}; isCallExpr) {
4685 init =
Call(
"std::move"sv, {init});
4694 auto type = stmt->getType();
4695 type.removeLocalConst();
4696 SmallVector<Stmt*, 4> allocAndFlagBodyStmts{
New({
Ref(compilerStorageVar)}, init, type),
4698 auto allocAndFlagBodyCompound =
mkCompoundStmt(allocAndFlagBodyStmts);
4705 Try(allocAndFlagBodyCompound,
Catch({
Call(
"__cxa_guard_abort"sv, {
Ref(compilerGuardVar)}),
Throw()})));
4707 innerBodyStmts.AddBodyStmts(allocAndFlagBodyCompound);
4715 StrCat(
"__cxa_atexit("sv, typeName,
"::~"sv, typeName,
", &"sv, internalVarName,
", &__dso_handle);"sv)));
4717 auto* aquireIf =
If(
Call(
"__cxa_guard_acquire"sv, {
Ref(compilerGuardVar)}), innerBodyStmts);
4718 bodyStmts.AddBodyStmts(aquireIf);
4720 bodyStmts.AddBodyStmts(allocAndFlagBodyCompound);
4727 std::string_view CodeGenerator::GetBuiltinTypeSuffix(
const BuiltinType::Kind& kind)
4729 #define CASE(K, retVal) \
4730 case BuiltinType::K: return retVal
4733 CASE(ULong,
"UL"sv);
4734 CASE(ULongLong,
"ULL"sv);
4735 CASE(UInt128,
"ULLL"sv);
4737 CASE(LongLong,
"LL"sv);
4739 CASE(LongDouble,
"L"sv);
4746 void CodeGenerator::HandleLambdaExpr(
const LambdaExpr* lambda,
LambdaHelper& lambdaHelper)
4751 LambdaCodeGenerator codeGenerator{outputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
4752 codeGenerator.mCapturedThisAsCopy = ranges::any_of(
4753 lambda->captures(), [](
auto& c) { return (c.capturesThis() and (c.getCaptureKind() == LCK_StarThis)); });
4756 codeGenerator.
InsertArg(lambda->getLambdaClass());
4760 void CodeGenerator::InsertConceptConstraint(
const llvm::SmallVectorImpl<const Expr*>& constraints,
4761 const InsertInline insertInline)
4763 for(
OnceTrue first{};
const auto* c : constraints) {
4764 if(first and (InsertInline::Yes == insertInline)) {
4765 mOutputFormatHelper.Append(
' ');
4771 if(InsertInline::No == insertInline) {
4772 mOutputFormatHelper.AppendNewLine();
4779 void CodeGenerator::InsertConceptConstraint(
const TemplateParameterList& tmplDecl)
4781 if(
const auto* reqClause = tmplDecl.getRequiresClause()) {
4782 SmallVector<const Expr*, 1> constraints{reqClause};
4784 InsertConceptConstraint(constraints, InsertInline::No);
4790 void CodeGenerator::InsertConceptConstraint(
const FunctionDecl* tmplDecl)
4792 SmallVector<const Expr*, 5> constraints{};
4793 tmplDecl->getAssociatedConstraints(constraints);
4795 InsertConceptConstraint(constraints, InsertInline::Yes);
4800 void CodeGenerator::InsertConceptConstraint(
const VarDecl* varDecl)
4802 if(
const auto* t = varDecl->getType()->getContainedAutoType()) {
4803 if(t->getTypeConstraintConcept()) {
4812 void CodeGenerator::InsertFunctionNameWithReturnType(
const FunctionDecl& decl,
4813 const CXXConstructorDecl* cxxInheritedCtorDecl)
4815 bool isLambda{
false};
4816 bool isFirstCxxMethodDecl{
true};
4817 const auto* methodDecl{dyn_cast_or_null<CXXMethodDecl>(&decl)};
4818 bool isCXXMethodDecl{
nullptr != methodDecl};
4819 const bool isClassTemplateSpec{isCXXMethodDecl and isa<ClassTemplateSpecializationDecl>(methodDecl->getParent())};
4820 const bool requiresComment{isCXXMethodDecl and not methodDecl->isUserProvided() and
4821 not methodDecl->isExplicitlyDefaulted()};
4823 const bool isLambdaStaticInvoker{isCXXMethodDecl and methodDecl->isLambdaStaticInvoker()};
4824 const FunctionDecl& constExprDecl{not isLambdaStaticInvoker ? decl
4825 : *methodDecl->getParent()->getLambdaCallOperator()};
4829 if(requiresComment) {
4833 isLambda = methodDecl->getParent()->isLambda();
4834 isFirstCxxMethodDecl = (
nullptr == methodDecl->getPreviousDecl());
4838 if(isa<CXXConversionDecl>(decl) and TypeContainsSubType<PointerType, FunctionProtoType>(desugaredReturnType)) {
4839 mOutputFormatHelper.AppendSemiNewLine(
4843 if(isCXXMethodDecl and decl.isOutOfLine()) {
4844 if(
const auto* parent = methodDecl->getParent()) {
4845 if(
const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
4846 InsertTemplateParameters(*outerClasTemplateDecl->getTemplateParameters());
4851 if(decl.isTemplated()) {
4852 if(decl.getDescribedTemplate()) {
4853 InsertTemplateParameters(*decl.getDescribedTemplate()->getTemplateParameters());
4856 }
else if(decl.isFunctionTemplateSpecialization() or (isClassTemplateSpec and decl.isOutOfLine() and
4857 (decl.getLexicalDeclContext() != methodDecl->getParent()))) {
4858 InsertTemplateSpecializationHeader(decl);
4861 InsertAttributes(decl.attrs());
4863 if(not decl.isFunctionTemplateSpecialization() or (isCXXMethodDecl and isFirstCxxMethodDecl)) {
4864 if(not decl.isOutOfLine() or (decl.getStorageClass() == SC_Extern)) {
4871 if(isCXXMethodDecl and not decl.isOutOfLine()) {
4879 if(Decl::FOK_None != decl.getFriendObjectKind()) {
4883 if(decl.isInlined()) {
4887 if(methodDecl and isFirstCxxMethodDecl) {
4888 if(methodDecl->isVirtual()) {
4892 const auto exspec = ExplicitSpecifier::getFromDecl(methodDecl);
4894 if(
const auto* expr = exspec.getExpr()) {
4899 switch(exspec.getKind()) {
4900 case ExplicitSpecKind::Unresolved: InsertArg(expr); break;
4901 case ExplicitSpecKind::ResolvedFalse: mOutputFormatHelper.Append(kwFalse); break;
4902 case ExplicitSpecKind::ResolvedTrue: mOutputFormatHelper.Append(
"true"sv); break;
4905 AddSpaceAtTheEnd::Yes);
4907 }
else if(exspec.isExplicit()) {
4912 if(constExprDecl.isConstexpr()) {
4913 const bool skipConstexpr{isLambda and not isa<CXXConversionDecl>(constExprDecl)};
4917 const bool isConversionOpWithConstevalCallOp{[&]() {
4919 if(
const auto callOp = methodDecl->getParent()->getLambdaCallOperator()) {
4920 return callOp->isConsteval();
4927 if(not isConversionOpWithConstevalCallOp and constExprDecl.isConstexprSpecified()) {
4938 }
else if(isConversionOpWithConstevalCallOp or constExprDecl.isConsteval()) {
4947 if(not isFirstCxxMethodDecl or InsertNamespace() and decl.getQualifier()) {
4949 cg->InsertNamespace(decl.getQualifier());
4952 }
else if(not isFirstCxxMethodDecl or InsertNamespace() and not decl.getQualifier()) {
4953 const auto* parent = methodDecl->getParent();
4954 outputFormatHelper.
Append(parent->getName(),
"::"sv);
4958 if(not isa<CXXConversionDecl>(decl)) {
4959 if(isa<CXXConstructorDecl>(decl) or isa<CXXDestructorDecl>(decl)) {
4961 if(isa<CXXDestructorDecl>(decl)) {
4962 outputFormatHelper.
Append(
'~');
4965 outputFormatHelper.
Append(
GetName(*methodDecl->getParent()));
4972 if(isFirstCxxMethodDecl and decl.isFunctionTemplateSpecialization()) {
4977 outputFormatHelper.
Append(
'(');
4981 if(cxxInheritedCtorDecl) {
4983 OutputFormatHelper::NameOnly::No,
4984 OutputFormatHelper::GenMissingParamName::Yes);
4988 const OutputFormatHelper::GenMissingParamName genMissingParamName{
4989 isLambdaStaticInvoker ? OutputFormatHelper::GenMissingParamName::Yes
4990 : OutputFormatHelper::GenMissingParamName::No};
4993 decl.parameters(), OutputFormatHelper::NameOnly::No, genMissingParamName);
4995 if(
GetInsightsOptions().UseShow2C and not decl.isVariadic() and decl.param_empty()) {
4996 outputFormatHelper.
Append(
"void"sv);
5000 if(decl.isVariadic()) {
5001 outputFormatHelper.
Append(
", ..."sv);
5004 outputFormatHelper.
Append(
')');
5006 if(not isa<CXXConstructorDecl>(decl) and not isa<CXXDestructorDecl>(decl)) {
5007 if(isa<CXXConversionDecl>(decl)) {
5008 const std::string typeName{TypeContainsSubType<PointerType, FunctionProtoType>(desugaredReturnType)
5010 :
GetName(desugaredReturnType)};
5017 mOutputFormatHelper.Append(outputFormatHelper);
5020 mOutputFormatHelper.Append(
GetConst(decl));
5023 if(methodDecl->isVolatile()) {
5027 if(methodDecl->hasAttr<FinalAttr>()) {
5032 switch(decl.getType()->getAs<FunctionProtoType>()->getRefQualifier()) {
5033 case RQ_None:
break;
5034 case RQ_LValue: mOutputFormatHelper.Append(
" &"sv);
break;
5035 case RQ_RValue: mOutputFormatHelper.Append(
" &&"sv);
break;
5042 InsertConceptConstraint(&decl);
5044 if(decl.isPureVirtual()) {
5045 mOutputFormatHelper.Append(
" = 0"sv);
5048 if(decl.isDeleted()) {
5050 if(
auto* delInfo = decl.getDefalutedOrDeletedInfo()) {
5051 WrapInParens([&]() { InsertArg(delInfo->getDeletedMessage()); }, AddSpaceAtTheEnd::No);
5053 mOutputFormatHelper.AppendSemiNewLine();
5056 }
else if(decl.isDefaulted()) {
5062 void CodeGenerator::InsertCurlysIfRequired(
const Stmt* stmt)
5064 const bool requiresCurlys{not isa<InitListExpr>(stmt) and not isa<ParenExpr>(stmt) and
5065 not isa<CXXDefaultInitExpr>(stmt)};
5067 if(requiresCurlys) {
5068 mOutputFormatHelper.Append(
'{');
5073 if(requiresCurlys) {
5074 mOutputFormatHelper.Append(
'}');
5079 void CodeGenerator::WrapInParensOrCurlys(
const BraceKind braceKind,
5081 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5083 if(BraceKind::Curlys == braceKind) {
5084 mOutputFormatHelper.Append(
'{');
5086 mOutputFormatHelper.Append(
'(');
5091 if(BraceKind::Curlys == braceKind) {
5092 mOutputFormatHelper.Append(
'}');
5094 mOutputFormatHelper.Append(
')');
5097 if(AddSpaceAtTheEnd::Yes == addSpaceAtTheEnd) {
5098 mOutputFormatHelper.Append(
' ');
5103 void CodeGenerator::WrapInCompoundIfNeeded(
const Stmt* stmt,
const AddNewLineAfter addNewLineAfter)
5105 const bool hasNoCompoundStmt = not(isa<CompoundStmt>(stmt) or isa<AttributedStmt>(stmt));
5107 if(hasNoCompoundStmt) {
5108 mOutputFormatHelper.OpenScope();
5111 if(not isa<NullStmt>(stmt)) {
5114 const bool isAttrWithCompound{[&] {
5115 auto* attrStmt = dyn_cast_or_null<AttributedStmt>(stmt);
5116 return attrStmt and isa<CompoundStmt>(attrStmt->getSubStmt());
5120 if(IsStmtRequiringSemi<IfStmt, CompoundStmt, NullStmt, WhileStmt, DoStmt>(stmt) and not isAttrWithCompound) {
5121 mOutputFormatHelper.AppendSemiNewLine();
5125 if(hasNoCompoundStmt) {
5126 mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
5129 const bool addNewLine = (AddNewLineAfter::Yes == addNewLineAfter);
5130 if(addNewLine or (hasNoCompoundStmt and addNewLine)) {
5131 mOutputFormatHelper.AppendNewLine();
5132 }
else if(not addNewLine or (hasNoCompoundStmt and not addNewLine)) {
5133 mOutputFormatHelper.Append(
' ');
5138 void CodeGenerator::WrapInParens(
void_func_ref lambda,
const AddSpaceAtTheEnd addSpaceAtTheEnd)
5140 WrapInParensOrCurlys(BraceKind::Parens, lambda, addSpaceAtTheEnd);
5144 void CodeGenerator::WrapInParensIfNeeded(
bool needsParens,
5146 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5149 WrapInParensOrCurlys(BraceKind::Parens, lambda, addSpaceAtTheEnd);
5156 void CodeGenerator::WrapInCurliesIfNeeded(
bool needsParens,
5158 const AddSpaceAtTheEnd addSpaceAtTheEnd)
5161 WrapInParensOrCurlys(BraceKind::Curlys, lambda, addSpaceAtTheEnd);
5168 void CodeGenerator::WrapInCurlys(
void_func_ref lambda,
const AddSpaceAtTheEnd addSpaceAtTheEnd)
5170 WrapInParensOrCurlys(BraceKind::Curlys, lambda, addSpaceAtTheEnd);
5174 void CodeGenerator::InsertArg(
const BindingDecl*)
5181 void StructuredBindingsCodeGenerator::InsertArg(
const BindingDecl* stmt)
5183 const auto* bindingStmt = stmt->getBinding();
5190 auto type = stmt->getType();
5194 if(
const auto* holdingVar = stmt->getHoldingVar()) {
5202 type = holdingVar->getType().getCanonicalType();
5204 bindingStmt = holdingVar->getAnyInitializer();
5206 }
else if(not type->isLValueReferenceType()) {
5207 type = stmt->getASTContext().getLValueReferenceType(type);
5210 InsertAttributes(stmt->attrs());
5212 mOutputFormatHelper.Append(
GetQualifiers(*dyn_cast_or_null<VarDecl>(stmt->getDecomposedDecl())),
5216 InsertArg(bindingStmt);
5218 mOutputFormatHelper.AppendSemiNewLine();
5222 void StructuredBindingsCodeGenerator::InsertDecompositionBindings(
const DecompositionDecl& decompositionDeclStmt)
5224 for(
const auto* bindingDecl : decompositionDeclStmt.bindings()) {
5225 InsertArg(bindingDecl);
5230 void StructuredBindingsCodeGenerator::InsertArg(
const DeclRefExpr* stmt)
5232 const auto name =
GetName(*stmt);
5234 mOutputFormatHelper.Append(name);
5237 mOutputFormatHelper.Append(mVarName);
5239 InsertTemplateArgs(*stmt);
5244 void LambdaCodeGenerator::InsertArg(
const CXXThisExpr* stmt)
5248 if(mCapturedThisAsCopy) {
#define LAMBDA_SCOPE_HELPER(type)
Convenience macro to create a LambdaScopeHandler on the stack.
#define CONDITIONAL_LAMBDA_SCOPE_HELPER(type, cond)
The lambda scope helper is only created if cond is true.
InsightsOptions & GetInsightsOptionsRW()
const CompilerInstance & GetGlobalCI()
Get access to the CompilerInstance.
const ASTContext & GetGlobalAST()
Get access to the ASTContext.
const InsightsOptions & GetInsightsOptions()
Get the global C++ Insights options.
#define SCOPE_HELPER(d)
Helper to create a ScopeHandler on the stack which adds the current Decl to it and removes it once th...
constexpr std::string_view kwTemplate
constexpr std::string_view kwNull
constexpr std::string_view kwCommentStart
constexpr std::string_view kwRequiresSpace
constexpr std::string_view kwStaticAssert
constexpr std::string_view kwCoAwaitSpace
constexpr std::string_view kwReturn
constexpr std::string_view kwReinterpretCast
constexpr std::string_view kwNamespaceSpace
constexpr std::string_view kwContinue
constexpr std::string_view kwSpaceConstEvalSpace
constexpr std::string_view cxaStart
constexpr std::string_view kwCCommentEndSpace
constexpr std::string_view kwInlineSpace
constexpr std::string_view kwMutableSpace
constexpr std::string_view kwUsingSpace
constexpr std::string_view kwDelete
constexpr std::string_view kwConstExprSpace
constexpr std::string_view kwTemplateSpace
constexpr std::string_view kwCoReturnSpace
constexpr std::string_view kwCoYieldSpace
constexpr std::string_view kwSpaceConstExpr
constexpr std::string_view kwSpaceCCommentEndSpace
constexpr std::string_view kwNamespace
constexpr std::string_view kwCaseSpace
constexpr std::string_view kwSizeof
constexpr std::string_view kwUnionSpace
constexpr std::string_view kwSpaceCCommentEnd
constexpr std::string_view kwEnumSpace
constexpr std::string_view kwElipsisSpace
constexpr std::string_view kwClassSpace
constexpr std::string_view kwTypeId
constexpr std::string_view kwConstEvalSpace
constexpr std::string_view kwSpaceEqualsDefault
constexpr std::string_view kwThis
constexpr std::string_view kwSpaceVolatile
constexpr std::string_view kwStructSpace
constexpr std::string_view functionPointerPrefix
constexpr std::string_view kwStaticCast
constexpr std::string_view kwElipsis
constexpr std::string_view kwOperator
constexpr std::string_view kwSpaceFinal
constexpr std::string_view kwNoexcept
constexpr std::string_view kwCCommentStartSpace
constexpr std::string_view kwTypeNameSpace
constexpr std::string_view kwExplicitSpace
constexpr std::string_view kwSwitch
constexpr std::string_view kwFriendSpace
constexpr std::string_view kwOperatorSpace
constexpr std::string_view kwInternalThis
constexpr std::string_view kwCppCommentStartSpace
constexpr std::string_view kwStaticSpace
constexpr std::string_view kwSpaceNoexcept
constexpr std::string_view kwSpaceEqualsDelete
constexpr std::string_view kwAlignof
constexpr std::string_view kwRequires
constexpr std::string_view kwNullptr
constexpr std::string_view kwFalse
constexpr std::string_view kwTrySpace
constexpr std::string_view kwExplicit
constexpr std::string_view hlpArrow
constexpr std::string_view hlpAssing
constexpr std::string_view kwBreak
constexpr std::string_view kwDoSpace
constexpr std::string_view memberVariablePointerPrefix
constexpr std::string_view kwWhile
constexpr std::string_view cxaAtExit
constexpr std::string_view kwVirtualSpace
constexpr std::string_view kwGotoSpace
constexpr std::string_view kwConceptSpace
#define RETURN_IF(cond)
! A helper inspired by https://github.com/Microsoft/wil/wiki/Error-handling-helpers
llvm::function_ref< void()> void_func_ref
void push(TStackListEntry &entry) noexcept
ArrayInitCodeGenerator(OutputFormatHelper &_outputFormatHelper, const uint64_t index)
void InsertArg(const ArrayInitIndexExpr *) override
Find a DeclRefExpr belonging to a DecompositionDecl.
bool Find(const Stmt *stmt)
BindingDeclFinder()=default
void VisitStmt(const Stmt *stmt)
void VisitDeclRefExpr(const DeclRefExpr *expr)
static CfrontVtableData & VtableData()
void setInsertName(bool b)
OutputFormatHelper & buffer()
LambdaScopeHandler(LambdaStackType &stack, OutputFormatHelper &outputFormatHelper, const LambdaCallerType lambdaCallerType)
More or less the heart of C++ Insights.
void InsertFunctionNameWithReturnType(const FunctionDecl &decl, const CXXConstructorDecl *cxxInheritedCtorDecl=nullptr)
Insert the code for a FunctionDecl.
void WrapInParensIfNeeded(bool needsParens, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
void WrapInCompoundIfNeeded(const Stmt *stmt, const AddNewLineAfter addNewLineAfter)
static std::map< std::string, bool > mSeenDecls
void InsertQualifierAndNameWithTemplateArgs(const DeclarationName &declName, const auto *stmt)
void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
static std::string FillConstantArray(const ConstantArrayType *ct, const std::string &value, const uint64_t startAt)
virtual void InsertArg(const Decl *stmt)
void InsertTemplateSpecializationHeader(const Decl &)
Insert template<> to introduce a template specialization.
virtual bool InsertVarDecl(const VarDecl *)
const LambdaExpr * mLambdaExpr
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaStackType &lambdaStack, LambdaInInitCapture lambdaInitCapture, ProcessingPrimaryTemplate processingPrimaryTemplate)
! We do not want to transform a primary template which contains a Coroutine.
void InsertInstantiationPoint(const SourceManager &sm, const SourceLocation &instLoc, std::string_view text={})
Inserts the instantiation point of a template.
ProcessingPrimaryTemplate mProcessingPrimaryTemplate
void InsertTemplateArgs(const T &t)
std::optional< size_t > mCurrentVarDeclPos
OutputFormatHelper * mOutputFormatHelperOutside
Helper output buffer for std::initializer_list expansion.
void WrapInCurliesIfNeeded(bool needsParens, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
void InsertTemplateGuardEnd(const FunctionDecl *stmt)
static std::string GetValueOfValueInit(const QualType &t)
void LifetimeAddExtended(const VarDecl *, const ValueDecl *)
void HandleLocalStaticNonTrivialClass(const VarDecl *stmt)
Show what is behind a local static variable.
std::optional< size_t > mCurrentCallExprPos
void InsertTemplateParameters(const TemplateParameterList &list, const TemplateParamsOnly templateParamsOnly=TemplateParamsOnly::No)
! Skip template, type constraints and class/typename.
void InsertIfOrSwitchInitVariables(same_as_any_of< const IfStmt, const SwitchStmt > auto *stmt)
virtual bool InsertSemi()
void UpdateCurrentPos(std::optional< size_t > &pos)
bool InsertLambdaStaticInvoker(const CXXMethodDecl *cxxMethodDecl)
void InsertTemplateGuardBegin(const FunctionDecl *stmt)
LambdaStackType & mLambdaStack
void InsertConceptConstraint(const llvm::SmallVectorImpl< const Expr * > &constraints, const InsertInline insertInline)
virtual bool InsertComma()
virtual bool InsertNamespace() const
void ForEachArg(const auto &arguments, auto &&lambda)
void InsertQualifierAndName(const DeclarationName &declName, const NestedNameSpecifier *qualifier, const bool hasTemplateKeyword)
NoEmptyInitList mNoEmptyInitList
At least in case if a requires-clause containing T{} we don't want to get T{{}}.
friend class CodeGeneratorVariant
void InsertMethodBody(const FunctionDecl *stmt, const size_t posBeforeFunc)
bool mRequiresImplicitReturnZero
Track whether this is a function with an imlpicit return 0.
static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS
void WrapInParensOrCurlys(const BraceKind curlys, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
std::optional< size_t > mCurrentFieldPos
void InsertTemplateArg(const TemplateArgument &arg)
void InsertSuffix(const QualType &type)
void InsertAttributes(const Decl *)
void StartLifetimeScope()
virtual bool SkipSpaceAfterVarDecl()
void InsertCurlysIfRequired(const Stmt *stmt)
Check whether or not this statement will add curlys or parentheses and add them only if required.
OutputFormatHelper & mOutputFormatHelper
LifetimeTracker mLifeTimeTracker
void InsertTemplateArgsObjectParam(const ArrayRef< TemplateArgument > &array)
void ParseDeclContext(const DeclContext *Ctx)
A special container which creates either a CodeGenerator or a CfrontCodeGenerator depending on the co...
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
A special code generator for Lambda init captures which use std::move.
LambdaInitCaptureCodeGenerator(OutputFormatHelper &outputFormatHelper, LambdaStackType &lambdaStack, std::string_view varName)
void InsertArg(const DeclRefExpr *stmt) override
void InsertArg(const LambdaExpr *stmt) override
bool EndScope(OutputFormatHelper &ofm, bool clear)
void Add(const VarDecl *decl)
void AddExtended(const VarDecl *decl, const ValueDecl *extending)
void StartScope(bool funcStart)
! Find a LambdaExpr inside a Decltype
static std::string RemoveCurrentScope(std::string name)
Remove the current scope from a string.
Specialization for ::llvm::raw_string_ostream with an internal std::string buffer.
void Print(const TemplateArgument &)
StructuredBindingsCodeGenerator(OutputFormatHelper &_outputFormatHelper, std::string &&varName)
virtual bool ShowXValueCasts() const override
Show casts to xvalues independent from the show all casts option.
Find a DeclRefExpr belonging to a DecompositionDecl.
void VisitStmt(Stmt *stmt)
TemporaryDeclFinder(CodeGenerator &_codeGenerator, const Stmt *stmt, bool inspectReturn=false)
void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *expr)
void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *stmt)
Handle using statements which pull functions ore members from a base class into the class.
bool InsertNamespace() const override
void InsertArg(const FieldDecl *stmt) override
UsingCodeGenerator(OutputFormatHelper &_outputFormatHelper)
void InsertArg(const CXXMethodDecl *stmt) override
void InsertArg(const CXXRecordDecl *) override
void InsertArg(const TypedefDecl *) override
BinaryOperator * Equal(Expr *var, Expr *assignExpr)
DeclStmt * mkDeclStmt(Dcls... dcls)
DeclRefExpr * mkDeclRefExpr(const ValueDecl *vd)
QualType Typedef(std::string_view name, QualType underlayingType)
CXXNewExpr * New(ArrayRef< Expr * > placementArgs, const Expr *expr, QualType t)
CallExpr * Call(const FunctionDecl *fd, ArrayRef< Expr * > params)
UnaryOperator * Ref(const Expr *e)
VarDecl * Variable(std::string_view name, QualType type, DeclContext *dc)
SmallVector< Expr *, 5 > ArgsToExprVector(const Expr *expr)
ReturnStmt * Return(Expr *stmt)
Stmt * Comment(std::string_view comment)
IfStmt * If(const Expr *condition, ArrayRef< Stmt * > bodyStmts)
BinaryOperator * And(VarDecl *lhs, Expr *rhs)
GotoStmt * Goto(std::string_view labelName)
InitListExpr * InitList(ArrayRef< Expr * > initExprs, QualType t)
CXXCatchStmt * Catch(ArrayRef< Stmt * > body)
CXXThrowExpr * Throw(const Expr *expr)
void ReplaceNode(Stmt *parent, Stmt *oldNode, Stmt *newNode)
UnaryExprOrTypeTraitExpr * Sizeof(QualType toType)
static CallExpr * CallConstructor(QualType ctorType, DeclRefExpr *lhsDeclRef, Expr *lhsMemberExpr, ArrayRef< Expr * > callParams, DoCast doCast, AsReference asReference)
LabelStmt * Label(std::string_view name)
CXXBoolLiteralExpr * Bool(bool b)
FunctionDecl * Function(std::string_view name, QualType returnType, const params_vector ¶meters)
CompoundStmt * mkCompoundStmt(ArrayRef< Stmt * > bodyStmts, SourceLocation beginLoc, SourceLocation endLoc)
IntegerLiteral * Int32(uint64_t value)
CXXStaticCastExpr * StaticCast(QualType toType, const Expr *toExpr, bool makePointer)
BinaryOperator * Assign(const VarDecl *var, Expr *assignExpr)
CXXTryStmt * Try(const Stmt *tryBody, CXXCatchStmt *catchAllBody)
CallExpr * CallDestructor(const VarDecl *varDecl)
void StrCat(std::string &ret, const auto &... args)
static std::string GetName(QualType t, const Unqualified unqualified=Unqualified::No, const InsightsSuppressScope supressScope=InsightsSuppressScope::No)
std::string ConvertToBoolString(bool b)
Convert a boolean value to a string representation of "true" or "false".
static std::string AccessToStringWithColon(const AccessSpecifier &access)
void InsertBefore(std::string &source, const std::string_view &find, const std::string_view &replace)
static void PushGlobalVariableDtor(const Expr *callExpr)
uint64_t GetSize(const ConstantArrayType *arrayType)
std::string GetLambdaName(const CXXRecordDecl &lambda)
@ HeaderException
Track whether there was a noexcept transformation requireing the exception header.
bool Contains(const std::string_view source, const std::string_view search)
BUILD_OPT_AND(IsPointer, QualType)
std::string BuildRetTypeName(const Decl &decl)
static void ToDo(std::string_view name, OutputFormatHelper &outputFormatHelper, std::source_location loc)
void DPrint([[maybe_unused]] const char *fmt, [[maybe_unused]] const auto &... args)
Debug print which is disabled in release-mode.
const std::string GetNoExcept(const FunctionDecl &decl)
const SourceManager & GetSM(const Decl &decl)
std::string GetPlainName(const DeclRefExpr &DRE)
static std::string_view ArrowOrDot(bool isArrow)
std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword)
void PushVtableEntry(const CXXRecordDecl *record, const CXXRecordDecl *recordB, VarDecl *decl)
int GetGlobalVtablePos(const CXXRecordDecl *record, const CXXRecordDecl *recordB)
static T ValueOr(bool b, T val, T el)
void Error(const char *fmt, const auto &... args)
Log an error.
Once< false > OnceFalse
Returns false only once, following checks return true.
static auto & GetRecordLayout(const RecordDecl *recordDecl)
std::string MakeLineColumnName(const SourceManager &sm, const SourceLocation &loc, const std::string_view &prefix)
static std::string_view GetCastName(const CastKind castKind, bool constnessChange=false)
static std::string GetTypeConstraintAsString(const TypeConstraint *typeConstraint)
static bool IsStmtRequiringSemi(const Stmt *stmt)
QualType GetType(QualType t)
In Cfront mode we transform references to pointers.
std::string GetName(const NamedDecl &nd, const QualifiedName qualifiedName)
const LangOptions & GetLangOpts(const Decl &decl)
std::string EmitGlobalVariableCtors()
static std::string_view EllipsisSpace(bool b)
std::string BuildInternalVarName(const std::string_view &varName)
auto GetSpaces(std::string::size_type offset)
static void PushGlobalVariable(const Expr *callExpr)
static std::string FormatVarTemplateSpecializationDecl(const Decl *decl, std::string &&defaultName)
static std::string GetStorageClassAsStringWithSpace(const StorageClass &sc)
static SmallVector< Expr *, 10 > globalVarDtors
static std::string_view GetTagDeclTypeName(const TagDecl &decl)
const std::string_view GetConst(const FunctionDecl &decl)
BUILD_OPT_AND_O(CanonicalType, const InitListExpr &, QualType)
static bool IsConstQualifiedType(QualType type)
std::string GetTemporaryName(const Expr &tmp)
std::string BuildTemplateParamObjectName(std::string name)
static std::string GetQualifiers(const VarDecl &vd)
bool IsReferenceType(const ValueDecl *decl)
static T ValueOrDefault(bool b, T v)
void AppendTemplateTypeParamName(OutputFormatHelper &ofm, const TemplateTypeParmDecl *decl, const bool isParameter, const TemplateTypeParmType *type)
static std::string_view Ellipsis(bool b)
Once< true > OnceTrue
Returns true only once, following checks return false.
std::string GetDeclContext(const DeclContext *ctx, WithTemplateParameters withTemplateParameters)
const QualType GetDesugarType(const QualType &QT)
Remove decltype from a QualType, if possible.
static SmallVector< Expr *, 10 > globalVarCtors
static std::string GetUnqualifiedScopelessName(const Type *type, const InsightsSuppressScope supressScope)
bool IsStaticStorageClass(const CXXMethodDecl *md)
static bool IsPrimaryTemplatePackExpansionExpr(const ParenListExpr *stmt)
void EnableGlobalInsert(GlobalInserts idx)
std::string GetNestedName(const NestedNameSpecifier *nns, const IgnoreNamespace ignoreNamespace)
static std::optional< std::pair< QualType, APValue > > EvaluateNTTPAsConstantExpr(const Expr *expr)
Evaluates a potential NTTP as a constant expression.
static SmallVector< std::pair< std::pair< const CXXRecordDecl *, const CXXRecordDecl * >, VarDecl * >, 10 > gVtables
void for_each(T start, T end, TFunc &&func)
static std::string_view GetStorageClassAsString(const StorageClass &sc)
static std::optional< std::string > GetFieldDeclNameForLambda(const FieldDecl &fieldDecl, const CXXRecordDecl &cxxRecordDecl)
std::string GetTypeNameAsParameter(const QualType &t, std::string_view varName, const Unqualified unqualified)
static bool IsTrivialStaticClassVarDecl(const DeclRefExpr &declRefExpr)
std::string StrCat(const auto &... args)
QualType GetDesugarReturnType(const FunctionDecl &FD)
VarDecl * VtblArrayVar(int size)
! A helper type to have a container for ArrayRef
void AddBodyStmts(Stmt *body)
Handy helper to avoid longish comparisons.
constexpr bool any_of(const auto &... ts) const