8 #ifndef INSIGHTS_CODE_GENERATOR_H
9 #define INSIGHTS_CODE_GENERATOR_H
11 #include "clang/AST/ASTContext.h"
12 #include "clang/Rewrite/Core/Rewriter.h"
13 #include "llvm/ADT/APInt.h"
27 void PushVtableEntry(
const CXXRecordDecl*,
const CXXRecordDecl*, VarDecl* decl);
32 std::string mComment{};
41 std::string_view
Comment()
const {
return mComment; }
43 static bool classof(
const Stmt* T) {
return T->getStmtClass() == NoStmtClass; }
47 static child_iterator iter{};
52 static const_child_iterator iter{};
68 inline static int scopeCounter{};
70 SmallVector<LifetimeEntry, 10> objects{};
75 void Add(
const VarDecl* decl);
76 void AddExtended(
const VarDecl* decl,
const ValueDecl* extending);
125 : mLambdaCallerType{lambdaCallerType}
126 , mCurrentVarDeclPos{outputFormatHelper.CurrentPos()}
127 , mOutputFormatHelper{outputFormatHelper}
129 mLambdaOutputFormatHelper.
SetIndent(mOutputFormatHelper);
134 if(not mLambdaOutputFormatHelper.
empty()) {
135 mOutputFormatHelper.
InsertAt(mCurrentVarDeclPos, mLambdaOutputFormatHelper);
141 std::string&
inits() {
return mInits; }
145 if(not mInits.empty()) {
146 outputFormatHelper.
Append(mInits);
158 const size_t mCurrentVarDeclPos;
161 std::string mInits{};
172 ProcessingPrimaryTemplate);
176 LambdaInInitCapture lambdaInitCapture,
177 ProcessingPrimaryTemplate processingPrimaryTemplate)
198 ProcessingPrimaryTemplate processingPrimaryTemplate)
199 :
CodeGenerator{_outputFormatHelper, lambdaStack, LambdaInInitCapture::No, processingPrimaryTemplate}
205 #define IGNORED_DECL(type) \
206 virtual void InsertArg(const type*) {}
207 #define IGNORED_STMT(type) \
208 virtual void InsertArg(const type*) {}
209 #define SUPPORTED_DECL(type) virtual void InsertArg(const type* stmt);
210 #define SUPPORTED_STMT(type) virtual void InsertArg(const type* stmt);
214 virtual void InsertArg(
const Decl* stmt);
220 if constexpr(std::is_same_v<T, FunctionDecl>) {
221 if(
const auto* tmplArgs = t.getTemplateSpecializationArgs()) {
224 }
else if constexpr(std::is_same_v<T, VarTemplateSpecializationDecl>) {
227 }
else if constexpr(requires { t.template_arguments(); }) {
228 if constexpr(std::is_same_v<DeclRefExpr, T>) {
229 if(0 == t.getNumTemplateArgs()) {
236 }
else if constexpr(requires { t.asArray(); }) {
252 const CXXConstructorDecl* cxxInheritedCtorDecl =
nullptr);
277 const TemplateParamsOnly templateParamsOnly = TemplateParamsOnly::No);
305 virtual void FormatCast(
const std::string_view castName,
306 const QualType& CastDestType,
308 const CastKind& castKind);
321 const InsertInline insertInline);
332 if(stmt->getNumTemplateArgs()) {
334 }
else if(stmt->hasExplicitTemplateArgs()) {
341 const NestedNameSpecifier* qualifier,
342 const bool hasTemplateKeyword);
362 void InsertMethodBody(
const FunctionDecl* stmt,
const size_t posBeforeFunc);
391 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
395 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
401 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
424 static std::string
FillConstantArray(
const ConstantArrayType* ct,
const std::string& value,
const uint64_t startAt);
442 NoEmptyInitList::No};
470 void InsertArg(
const CXXThisExpr* stmt)
override;
491 :
CodeGenerator{_outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
540 const size_t posBeforeFunc,
541 std::string_view fsmName,
542 size_t suspendsCount,
545 , mPosBeforeFunc{posBeforeFunc}
546 , mSuspendsCount{suspendsCount}
556 void InsertArg(
const ImplicitCastExpr* stmt)
override;
557 void InsertArg(
const CallExpr* stmt)
override;
558 void InsertArg(
const CXXRecordDecl* stmt)
override;
559 void InsertArg(
const OpaqueValueExpr* stmt)
override;
561 void InsertArg(
const CoroutineBodyStmt* stmt)
override;
562 void InsertArg(
const CoroutineSuspendExpr* stmt)
override;
563 void InsertArg(
const CoreturnStmt* stmt)
override;
565 void InsertCoroutine(
const FunctionDecl& fd,
const CoroutineBodyStmt* body);
570 bool InsertVarDecl(
const VarDecl* vd)
override {
return mInsertVarDecl or (vd and vd->isStaticLocal()); }
583 const size_t mPosBeforeFunc;
584 size_t mPosBeforeSuspendExpr{};
585 size_t mSuspendsCount{};
586 size_t mSuspendsCounter{};
587 bool mInsertVarDecl{
true};
588 bool mSupressCasts{};
589 bool mSupressRecordDecls{};
590 std::string mFrameName{};
591 std::string mFSMName{};
592 CoroutineASTData mASTData{};
593 llvm::DenseMap<const Stmt*, bool> mBinaryExprs{};
594 static inline llvm::DenseMap<const Expr*, std::pair<const DeclRefExpr*, std::string>>
597 QualType GetFrameType()
const {
return QualType(mASTData.mFrameType->getTypeForDecl(), 0); }
598 QualType GetFramePointerType()
const;
600 std::string BuildResumeLabelName(
int)
const;
601 FieldDecl*
AddField(std::string_view name, QualType type);
603 void InsertArgWithNull(
const Stmt* stmt);
613 static inline llvm::DenseMap<std::pair<const Decl*, std::pair<const CXXRecordDecl*, const CXXRecordDecl*>>,
int>
615 bool mInsertSemi{
true};
618 using CodeGenerator::CodeGenerator;
620 using CodeGenerator::InsertArg;
622 void InsertArg(
const CXXThisExpr*)
override;
623 void InsertArg(
const CXXDeleteExpr*)
override;
624 void InsertArg(
const CXXNewExpr*)
override;
625 void InsertArg(
const CXXOperatorCallExpr*)
override;
626 void InsertArg(
const CXXNullPtrLiteralExpr*)
override;
627 void InsertArg(
const StaticAssertDecl*)
override;
628 void InsertArg(
const CXXRecordDecl*)
override;
629 void InsertArg(
const CXXMemberCallExpr*)
override;
630 void InsertArg(
const CXXConstructExpr*)
override;
631 void InsertArg(
const FunctionDecl* stmt)
override;
632 void InsertArg(
const TypedefDecl* stmt)
override;
634 void InsertCXXMethodDecl(
const CXXMethodDecl*, CodeGenerator::SkipBody)
override;
636 void FormatCast(
const std::string_view,
const QualType&,
const Expr*,
const CastKind&)
override;
643 VarDecl* VtblArrayVar(
int size);
644 FieldDecl* VtblPtrField(
const CXXRecordDecl* parent);
665 bool InsertSemi()
override {
return std::exchange(mInsertSemi,
true); }
681 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate);
682 CodeGenerators(
OutputFormatHelper& _outputFormatHelper, CodeGenerator::LambdaInInitCapture lambdaInitCapture);
700 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
701 : cgs{_outputFormatHelper, lambdaStack, processingPrimaryTemplate}
702 , ofm{_outputFormatHelper}
709 : cgs{_outputFormatHelper, lambdaInitCapture}
710 , ofm{_outputFormatHelper}
llvm::function_ref< void()> void_func_ref
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
bool InsertSemi() override
LambdaCallerType callerType() const
void insertInits(OutputFormatHelper &outputFormatHelper)
LambdaHelper(const LambdaCallerType lambdaCallerType, OutputFormatHelper &outputFormatHelper)
void setInsertName(bool b)
OutputFormatHelper & buffer()
LambdaScopeHandler(LambdaStackType &stack, OutputFormatHelper &outputFormatHelper, const LambdaCallerType lambdaCallerType)
More or less the heart of C++ Insights.
STRONG_BOOL(LambdaInInitCapture)
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 HandleCompoundStmt(const CompoundStmt *stmt)
void InsertQualifierAndNameWithTemplateArgs(const DeclarationName &declName, const auto *stmt)
void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
LambdaInInitCapture mLambdaInitCapture
LambdaStackType mLambdaStackThis
static std::string FillConstantArray(const ConstantArrayType *ct, const std::string &value, const uint64_t startAt)
void InsertTemplateArg(const TemplateArgumentLoc &arg)
virtual void InsertArg(const Decl *stmt)
void InsertTemplateSpecializationHeader(const Decl &)
Insert template<> to introduce a template specialization.
void WrapInCurlys(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
virtual bool InsertVarDecl(const VarDecl *)
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaStackType &lambdaStack, ProcessingPrimaryTemplate processingPrimaryTemplate)
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaInInitCapture lambdaInitCapture)
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
STRONG_BOOL(InsertInline)
void InsertAttribute(const Attr &)
OutputFormatHelper * mOutputFormatHelperOutside
Helper output buffer for std::initializer_list expansion.
void HandleLambdaExpr(const LambdaExpr *stmt, LambdaHelper &lambdaHelper)
void WrapInCurliesIfNeeded(bool needsParens, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
STRONG_BOOL(AddNewLineAfter)
void InsertTemplateGuardEnd(const FunctionDecl *stmt)
static std::string GetValueOfValueInit(const QualType &t)
STRONG_BOOL(TemplateParamsOnly)
void LifetimeAddExtended(const VarDecl *, const ValueDecl *)
STRONG_BOOL(ProcessingPrimaryTemplate)
void HandleLocalStaticNonTrivialClass(const VarDecl *stmt)
Show what is behind a local static variable.
virtual void FormatCast(const std::string_view castName, const QualType &CastDestType, const Expr *SubExpr, const CastKind &castKind)
std::optional< size_t > mCurrentCallExprPos
virtual void InsertCXXMethodDecl(const CXXMethodDecl *stmt, SkipBody skipBody)
void InsertTemplateParameters(const TemplateParameterList &list, const TemplateParamsOnly templateParamsOnly=TemplateParamsOnly::No)
! Skip template, type constraints and class/typename.
void HandleTemplateParameterPack(const ArrayRef< TemplateArgument > &args)
void InsertIfOrSwitchInitVariables(same_as_any_of< const IfStmt, const SwitchStmt > auto *stmt)
STRONG_BOOL(NoEmptyInitList)
STRONG_BOOL(UseCommaInsteadOfSemi)
virtual bool InsertSemi()
void UpdateCurrentPos(std::optional< size_t > &pos)
bool InsertLambdaStaticInvoker(const CXXMethodDecl *cxxMethodDecl)
virtual ~CodeGenerator()=default
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{{}}.
std::optional< size_t > mCurrentReturnPos
void InsertMethodBody(const FunctionDecl *stmt, const size_t posBeforeFunc)
bool mRequiresImplicitReturnZero
Track whether this is a function with an imlpicit return 0.
void InsertConstructorExpr(const T *stmt)
Generalized function to insert either a CXXConstructExpr or CXXUnresolvedConstructExpr.
void InsertArgWithParensIfNeeded(const Stmt *stmt)
static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS
void WrapInParensOrCurlys(const BraceKind curlys, void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd=AddSpaceAtTheEnd::No)
UseCommaInsteadOfSemi mUseCommaInsteadOfSemi
std::optional< size_t > mCurrentFieldPos
void InsertTemplateArg(const TemplateArgument &arg)
void InsertSuffix(const QualType &type)
STRONG_BOOL(ShowConstantExprValue)
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
void InsertTemplate(const FunctionTemplateDecl *, bool withSpec)
bool InsideDecltype() const
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper)
void InsertCXXMethodHeader(const CXXMethodDecl *stmt, OutputFormatHelper &initOutputFormatHelper)
void InsertTemplateArgs(const ArrayRef< T > &array)
STRONG_BOOL(AddSpaceAtTheEnd)
LifetimeTracker mLifeTimeTracker
void InsertTemplateArgsObjectParam(const ArrayRef< TemplateArgument > &array)
virtual bool ShowXValueCasts() const
Show casts to xvalues independent from the show all casts option.
static std::string_view GetBuiltinTypeSuffix(const BuiltinType::Kind &kind)
ShowConstantExprValue mShowConstantExprValue
void ParseDeclContext(const DeclContext *Ctx)
A special container which creates either a CodeGenerator or a CfrontCodeGenerator depending on the co...
CodeGeneratorVariant(OutputFormatHelper &_outputFormatHelper, CodeGenerator::LambdaStackType &lambdaStack, CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
CodeGeneratorVariant(OutputFormatHelper &_outputFormatHelper, CodeGenerator::LambdaInInitCapture lambdaInitCapture)
CodeGenerator * operator->()
CodeGeneratorVariant(OutputFormatHelper &_outputFormatHelper)
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
bool InsertVarDecl(const VarDecl *vd) override
CoroutinesCodeGenerator(OutputFormatHelper &_outputFormatHelper, const size_t posBeforeFunc)
std::string GetFrameName() const
CoroutinesCodeGenerator(OutputFormatHelper &_outputFormatHelper, const size_t posBeforeFunc, std::string_view fsmName, size_t suspendsCount, CoroutineASTData data)
bool SkipSpaceAfterVarDecl() override
virtual void InsertArg(const Decl *stmt)
bool EndScope(OutputFormatHelper &ofm, bool clear)
void Add(const VarDecl *decl)
bool Return(OutputFormatHelper &ofm)
void AddExtended(const VarDecl *decl, const ValueDecl *extending)
void StartScope(bool funcStart)
bool InsertSemi() override
OnceFalse mInsertComma
Insert the VarDecl only once.
MultiStmtDeclCodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaStackType &lambdaStack, bool insertVarDecl)
bool InsertVarDecl(const VarDecl *) override
bool InsertComma() override
~MultiStmtDeclCodeGenerator()
void PushVtableEntry(const CXXRecordDecl *record, const CXXRecordDecl *recordB, VarDecl *decl)
int GetGlobalVtablePos(const CXXRecordDecl *record, const CXXRecordDecl *recordB)
static FieldDecl * AddField(CoroutineASTData &astData, std::string_view name, QualType type)
Base class for StackList.
QualType vtableRecordType
CXXRecordDecl * vtableRecorDecl
FieldDecl * mInitialAwaitResumeCalledField
std::vector< const CXXThisExpr * > mThisExprs
FieldDecl * mPromiseField
FieldDecl * mResumeFnField
FieldDecl * mSuspendIndexField
MemberExpr * mSuspendIndexAccess
DeclRefExpr * mFrameAccessDeclRef
CXXRecordDecl * mFrameType
FieldDecl * mDestroyFnField
MemberExpr * mInitialAwaitResumeCalledAccess