CodeGenerator.h
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * C++ Insights, copyright (C) by Andreas Fertig
4 * Distributed under an MIT license. See LICENSE for details
5 *
6 ****************************************************************************/
7
8#ifndef INSIGHTS_CODE_GENERATOR_H
9#define INSIGHTS_CODE_GENERATOR_H
10
11#include "clang/AST/ASTContext.h"
12#include "clang/Rewrite/Core/Rewriter.h"
13#include "llvm/ADT/APInt.h"
14
15#include <optional>
16
17#include "ClangCompat.h"
19#include "InsightsStrongTypes.h"
20#include "InsightsUtility.h"
21#include "OutputFormatHelper.h"
22#include "StackList.h"
23//-----------------------------------------------------------------------------
24
25namespace clang::insights {
26
27void PushVtableEntry(const CXXRecordDecl*, const CXXRecordDecl*, VarDecl* decl);
28int GetGlobalVtablePos(const CXXRecordDecl*, const CXXRecordDecl*);
29
31{
32 std::string mComment{};
33
34public:
35 CppInsightsCommentStmt(std::string_view comment)
36 : Stmt{NoStmtClass}
37 , mComment{comment}
38 {
39 }
40
41 std::string_view Comment() const { return mComment; }
42
43 static bool classof(const Stmt* T) { return T->getStmtClass() == NoStmtClass; }
44
45 child_range children()
46 {
47 static child_iterator iter{};
48 return {iter, iter};
49 }
50 const_child_range children() const
51 {
52 static const_child_iterator iter{};
53 return {iter, iter};
54 }
55};
56
58{
59 STRONG_BOOL(FuncStart);
60
61 const VarDecl* item{};
62 FuncStart funcStart{FuncStart::No};
63 int scope{};
64};
65
67{
68 inline static int scopeCounter{};
69
70 SmallVector<LifetimeEntry, 10> objects{};
71
72 void InsertDtorCall(const VarDecl* decl, OutputFormatHelper& ofm);
73
74public:
75 void Add(const VarDecl* decl);
76 void AddExtended(const VarDecl* decl, const ValueDecl* extending);
77
78 LifetimeEntry& top() { return objects.back(); }
79
80 void removeTop();
81 void StartScope(bool funcStart);
82 bool Return(OutputFormatHelper& ofm);
83 bool EndScope(OutputFormatHelper& ofm, bool clear);
84};
85
86/// \brief More or less the heart of C++ Insights.
87///
88/// This is the place where nearly all of the transformations happen. This class knows the needed types and how to
89/// generated code from them.
91{
92protected:
94 const Stmt* mLastStmt{};
95 const Expr* mLastExpr{}; // special case for assignments to class member
96
97public:
98 const Decl* mLastDecl{};
99
100protected:
103
105
119
120 class LambdaHelper : public StackListEntry<LambdaHelper>
121 {
122 public:
123 LambdaHelper(const LambdaCallerType lambdaCallerType, OutputFormatHelper& outputFormatHelper)
124 : mLambdaCallerType{lambdaCallerType}
125 , mCurrentDeclPos{outputFormatHelper.CurrentPos()}
126 , mOutputFormatHelper{outputFormatHelper}
127 {
128 mLambdaOutputFormatHelper.SetIndent(mOutputFormatHelper);
129 }
130
131 void finish()
132 {
133 if(not mLambdaOutputFormatHelper.empty()) {
134 mOutputFormatHelper.InsertAt(mCurrentDeclPos, mLambdaOutputFormatHelper);
135 }
136 }
137
138 OutputFormatHelper& buffer() { return mLambdaOutputFormatHelper; }
139 LambdaCallerType callerType() const { return mLambdaCallerType; }
140 void setCallerType(LambdaCallerType lambdaCallerType) { mLambdaCallerType = lambdaCallerType; }
141 bool insertName() const
142 { // do we require the name or only the datatype?
143 return (mLambdaCallerType != LambdaCallerType::Decltype) and
144 (mLambdaCallerType != LambdaCallerType::LambdaExpr);
145 }
146
147 private:
148 LambdaCallerType mLambdaCallerType{};
149 const size_t mCurrentDeclPos{};
150 OutputFormatHelper& mOutputFormatHelper;
151 OutputFormatHelper mLambdaOutputFormatHelper{};
152 };
153 //-----------------------------------------------------------------------------
154
156
158 ProcessingPrimaryTemplate); ///! We do not want to transform a primary template which contains a Coroutine.
159
160public:
161 explicit constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper)
162 : CodeGenerator{_outputFormatHelper, mLambdaStackThis, ProcessingPrimaryTemplate::No}
163 {
164 }
165
166 constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper,
167 LambdaStackType& lambdaStack,
168 ProcessingPrimaryTemplate processingPrimaryTemplate)
169 : mOutputFormatHelper{_outputFormatHelper}
170 , mLambdaStack{lambdaStack}
171 , mProcessingPrimaryTemplate{processingPrimaryTemplate}
172 {
173 }
174
175 virtual ~CodeGenerator() = default;
176
177#define IGNORED_DECL(type) \
178 virtual void InsertArg(const type*) {}
179#define IGNORED_STMT(type) \
180 virtual void InsertArg(const type*) {}
181#define SUPPORTED_DECL(type) virtual void InsertArg(const type* stmt);
182#define SUPPORTED_STMT(type) virtual void InsertArg(const type* stmt);
183
184#include "CodeGeneratorTypes.h"
185
186 virtual void InsertArg(const Decl* stmt);
187 virtual void InsertArg(const Stmt* stmt);
188
189 template<typename T>
190 void InsertTemplateArgs(const T& t)
191 {
192 if constexpr(std::is_same_v<T, FunctionDecl>) {
193 if(const auto* tmplArgs = t.getTemplateSpecializationArgs()) {
194 InsertTemplateArgs(*tmplArgs);
195 }
196 } else if constexpr(std::is_same_v<T, VarTemplateSpecializationDecl>) {
197 InsertTemplateArgs(t.getTemplateArgs());
198
199 } else if constexpr(requires { t.template_arguments(); }) {
200 if constexpr(std::is_same_v<DeclRefExpr, T>) {
201 if(0 == t.getNumTemplateArgs()) {
202 return;
203 }
204 }
205
206 InsertTemplateArgs(t.template_arguments());
207
208 } else if constexpr(requires { t.asArray(); }) {
209 InsertTemplateArgs(t.asArray());
210 }
211 }
212
213 void InsertTemplateArgs(const ClassTemplateSpecializationDecl& clsTemplateSpe);
214
215 /// \brief Insert the code for a FunctionDecl.
216 ///
217 /// This inserts the code of a FunctionDecl (and everything which is derived from one). It takes care of
218 /// CXXMethodDecl's access modifier as well as things like constexpr, noexcept, static and more.
219 ///
220 /// @param decl The FunctionDecl to process.
221 /// @param skipAccess Show or hide access modifiers (public, private, protected). The default is to show them.
222 /// @param cxxInheritedCtorDecl If not null, the type and name of this decl is used for the parameters.
223 void InsertFunctionNameWithReturnType(const FunctionDecl& decl,
224 const CXXConstructorDecl* cxxInheritedCtorDecl = nullptr);
225
226 template<typename T>
227 void InsertTemplateArgs(const ArrayRef<T>& array)
228 {
230
231 ForEachArg(array, [&](const auto& arg) { InsertTemplateArg(arg); });
232
233 /* put as space between to closing brackets: >> -> > > */
234 if(mOutputFormatHelper.GetString().back() == '>') {
236 }
237
239 }
240
241 void InsertAttributes(const Decl*);
242 void InsertAttributes(const Decl::attr_range&);
243 void InsertAttribute(const Attr&);
244
245 void InsertTemplateArg(const TemplateArgument& arg);
246
247 STRONG_BOOL(TemplateParamsOnly); ///! Skip template, type constraints and class/typename.
248 void InsertTemplateParameters(const TemplateParameterList& list,
249 const TemplateParamsOnly templateParamsOnly = TemplateParamsOnly::No);
250
251 void StartLifetimeScope();
252 void LifetimeAddExtended(const VarDecl*, const ValueDecl*);
253 void EndLifetimeScope();
254
255protected:
256 virtual bool InsertVarDecl(const VarDecl*) { return true; }
257 virtual bool SkipSpaceAfterVarDecl() { return false; }
258 virtual bool InsertComma() { return false; }
259 virtual bool InsertSemi() { return true; }
260 virtual bool InsertNamespace() const { return false; }
261
262 /// \brief Show casts to xvalues independent from the show all casts option.
263 ///
264 /// This helps showing xvalue casts in structured bindings.
265 virtual bool ShowXValueCasts() const { return false; }
266
267 void HandleTemplateParameterPack(const ArrayRef<TemplateArgument>& args);
268 void HandleCompoundStmt(const CompoundStmt* stmt);
269 /// \brief Show what is behind a local static variable.
270 ///
271 /// [stmt.dcl] p4: Initialization of a block-scope variable with static storage duration is thread-safe since C++11.
272 /// Regardless of that, as long as it is a non-trivally construct and destructable class the compiler adds code to
273 /// track the initialization state. Reference:
274 /// - www.opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx
276
277 virtual void FormatCast(const std::string_view castName,
278 const QualType& CastDestType,
279 const Expr* SubExpr,
280 const CastKind& castKind);
281
282 void ForEachArg(const auto& arguments, auto&& lambda) { mOutputFormatHelper.ForEachArg(arguments, lambda); }
283
284 void InsertArgWithParensIfNeeded(const Stmt* stmt);
285 void InsertSuffix(const QualType& type);
286
287 void InsertTemplateArg(const TemplateArgumentLoc& arg) { InsertTemplateArg(arg.getArgument()); }
288 bool InsertLambdaStaticInvoker(const CXXMethodDecl* cxxMethodDecl);
289
290 STRONG_BOOL(InsertInline);
291
292 void InsertConceptConstraint(const llvm::SmallVectorImpl<const Expr*>& constraints,
293 const InsertInline insertInline);
294 void InsertConceptConstraint(const FunctionDecl* tmplDecl);
295 void InsertConceptConstraint(const VarDecl* varDecl);
296 void InsertConceptConstraint(const TemplateParameterList& tmplDecl);
297
298 void InsertTemplate(const FunctionTemplateDecl*, bool withSpec);
299
300 void InsertQualifierAndNameWithTemplateArgs(const DeclarationName& declName, const auto* stmt)
301 {
302 InsertQualifierAndName(declName, stmt->getQualifier(), stmt->hasTemplateKeyword());
303
304 if(stmt->getNumTemplateArgs()) {
305 InsertTemplateArgs(*stmt);
306 } else if(stmt->hasExplicitTemplateArgs()) {
307 // we have empty templates arguments, but angle brackets provided by the user
309 }
310 }
311
312 void InsertQualifierAndName(const DeclarationName& declName,
313 const NestedNameSpecifier* qualifier,
314 const bool hasTemplateKeyword);
315
316 /// For a special case, when a LambdaExpr occurs in a Constructor from an
317 /// in class initializer, there is a need for a more narrow scope for the \c LAMBDA_SCOPE_HELPER.
318 void InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputFormatHelper& initOutputFormatHelper);
319
320 void InsertTemplateGuardBegin(const FunctionDecl* stmt);
321 void InsertTemplateGuardEnd(const FunctionDecl* stmt);
322
323 /// \brief Insert \c template<> to introduce a template specialization.
324 void InsertTemplateSpecializationHeader(const Decl&);
325
326 void InsertTemplateArgsObjectParam(const ArrayRef<TemplateArgument>& array);
327 void InsertTemplateArgsObjectParam(const TemplateParamObjectDecl& param);
328
329 void InsertNamespace(const NestedNameSpecifier* namespaceSpecifier);
330 void ParseDeclContext(const DeclContext* Ctx);
331
332 STRONG_BOOL(SkipBody);
333 virtual void InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBody skipBody);
334 void InsertMethodBody(const FunctionDecl* stmt, const size_t posBeforeFunc);
335
336 /// \brief Generalized function to insert either a \c CXXConstructExpr or \c CXXUnresolvedConstructExpr
337 template<typename T>
338 void InsertConstructorExpr(const T* stmt);
339
340 /// \brief Check whether or not this statement will add curlys or parentheses and add them only if required.
341 void InsertCurlysIfRequired(const Stmt* stmt);
342
344
345 void InsertInstantiationPoint(const SourceManager& sm, const SourceLocation& instLoc, std::string_view text = {});
346
347 STRONG_BOOL(AddNewLineAfter);
348
349 void WrapInCompoundIfNeeded(const Stmt* stmt, const AddNewLineAfter addNewLineAfter);
350
351 STRONG_BOOL(AddSpaceAtTheEnd);
352
353 enum class BraceKind
354 {
355 Parens,
356 Curlys
357 };
358
359 void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
360
361 void WrapInParensIfNeeded(bool needsParens,
362 void_func_ref lambda,
363 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
364
365 void WrapInCurliesIfNeeded(bool needsParens,
366 void_func_ref lambda,
367 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
368
369 void WrapInCurlys(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
370
371 void WrapInParensOrCurlys(const BraceKind curlys,
372 void_func_ref lambda,
373 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
374
375 void UpdateCurrentPos(std::optional<size_t>& pos) { pos = mOutputFormatHelper.CurrentPos(); }
376
377 static std::string_view GetBuiltinTypeSuffix(const BuiltinType::Kind& kind);
378
380 {
381 public:
383 OutputFormatHelper& outputFormatHelper,
384 const LambdaCallerType lambdaCallerType);
385
387
388 private:
389 LambdaStackType& mStack;
390 LambdaHelper mHelper;
391
392 OutputFormatHelper& GetBuffer(OutputFormatHelper& outputFormatHelper) const;
393 };
394
395 static std::string FillConstantArray(const ConstantArrayType* ct, const std::string& value, const uint64_t startAt);
396 static std::string GetValueOfValueInit(const QualType& t);
397
398 bool InsideDecltype() const;
399
402
403 STRONG_BOOL(SkipVarDecl);
404 STRONG_BOOL(UseCommaInsteadOfSemi);
405 STRONG_BOOL(NoEmptyInitList);
406 STRONG_BOOL(ShowConstantExprValue);
407
408 ShowConstantExprValue mShowConstantExprValue{ShowConstantExprValue::No};
409 SkipVarDecl mSkipVarDecl{SkipVarDecl::No};
410 UseCommaInsteadOfSemi mUseCommaInsteadOfSemi{UseCommaInsteadOfSemi::No};
411 NoEmptyInitList mNoEmptyInitList{
412 NoEmptyInitList::No}; //!< At least in case if a requires-clause containing T{} we don't want to get T{{}}.
414 static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS{
415 uint64_t{100}}; //!< This is the upper limit of elements which will be shown for an array when filled by \c
416 //!< FillConstantArray.
417 std::optional<size_t> mCurrentVarDeclPos{}; //!< The position in mOutputFormatHelper where a potential
418 //!< std::initializer_list expansion must be inserted.
419 std::optional<size_t> mCurrentCallExprPos{}; //!< The position in mOutputFormatHelper where a potential
420 //!< std::initializer_list expansion must be inserted.
421 std::optional<size_t> mCurrentReturnPos{}; //!< The position in mOutputFormatHelper from a return where a
422 //!< potential std::initializer_list expansion must be inserted.
423 std::optional<size_t> mCurrentFieldPos{}; //!< The position in mOutputFormatHelper in a class where where a
424 //!< potential std::initializer_list expansion must be inserted.
426 nullptr}; //!< Helper output buffer for std::initializer_list expansion.
427 bool mRequiresImplicitReturnZero{}; //!< Track whether this is a function with an imlpicit return 0.
428 bool mSkipSemi{};
429 ProcessingPrimaryTemplate mProcessingPrimaryTemplate{};
430 static inline std::map<std::string, bool> mSeenDecls{};
431};
432//-----------------------------------------------------------------------------
433
434/*
435 * \brief Special case to generate the inits of e.g. a \c ForStmt.
436 *
437 * This class is a specialization to handle cases where we can have multiple init statements to the same variable and
438 * hence need only one time the \c VarDecl. An example a for-loops:
439\code
440for(int x=2, y=3, z=4; i < x; ++i) {}
441\endcode
442 */
444{
445public:
446 explicit MultiStmtDeclCodeGenerator(OutputFormatHelper& _outputFormatHelper,
447 LambdaStackType& lambdaStack,
448 bool insertVarDecl)
449 : CodeGenerator{_outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
450 , mInsertVarDecl{insertVarDecl}
451 , mInsertComma{}
452 {
453 }
454
455 // Insert the semi after the last declaration. This implies that this class always requires its own scope.
457
459
460protected:
461 OnceTrue mInsertVarDecl{}; //! Insert the \c VarDecl only once.
462 OnceFalse mInsertComma{}; //! Insert the comma after we have generated the first \c VarDecl and we are about to
463 //! insert another one.
464
465 bool InsertVarDecl(const VarDecl*) override { return mInsertVarDecl; }
466 bool InsertComma() override { return mInsertComma; }
467 bool InsertSemi() override { return false; }
468};
469//-----------------------------------------------------------------------------
470
472{
473 CXXRecordDecl* mFrameType{};
474 FieldDecl* mResumeFnField{};
475 FieldDecl* mDestroyFnField{};
476 FieldDecl* mPromiseField{};
477 FieldDecl* mSuspendIndexField{};
480 DeclRefExpr* mFrameAccessDeclRef{};
481 MemberExpr* mSuspendIndexAccess{};
483 std::vector<const CXXThisExpr*> mThisExprs{};
484};
485
486///
487/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
488/// command line option.
490{
491public:
492 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper, const size_t posBeforeFunc)
493 : CoroutinesCodeGenerator{_outputFormatHelper, posBeforeFunc, {}, {}, {}}
494 {
495 }
496
497 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper,
498 const size_t posBeforeFunc,
499 std::string_view fsmName,
500 size_t suspendsCount,
501 CoroutineASTData data)
502 : CodeGenerator{_outputFormatHelper}
503 , mPosBeforeFunc{posBeforeFunc}
504 , mSuspendsCount{suspendsCount}
505 , mFSMName{fsmName}
506 , mASTData{data}
507 {
508 }
509
510 ~CoroutinesCodeGenerator() override;
511
513
514 void InsertArg(const ImplicitCastExpr* stmt) override;
515 void InsertArg(const CallExpr* stmt) override;
516 void InsertArg(const CXXRecordDecl* stmt) override;
517 void InsertArg(const OpaqueValueExpr* stmt) override;
518
519 void InsertArg(const CoroutineBodyStmt* stmt) override;
520 void InsertArg(const CoroutineSuspendExpr* stmt) override;
521 void InsertArg(const CoreturnStmt* stmt) override;
522
523 void InsertCoroutine(const FunctionDecl& fd, const CoroutineBodyStmt* body);
524
525 std::string GetFrameName() const { return mFrameName; }
526
527protected:
528 bool InsertVarDecl(const VarDecl* vd) override { return mInsertVarDecl or (vd and vd->isStaticLocal()); }
529 bool SkipSpaceAfterVarDecl() override { return not mInsertVarDecl; }
530
531private:
532 enum class eState
533 {
534 Invalid,
535 InitialSuspend,
536 Body,
537 FinalSuspend,
538 };
539
540 eState mState{};
541 const size_t mPosBeforeFunc;
542 size_t mPosBeforeSuspendExpr{};
543 size_t mSuspendsCount{};
544 size_t mSuspendsCounter{};
545 bool mInsertVarDecl{true};
546 bool mSupressCasts{};
547 bool mSupressRecordDecls{};
548 std::string mFrameName{};
549 std::string mFSMName{};
550 CoroutineASTData mASTData{};
551 llvm::DenseMap<const Stmt*, bool> mBinaryExprs{};
552 static inline llvm::DenseMap<const Expr*, std::pair<const DeclRefExpr*, std::string>>
553 mOpaqueValues{}; ///! Keeps track of the current set of opaque value
554
555 QualType GetFrameType() const { return QualType(mASTData.mFrameType->getTypeForDecl(), 0); }
556 QualType GetFramePointerType() const;
557
558 std::string BuildResumeLabelName(int) const;
559 FieldDecl* AddField(std::string_view name, QualType type);
560
561 void InsertArgWithNull(const Stmt* stmt);
562};
563//-----------------------------------------------------------------------------
564
565///
566/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
567/// command line option.
569{
570 ///! A mapping for the pair method decl - derived-to-base-class to index in the vtable.
571 static inline llvm::DenseMap<std::pair<const Decl*, std::pair<const CXXRecordDecl*, const CXXRecordDecl*>>, int>
572 mVirtualFunctions{};
573 bool mInsertSemi{true}; // We need to for int* p = new{5};
574
575public:
576 using CodeGenerator::CodeGenerator;
577
578 using CodeGenerator::InsertArg;
579
580 void InsertArg(const CXXThisExpr*) override;
581 void InsertArg(const CXXDeleteExpr*) override;
582 void InsertArg(const CXXNewExpr*) override;
583 void InsertArg(const CXXOperatorCallExpr*) override;
584 void InsertArg(const CXXNullPtrLiteralExpr*) override;
585 void InsertArg(const StaticAssertDecl*) override;
586 void InsertArg(const CXXRecordDecl*) override;
587 void InsertArg(const CXXMemberCallExpr*) override;
588 void InsertArg(const CXXConstructExpr*) override;
589 void InsertArg(const FunctionDecl* stmt) override;
590 void InsertArg(const TypedefDecl* stmt) override;
591
592 void InsertCXXMethodDecl(const CXXMethodDecl*, CodeGenerator::SkipBody) override;
593
594 void FormatCast(const std::string_view, const QualType&, const Expr*, const CastKind&) override;
595
597 {
599
600 // struct __mptr *__ptbl_vec__c___src_C_[]
601 VarDecl* VtblArrayVar(int size);
602 FieldDecl* VtblPtrField(const CXXRecordDecl* parent);
603
604 QualType vptpTypedef; // typedef int (*__vptp)();
605
606 /*
607struct __mptr
608{
609 short d;
610 short i;
611 __vptp f;
612};
613*/
614 CXXRecordDecl* vtableRecorDecl;
616 FieldDecl* d;
617 FieldDecl* f;
618 };
619
620 static CfrontVtableData& VtableData();
621
622protected:
623 bool InsertSemi() override { return std::exchange(mInsertSemi, true); }
624};
625//-----------------------------------------------------------------------------
626
627///
628/// \brief A special container which creates either a \c CodeGenerator or a \c CfrontCodeGenerator depending on the
629/// command line options.
631{
632 union CodeGenerators
633 {
634 CodeGenerator cg;
636
637 CodeGenerators(OutputFormatHelper& _outputFormatHelper,
639 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate);
640 CodeGenerators(OutputFormatHelper& _outputFormatHelper);
641
642 ~CodeGenerators();
643 } cgs;
644
645 CodeGenerator* cg;
647
648 void Set();
649
650public:
653 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
654 : cgs{_outputFormatHelper, lambdaStack, processingPrimaryTemplate}
655 , ofm{_outputFormatHelper}
656 , cg{}
657 {
658 Set();
659 }
660
662 : cgs{_outputFormatHelper}
663 , ofm{_outputFormatHelper}
664 , cg{}
665 {
666 Set();
667 }
668
669 CodeGenerator* operator->() { return cg; }
670};
671//-----------------------------------------------------------------------------
672
673} // namespace clang::insights
674
675#endif /* INSIGHTS_CODE_GENERATOR_H */
llvm::function_ref< void()> void_func_ref
A special generator for coroutines. It is only activated, if -show-coroutines-transformation is given...
LambdaHelper(const LambdaCallerType lambdaCallerType, OutputFormatHelper &outputFormatHelper)
void setCallerType(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 HandleCompoundStmt(const CompoundStmt *stmt)
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)
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)
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)
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(UseCommaInsteadOfSemi)
void UpdateCurrentPos(std::optional< size_t > &pos)
bool InsertLambdaStaticInvoker(const CXXMethodDecl *cxxMethodDecl)
virtual ~CodeGenerator()=default
void InsertTemplateGuardBegin(const FunctionDecl *stmt)
void InsertConceptConstraint(const llvm::SmallVectorImpl< const Expr * > &constraints, const InsertInline insertInline)
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 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)
constexpr CodeGenerator(OutputFormatHelper &_outputFormatHelper)
! We do not want to transform a primary template which contains a Coroutine.
void InsertCXXMethodHeader(const CXXMethodDecl *stmt, OutputFormatHelper &initOutputFormatHelper)
void InsertTemplateArgs(const ArrayRef< T > &array)
STRONG_BOOL(AddSpaceAtTheEnd)
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)
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)
CoroutinesCodeGenerator(OutputFormatHelper &_outputFormatHelper, const size_t posBeforeFunc, std::string_view fsmName, size_t suspendsCount, CoroutineASTData data)
const_child_range children() const
CppInsightsCommentStmt(std::string_view comment)
static bool classof(const Stmt *T)
bool EndScope(OutputFormatHelper &ofm, bool clear)
void Add(const VarDecl *decl)
bool Return(OutputFormatHelper &ofm)
void AddExtended(const VarDecl *decl, const ValueDecl *extending)
OnceFalse mInsertComma
Insert the VarDecl only once.
MultiStmtDeclCodeGenerator(OutputFormatHelper &_outputFormatHelper, LambdaStackType &lambdaStack, bool insertVarDecl)
bool InsertVarDecl(const VarDecl *) override
void ForEachArg(const auto &arguments, auto &&lambda)
Append a argument list to the buffer.
void Append(const char c)
Append a single character.
std::string & GetString()
Returns a reference to the underlying string buffer.
bool empty() const
Check whether the buffer is empty.
void SetIndent(const unsigned indent, const SkipIndenting skipIndenting=SkipIndenting::No)
Set the indent level of this class to indent.
size_t CurrentPos() const
Returns the current position in the output buffer.
void InsertAt(const size_t atPos, std::string_view data)
Insert a string before the position atPos.
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.
Definition StackList.h:8
std::vector< const CXXThisExpr * > mThisExprs
STRONG_BOOL(FuncStart)
FuncStart funcStart
int scope
const VarDecl * item