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
314#if not IS_CLANG_NEWER_THAN(22)
315 *
316#endif
317 qualifier,
318 const bool hasTemplateKeyword);
319
320 /// For a special case, when a LambdaExpr occurs in a Constructor from an
321 /// in class initializer, there is a need for a more narrow scope for the \c LAMBDA_SCOPE_HELPER.
322 void InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputFormatHelper& initOutputFormatHelper);
323
324 void InsertTemplateGuardBegin(const FunctionDecl* stmt);
325 void InsertTemplateGuardEnd(const FunctionDecl* stmt);
326
327 /// \brief Insert \c template<> to introduce a template specialization.
328 void InsertTemplateSpecializationHeader(const Decl&);
329
330 void InsertTemplateArgsObjectParam(const ArrayRef<TemplateArgument>& array);
331 void InsertTemplateArgsObjectParam(const TemplateParamObjectDecl& param);
332
333 void InsertNamespace(const NestedNameSpecifier
334#if not IS_CLANG_NEWER_THAN(22)
335 *
336#endif
337 namespaceSpecifier);
338 void ParseDeclContext(const DeclContext* Ctx);
339
340 STRONG_BOOL(SkipBody);
341 virtual void InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBody skipBody);
342 void InsertMethodBody(const FunctionDecl* stmt, const size_t posBeforeFunc);
343
344 /// \brief Generalized function to insert either a \c CXXConstructExpr or \c CXXUnresolvedConstructExpr
345 template<typename T>
346 void InsertConstructorExpr(const T* stmt);
347
348 /// \brief Check whether or not this statement will add curlys or parentheses and add them only if required.
349 void InsertCurlysIfRequired(const Stmt* stmt);
350
352
353 void InsertInstantiationPoint(const SourceManager& sm, const SourceLocation& instLoc, std::string_view text = {});
354
355 STRONG_BOOL(AddNewLineAfter);
356
357 void WrapInCompoundIfNeeded(const Stmt* stmt, const AddNewLineAfter addNewLineAfter);
358
359 STRONG_BOOL(AddSpaceAtTheEnd);
360
361 enum class BraceKind
362 {
363 Parens,
364 Curlys
365 };
366
367 void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
368
369 void WrapInParensIfNeeded(bool needsParens,
370 void_func_ref lambda,
371 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
372
373 void WrapInCurliesIfNeeded(bool needsParens,
374 void_func_ref lambda,
375 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
376
377 void WrapInCurlys(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
378
379 void WrapInParensOrCurlys(const BraceKind curlys,
380 void_func_ref lambda,
381 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
382
383 void UpdateCurrentPos(std::optional<size_t>& pos) { pos = mOutputFormatHelper.CurrentPos(); }
384
385 static std::string_view GetBuiltinTypeSuffix(const BuiltinType::Kind& kind);
386
388 {
389 public:
391 OutputFormatHelper& outputFormatHelper,
392 const LambdaCallerType lambdaCallerType);
393
395
396 private:
397 LambdaStackType& mStack;
398 LambdaHelper mHelper;
399
400 OutputFormatHelper& GetBuffer(OutputFormatHelper& outputFormatHelper) const;
401 };
402
403 static std::string FillConstantArray(const ConstantArrayType* ct, const std::string& value, const uint64_t startAt);
404 static std::string GetValueOfValueInit(const QualType& t);
405
406 bool InsideDecltype() const;
407
410
411 STRONG_BOOL(SkipVarDecl);
412 STRONG_BOOL(UseCommaInsteadOfSemi);
413 STRONG_BOOL(NoEmptyInitList);
414 STRONG_BOOL(ShowConstantExprValue);
415
416 ShowConstantExprValue mShowConstantExprValue{ShowConstantExprValue::No};
417 SkipVarDecl mSkipVarDecl{SkipVarDecl::No};
418 UseCommaInsteadOfSemi mUseCommaInsteadOfSemi{UseCommaInsteadOfSemi::No};
419 NoEmptyInitList mNoEmptyInitList{
420 NoEmptyInitList::No}; //!< At least in case if a requires-clause containing T{} we don't want to get T{{}}.
422 static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS{
423 uint64_t{100}}; //!< This is the upper limit of elements which will be shown for an array when filled by \c
424 //!< FillConstantArray.
425 std::optional<size_t> mCurrentVarDeclPos{}; //!< The position in mOutputFormatHelper where a potential
426 //!< std::initializer_list expansion must be inserted.
427 std::optional<size_t> mCurrentCallExprPos{}; //!< The position in mOutputFormatHelper where a potential
428 //!< std::initializer_list expansion must be inserted.
429 std::optional<size_t> mCurrentReturnPos{}; //!< The position in mOutputFormatHelper from a return where a
430 //!< potential std::initializer_list expansion must be inserted.
431 std::optional<size_t> mCurrentFieldPos{}; //!< The position in mOutputFormatHelper in a class where where a
432 //!< potential std::initializer_list expansion must be inserted.
434 nullptr}; //!< Helper output buffer for std::initializer_list expansion.
435 bool mRequiresImplicitReturnZero{}; //!< Track whether this is a function with an imlpicit return 0.
436 bool mSkipSemi{};
437 ProcessingPrimaryTemplate mProcessingPrimaryTemplate{};
438 static inline std::map<std::string, bool> mSeenDecls{};
439};
440//-----------------------------------------------------------------------------
441
442/*
443 * \brief Special case to generate the inits of e.g. a \c ForStmt.
444 *
445 * This class is a specialization to handle cases where we can have multiple init statements to the same variable and
446 * hence need only one time the \c VarDecl. An example a for-loops:
447\code
448for(int x=2, y=3, z=4; i < x; ++i) {}
449\endcode
450 */
452{
453public:
454 explicit MultiStmtDeclCodeGenerator(OutputFormatHelper& _outputFormatHelper,
455 LambdaStackType& lambdaStack,
456 bool insertVarDecl)
457 : CodeGenerator{_outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
458 , mInsertVarDecl{insertVarDecl}
459 , mInsertComma{}
460 {
461 }
462
463 // Insert the semi after the last declaration. This implies that this class always requires its own scope.
465
467
468protected:
469 OnceTrue mInsertVarDecl{}; //! Insert the \c VarDecl only once.
470 OnceFalse mInsertComma{}; //! Insert the comma after we have generated the first \c VarDecl and we are about to
471 //! insert another one.
472
473 bool InsertVarDecl(const VarDecl*) override { return mInsertVarDecl; }
474 bool InsertComma() override { return mInsertComma; }
475 bool InsertSemi() override { return false; }
476};
477//-----------------------------------------------------------------------------
478
480{
481 CXXRecordDecl* mFrameType{};
482 FieldDecl* mResumeFnField{};
483 FieldDecl* mDestroyFnField{};
484 FieldDecl* mPromiseField{};
485 FieldDecl* mSuspendIndexField{};
488 DeclRefExpr* mFrameAccessDeclRef{};
489 MemberExpr* mSuspendIndexAccess{};
491 std::vector<const CXXThisExpr*> mThisExprs{};
492};
493
494///
495/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
496/// command line option.
498{
499public:
500 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper, const size_t posBeforeFunc)
501 : CoroutinesCodeGenerator{_outputFormatHelper, posBeforeFunc, {}, {}, {}}
502 {
503 }
504
505 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper,
506 const size_t posBeforeFunc,
507 std::string_view fsmName,
508 size_t suspendsCount,
509 CoroutineASTData data)
510 : CodeGenerator{_outputFormatHelper}
511 , mPosBeforeFunc{posBeforeFunc}
512 , mSuspendsCount{suspendsCount}
513 , mFSMName{fsmName}
514 , mASTData{data}
515 {
516 }
517
518 ~CoroutinesCodeGenerator() override;
519
521
522 void InsertArg(const ImplicitCastExpr* stmt) override;
523 void InsertArg(const CallExpr* stmt) override;
524 void InsertArg(const CXXRecordDecl* stmt) override;
525 void InsertArg(const OpaqueValueExpr* stmt) override;
526
527 void InsertArg(const CoroutineBodyStmt* stmt) override;
528 void InsertArg(const CoroutineSuspendExpr* stmt) override;
529 void InsertArg(const CoreturnStmt* stmt) override;
530
531 void InsertCoroutine(const FunctionDecl& fd, const CoroutineBodyStmt* body);
532
533 std::string GetFrameName() const { return mFrameName; }
534
535protected:
536 bool InsertVarDecl(const VarDecl* vd) override { return mInsertVarDecl or (vd and vd->isStaticLocal()); }
537 bool SkipSpaceAfterVarDecl() override { return not mInsertVarDecl; }
538
539private:
540 enum class eState
541 {
542 Invalid,
543 InitialSuspend,
544 Body,
545 FinalSuspend,
546 };
547
548 eState mState{};
549 const size_t mPosBeforeFunc;
550 size_t mPosBeforeSuspendExpr{};
551 size_t mSuspendsCount{};
552 size_t mSuspendsCounter{};
553 bool mInsertVarDecl{true};
554 bool mSupressCasts{};
555 bool mSupressRecordDecls{};
556 std::string mFrameName{};
557 std::string mFSMName{};
558 CoroutineASTData mASTData{};
559 llvm::DenseMap<const Stmt*, bool> mBinaryExprs{};
560 static inline llvm::DenseMap<const Expr*, std::pair<const DeclRefExpr*, std::string>>
561 mOpaqueValues{}; ///! Keeps track of the current set of opaque value
562
563 QualType GetFrameType() const
564 {
565 return
566#if IS_CLANG_NEWER_THAN(22)
567 mASTData.mFrameType->getASTContext().getCanonicalTagType(mASTData.mFrameType);
568#else
569 QualType(mASTData.mFrameType->getTypeForDecl(), 0);
570#endif
571 }
572 QualType GetFramePointerType() const;
573
574 std::string BuildResumeLabelName(int) const;
575 FieldDecl* AddField(std::string_view name, QualType type);
576
577 void InsertArgWithNull(const Stmt* stmt);
578};
579//-----------------------------------------------------------------------------
580
581///
582/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
583/// command line option.
585{
586 ///! A mapping for the pair method decl - derived-to-base-class to index in the vtable.
587 static inline llvm::DenseMap<std::pair<const Decl*, std::pair<const CXXRecordDecl*, const CXXRecordDecl*>>, int>
588 mVirtualFunctions{};
589 bool mInsertSemi{true}; // We need to for int* p = new{5};
590
591public:
592 using CodeGenerator::CodeGenerator;
593
594 using CodeGenerator::InsertArg;
595
596 void InsertArg(const CXXThisExpr*) override;
597 void InsertArg(const CXXDeleteExpr*) override;
598 void InsertArg(const CXXNewExpr*) override;
599 void InsertArg(const CXXOperatorCallExpr*) override;
600 void InsertArg(const CXXNullPtrLiteralExpr*) override;
601 void InsertArg(const StaticAssertDecl*) override;
602 void InsertArg(const CXXRecordDecl*) override;
603 void InsertArg(const CXXMemberCallExpr*) override;
604 void InsertArg(const CXXConstructExpr*) override;
605 void InsertArg(const FunctionDecl* stmt) override;
606 void InsertArg(const TypedefDecl* stmt) override;
607
608 void InsertCXXMethodDecl(const CXXMethodDecl*, CodeGenerator::SkipBody) override;
609
610 void FormatCast(const std::string_view, const QualType&, const Expr*, const CastKind&) override;
611
613 {
615
616 // struct __mptr *__ptbl_vec__c___src_C_[]
617 VarDecl* VtblArrayVar(int size);
618 FieldDecl* VtblPtrField(const CXXRecordDecl* parent);
619
620 QualType vptpTypedef; // typedef int (*__vptp)();
621
622 /*
623struct __mptr
624{
625 short d;
626 short i;
627 __vptp f;
628};
629*/
630 CXXRecordDecl* vtableRecorDecl;
632 FieldDecl* d;
633 FieldDecl* f;
634 };
635
636 static CfrontVtableData& VtableData();
637
638protected:
639 bool InsertSemi() override { return std::exchange(mInsertSemi, true); }
640};
641//-----------------------------------------------------------------------------
642
643///
644/// \brief A special container which creates either a \c CodeGenerator or a \c CfrontCodeGenerator depending on the
645/// command line options.
647{
648 union CodeGenerators
649 {
650 CodeGenerator cg;
652
653 CodeGenerators(OutputFormatHelper& _outputFormatHelper,
655 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate);
656 CodeGenerators(OutputFormatHelper& _outputFormatHelper);
657
658 ~CodeGenerators();
659 } cgs;
660
661 CodeGenerator* cg;
663
664 void Set();
665
666public:
669 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
670 : cgs{_outputFormatHelper, lambdaStack, processingPrimaryTemplate}
671 , ofm{_outputFormatHelper}
672 , cg{}
673 {
674 Set();
675 }
676
678 : cgs{_outputFormatHelper}
679 , ofm{_outputFormatHelper}
680 , cg{}
681 {
682 Set();
683 }
684
685 CodeGenerator* operator->() { return cg; }
686};
687//-----------------------------------------------------------------------------
688
689} // namespace clang::insights
690
691#endif /* INSIGHTS_CODE_GENERATOR_H */
#define IS_CLANG_NEWER_THAN(major)
Definition ClangCompat.h:16
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