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
120
121 class LambdaHelper : public StackListEntry<LambdaHelper>
122 {
123 public:
124 LambdaHelper(const LambdaCallerType lambdaCallerType, OutputFormatHelper& outputFormatHelper)
125 : mLambdaCallerType{lambdaCallerType}
126 , mCurrentVarDeclPos{outputFormatHelper.CurrentPos()}
127 , mOutputFormatHelper{outputFormatHelper}
128 {
129 mLambdaOutputFormatHelper.SetIndent(mOutputFormatHelper);
130 }
131
132 void finish()
133 {
134 if(not mLambdaOutputFormatHelper.empty()) {
135 mOutputFormatHelper.InsertAt(mCurrentVarDeclPos, mLambdaOutputFormatHelper);
136 }
137 }
138
139 OutputFormatHelper& buffer() { return mLambdaOutputFormatHelper; }
140
141 std::string& inits() { return mInits; }
142
143 void insertInits(OutputFormatHelper& outputFormatHelper)
144 {
145 if(not mInits.empty()) {
146 outputFormatHelper.Append(mInits);
147 mInits.clear();
148 }
149 }
150
151 LambdaCallerType callerType() const { return mLambdaCallerType; }
152 bool insertName() const { return (LambdaCallerType::Decltype != mLambdaCallerType) or mForceName; }
153
154 void setInsertName(bool b) { mForceName = b; }
155
156 private:
157 const LambdaCallerType mLambdaCallerType;
158 const size_t mCurrentVarDeclPos;
159 OutputFormatHelper& mOutputFormatHelper;
160 OutputFormatHelper mLambdaOutputFormatHelper{};
161 std::string mInits{};
162 bool mForceName{};
163 };
164 //-----------------------------------------------------------------------------
165
167
168 STRONG_BOOL(LambdaInInitCapture); ///! Signal whether we are processing a lambda created and assigned to an init
169 /// capture of another lambda.
170
172 ProcessingPrimaryTemplate); ///! We do not want to transform a primary template which contains a Coroutine.
173
174 constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper,
175 LambdaStackType& lambdaStack,
176 LambdaInInitCapture lambdaInitCapture,
177 ProcessingPrimaryTemplate processingPrimaryTemplate)
178 : mOutputFormatHelper{_outputFormatHelper}
179 , mLambdaStack{lambdaStack}
180 , mLambdaInitCapture{lambdaInitCapture}
181 , mProcessingPrimaryTemplate{processingPrimaryTemplate}
182 {
183 }
184
185public:
186 explicit constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper)
187 : CodeGenerator{_outputFormatHelper, mLambdaStackThis, ProcessingPrimaryTemplate::No}
188 {
189 }
190
191 constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper, LambdaInInitCapture lambdaInitCapture)
192 : CodeGenerator{_outputFormatHelper, mLambdaStackThis, lambdaInitCapture, ProcessingPrimaryTemplate::No}
193 {
194 }
195
196 constexpr CodeGenerator(OutputFormatHelper& _outputFormatHelper,
197 LambdaStackType& lambdaStack,
198 ProcessingPrimaryTemplate processingPrimaryTemplate)
199 : CodeGenerator{_outputFormatHelper, lambdaStack, LambdaInInitCapture::No, processingPrimaryTemplate}
200 {
201 }
202
203 virtual ~CodeGenerator() = default;
204
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);
211
212#include "CodeGeneratorTypes.h"
213
214 virtual void InsertArg(const Decl* stmt);
215 virtual void InsertArg(const Stmt* stmt);
216
217 template<typename T>
218 void InsertTemplateArgs(const T& t)
219 {
220 if constexpr(std::is_same_v<T, FunctionDecl>) {
221 if(const auto* tmplArgs = t.getTemplateSpecializationArgs()) {
222 InsertTemplateArgs(*tmplArgs);
223 }
224 } else if constexpr(std::is_same_v<T, VarTemplateSpecializationDecl>) {
225 InsertTemplateArgs(t.getTemplateArgs());
226
227 } else if constexpr(requires { t.template_arguments(); }) {
228 if constexpr(std::is_same_v<DeclRefExpr, T>) {
229 if(0 == t.getNumTemplateArgs()) {
230 return;
231 }
232 }
233
234 InsertTemplateArgs(t.template_arguments());
235
236 } else if constexpr(requires { t.asArray(); }) {
237 InsertTemplateArgs(t.asArray());
238 }
239 }
240
241 void InsertTemplateArgs(const ClassTemplateSpecializationDecl& clsTemplateSpe);
242
243 /// \brief Insert the code for a FunctionDecl.
244 ///
245 /// This inserts the code of a FunctionDecl (and everything which is derived from one). It takes care of
246 /// CXXMethodDecl's access modifier as well as things like constexpr, noexcept, static and more.
247 ///
248 /// @param decl The FunctionDecl to process.
249 /// @param skipAccess Show or hide access modifiers (public, private, protected). The default is to show them.
250 /// @param cxxInheritedCtorDecl If not null, the type and name of this decl is used for the parameters.
251 void InsertFunctionNameWithReturnType(const FunctionDecl& decl,
252 const CXXConstructorDecl* cxxInheritedCtorDecl = nullptr);
253
254 template<typename T>
255 void InsertTemplateArgs(const ArrayRef<T>& array)
256 {
258
259 ForEachArg(array, [&](const auto& arg) { InsertTemplateArg(arg); });
260
261 /* put as space between to closing brackets: >> -> > > */
262 if(mOutputFormatHelper.GetString().back() == '>') {
264 }
265
267 }
268
269 void InsertAttributes(const Decl*);
270 void InsertAttributes(const Decl::attr_range&);
271 void InsertAttribute(const Attr&);
272
273 void InsertTemplateArg(const TemplateArgument& arg);
274
275 STRONG_BOOL(TemplateParamsOnly); ///! Skip template, type constraints and class/typename.
276 void InsertTemplateParameters(const TemplateParameterList& list,
277 const TemplateParamsOnly templateParamsOnly = TemplateParamsOnly::No);
278
279 void StartLifetimeScope();
280 void LifetimeAddExtended(const VarDecl*, const ValueDecl*);
281 void EndLifetimeScope();
282
283protected:
284 virtual bool InsertVarDecl(const VarDecl*) { return true; }
285 virtual bool SkipSpaceAfterVarDecl() { return false; }
286 virtual bool InsertComma() { return false; }
287 virtual bool InsertSemi() { return true; }
288 virtual bool InsertNamespace() const { return false; }
289
290 /// \brief Show casts to xvalues independent from the show all casts option.
291 ///
292 /// This helps showing xvalue casts in structured bindings.
293 virtual bool ShowXValueCasts() const { return false; }
294
295 void HandleTemplateParameterPack(const ArrayRef<TemplateArgument>& args);
296 void HandleCompoundStmt(const CompoundStmt* stmt);
297 /// \brief Show what is behind a local static variable.
298 ///
299 /// [stmt.dcl] p4: Initialization of a block-scope variable with static storage duration is thread-safe since C++11.
300 /// Regardless of that, as long as it is a non-trivally construct and destructable class the compiler adds code to
301 /// track the initialization state. Reference:
302 /// - www.opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx
304
305 virtual void FormatCast(const std::string_view castName,
306 const QualType& CastDestType,
307 const Expr* SubExpr,
308 const CastKind& castKind);
309
310 void ForEachArg(const auto& arguments, auto&& lambda) { mOutputFormatHelper.ForEachArg(arguments, lambda); }
311
312 void InsertArgWithParensIfNeeded(const Stmt* stmt);
313 void InsertSuffix(const QualType& type);
314
315 void InsertTemplateArg(const TemplateArgumentLoc& arg) { InsertTemplateArg(arg.getArgument()); }
316 bool InsertLambdaStaticInvoker(const CXXMethodDecl* cxxMethodDecl);
317
318 STRONG_BOOL(InsertInline);
319
320 void InsertConceptConstraint(const llvm::SmallVectorImpl<const Expr*>& constraints,
321 const InsertInline insertInline);
322 void InsertConceptConstraint(const FunctionDecl* tmplDecl);
323 void InsertConceptConstraint(const VarDecl* varDecl);
324 void InsertConceptConstraint(const TemplateParameterList& tmplDecl);
325
326 void InsertTemplate(const FunctionTemplateDecl*, bool withSpec);
327
328 void InsertQualifierAndNameWithTemplateArgs(const DeclarationName& declName, const auto* stmt)
329 {
330 InsertQualifierAndName(declName, stmt->getQualifier(), stmt->hasTemplateKeyword());
331
332 if(stmt->getNumTemplateArgs()) {
333 InsertTemplateArgs(*stmt);
334 } else if(stmt->hasExplicitTemplateArgs()) {
335 // we have empty templates arguments, but angle brackets provided by the user
337 }
338 }
339
340 void InsertQualifierAndName(const DeclarationName& declName,
341 const NestedNameSpecifier* qualifier,
342 const bool hasTemplateKeyword);
343
344 /// For a special case, when a LambdaExpr occurs in a Constructor from an
345 /// in class initializer, there is a need for a more narrow scope for the \c LAMBDA_SCOPE_HELPER.
346 void InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputFormatHelper& initOutputFormatHelper);
347
348 void InsertTemplateGuardBegin(const FunctionDecl* stmt);
349 void InsertTemplateGuardEnd(const FunctionDecl* stmt);
350
351 /// \brief Insert \c template<> to introduce a template specialization.
352 void InsertTemplateSpecializationHeader(const Decl&);
353
354 void InsertTemplateArgsObjectParam(const ArrayRef<TemplateArgument>& array);
355 void InsertTemplateArgsObjectParam(const TemplateParamObjectDecl& param);
356
357 void InsertNamespace(const NestedNameSpecifier* namespaceSpecifier);
358 void ParseDeclContext(const DeclContext* Ctx);
359
360 STRONG_BOOL(SkipBody);
361 virtual void InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBody skipBody);
362 void InsertMethodBody(const FunctionDecl* stmt, const size_t posBeforeFunc);
363
364 /// \brief Generalized function to insert either a \c CXXConstructExpr or \c CXXUnresolvedConstructExpr
365 template<typename T>
366 void InsertConstructorExpr(const T* stmt);
367
368 /// \brief Check whether or not this statement will add curlys or parentheses and add them only if required.
369 void InsertCurlysIfRequired(const Stmt* stmt);
370
372
373 void InsertInstantiationPoint(const SourceManager& sm, const SourceLocation& instLoc, std::string_view text = {});
374
375 STRONG_BOOL(AddNewLineAfter);
376
377 void WrapInCompoundIfNeeded(const Stmt* stmt, const AddNewLineAfter addNewLineAfter);
378
379 STRONG_BOOL(AddSpaceAtTheEnd);
380
381 enum class BraceKind
382 {
383 Parens,
384 Curlys
385 };
386
387 void WrapInParens(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
388
389 void WrapInParensIfNeeded(bool needsParens,
390 void_func_ref lambda,
391 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
392
393 void WrapInCurliesIfNeeded(bool needsParens,
394 void_func_ref lambda,
395 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
396
397 void WrapInCurlys(void_func_ref lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
398
399 void WrapInParensOrCurlys(const BraceKind curlys,
400 void_func_ref lambda,
401 const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);
402
403 void UpdateCurrentPos(std::optional<size_t>& pos) { pos = mOutputFormatHelper.CurrentPos(); }
404
405 static std::string_view GetBuiltinTypeSuffix(const BuiltinType::Kind& kind);
406
408 {
409 public:
411 OutputFormatHelper& outputFormatHelper,
412 const LambdaCallerType lambdaCallerType);
413
415
416 private:
417 LambdaStackType& mStack;
418 LambdaHelper mHelper;
419
420 OutputFormatHelper& GetBuffer(OutputFormatHelper& outputFormatHelper) const;
421 };
422
423 void HandleLambdaExpr(const LambdaExpr* stmt, LambdaHelper& lambdaHelper);
424 static std::string FillConstantArray(const ConstantArrayType* ct, const std::string& value, const uint64_t startAt);
425 static std::string GetValueOfValueInit(const QualType& t);
426
427 bool InsideDecltype() const;
428
431
432 STRONG_BOOL(SkipVarDecl);
433 STRONG_BOOL(UseCommaInsteadOfSemi);
434 STRONG_BOOL(NoEmptyInitList);
435 STRONG_BOOL(ShowConstantExprValue);
436 LambdaInInitCapture mLambdaInitCapture{LambdaInInitCapture::No};
437
438 ShowConstantExprValue mShowConstantExprValue{ShowConstantExprValue::No};
439 SkipVarDecl mSkipVarDecl{SkipVarDecl::No};
440 UseCommaInsteadOfSemi mUseCommaInsteadOfSemi{UseCommaInsteadOfSemi::No};
441 NoEmptyInitList mNoEmptyInitList{
442 NoEmptyInitList::No}; //!< At least in case if a requires-clause containing T{} we don't want to get T{{}}.
444 static constexpr auto MAX_FILL_VALUES_FOR_ARRAYS{
445 uint64_t{100}}; //!< This is the upper limit of elements which will be shown for an array when filled by \c
446 //!< FillConstantArray.
447 std::optional<size_t> mCurrentVarDeclPos{}; //!< The position in mOutputFormatHelper where a potential
448 //!< std::initializer_list expansion must be inserted.
449 std::optional<size_t> mCurrentCallExprPos{}; //!< The position in mOutputFormatHelper where a potential
450 //!< std::initializer_list expansion must be inserted.
451 std::optional<size_t> mCurrentReturnPos{}; //!< The position in mOutputFormatHelper from a return where a
452 //!< potential std::initializer_list expansion must be inserted.
453 std::optional<size_t> mCurrentFieldPos{}; //!< The position in mOutputFormatHelper in a class where where a
454 //!< potential std::initializer_list expansion must be inserted.
456 nullptr}; //!< Helper output buffer for std::initializer_list expansion.
457 bool mRequiresImplicitReturnZero{}; //!< Track whether this is a function with an imlpicit return 0.
458 bool mSkipSemi{};
459 ProcessingPrimaryTemplate mProcessingPrimaryTemplate{};
460 static inline std::map<std::string, bool> mSeenDecls{};
461};
462//-----------------------------------------------------------------------------
463
465{
466public:
468
470 void InsertArg(const CXXThisExpr* stmt) override;
471
473};
474//-----------------------------------------------------------------------------
475
476/*
477 * \brief Special case to generate the inits of e.g. a \c ForStmt.
478 *
479 * This class is a specialization to handle cases where we can have multiple init statements to the same variable and
480 * hence need only one time the \c VarDecl. An example a for-loops:
481\code
482for(int x=2, y=3, z=4; i < x; ++i) {}
483\endcode
484 */
486{
487public:
488 explicit MultiStmtDeclCodeGenerator(OutputFormatHelper& _outputFormatHelper,
489 LambdaStackType& lambdaStack,
490 bool insertVarDecl)
491 : CodeGenerator{_outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
492 , mInsertVarDecl{insertVarDecl}
493 , mInsertComma{}
494 {
495 }
496
497 // Insert the semi after the last declaration. This implies that this class always requires its own scope.
499
501
502protected:
503 OnceTrue mInsertVarDecl{}; //! Insert the \c VarDecl only once.
504 OnceFalse mInsertComma{}; //! Insert the comma after we have generated the first \c VarDecl and we are about to
505 //! insert another one.
506
507 bool InsertVarDecl(const VarDecl*) override { return mInsertVarDecl; }
508 bool InsertComma() override { return mInsertComma; }
509 bool InsertSemi() override { return false; }
510};
511//-----------------------------------------------------------------------------
512
514{
515 CXXRecordDecl* mFrameType{};
516 FieldDecl* mResumeFnField{};
517 FieldDecl* mDestroyFnField{};
518 FieldDecl* mPromiseField{};
519 FieldDecl* mSuspendIndexField{};
522 DeclRefExpr* mFrameAccessDeclRef{};
523 MemberExpr* mSuspendIndexAccess{};
525 std::vector<const CXXThisExpr*> mThisExprs{};
526};
527
528///
529/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
530/// command line option.
532{
533public:
534 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper, const size_t posBeforeFunc)
535 : CoroutinesCodeGenerator{_outputFormatHelper, posBeforeFunc, {}, {}, {}}
536 {
537 }
538
539 explicit CoroutinesCodeGenerator(OutputFormatHelper& _outputFormatHelper,
540 const size_t posBeforeFunc,
541 std::string_view fsmName,
542 size_t suspendsCount,
543 CoroutineASTData data)
544 : CodeGenerator{_outputFormatHelper}
545 , mPosBeforeFunc{posBeforeFunc}
546 , mSuspendsCount{suspendsCount}
547 , mFSMName{fsmName}
548 , mASTData{data}
549 {
550 }
551
552 ~CoroutinesCodeGenerator() override;
553
555
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;
560
561 void InsertArg(const CoroutineBodyStmt* stmt) override;
562 void InsertArg(const CoroutineSuspendExpr* stmt) override;
563 void InsertArg(const CoreturnStmt* stmt) override;
564
565 void InsertCoroutine(const FunctionDecl& fd, const CoroutineBodyStmt* body);
566
567 std::string GetFrameName() const { return mFrameName; }
568
569protected:
570 bool InsertVarDecl(const VarDecl* vd) override { return mInsertVarDecl or (vd and vd->isStaticLocal()); }
571 bool SkipSpaceAfterVarDecl() override { return not mInsertVarDecl; }
572
573private:
574 enum class eState
575 {
576 Invalid,
577 InitialSuspend,
578 Body,
579 FinalSuspend,
580 };
581
582 eState mState{};
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>>
595 mOpaqueValues{}; ///! Keeps track of the current set of opaque value
596
597 QualType GetFrameType() const { return QualType(mASTData.mFrameType->getTypeForDecl(), 0); }
598 QualType GetFramePointerType() const;
599
600 std::string BuildResumeLabelName(int) const;
601 FieldDecl* AddField(std::string_view name, QualType type);
602
603 void InsertArgWithNull(const Stmt* stmt);
604};
605//-----------------------------------------------------------------------------
606
607///
608/// \brief A special generator for coroutines. It is only activated, if \c -show-coroutines-transformation is given as a
609/// command line option.
611{
612 ///! A mapping for the pair method decl - derived-to-base-class to index in the vtable.
613 static inline llvm::DenseMap<std::pair<const Decl*, std::pair<const CXXRecordDecl*, const CXXRecordDecl*>>, int>
614 mVirtualFunctions{};
615 bool mInsertSemi{true}; // We need to for int* p = new{5};
616
617public:
618 using CodeGenerator::CodeGenerator;
619
620 using CodeGenerator::InsertArg;
621
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;
633
634 void InsertCXXMethodDecl(const CXXMethodDecl*, CodeGenerator::SkipBody) override;
635
636 void FormatCast(const std::string_view, const QualType&, const Expr*, const CastKind&) override;
637
639 {
641
642 // struct __mptr *__ptbl_vec__c___src_C_[]
643 VarDecl* VtblArrayVar(int size);
644 FieldDecl* VtblPtrField(const CXXRecordDecl* parent);
645
646 QualType vptpTypedef; // typedef int (*__vptp)();
647
648 /*
649struct __mptr
650{
651 short d;
652 short i;
653 __vptp f;
654};
655*/
656 CXXRecordDecl* vtableRecorDecl;
658 FieldDecl* d;
659 FieldDecl* f;
660 };
661
662 static CfrontVtableData& VtableData();
663
664protected:
665 bool InsertSemi() override { return std::exchange(mInsertSemi, true); }
666};
667//-----------------------------------------------------------------------------
668
669///
670/// \brief A special container which creates either a \c CodeGenerator or a \c CfrontCodeGenerator depending on the
671/// command line options.
673{
674 union CodeGenerators
675 {
676 CodeGenerator cg;
678
679 CodeGenerators(OutputFormatHelper& _outputFormatHelper,
681 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate);
682 CodeGenerators(OutputFormatHelper& _outputFormatHelper, CodeGenerator::LambdaInInitCapture lambdaInitCapture);
683
684 ~CodeGenerators();
685 } cgs;
686
687 CodeGenerator* cg;
689
690 void Set();
691
692public:
694 : CodeGeneratorVariant{_outputFormatHelper, CodeGenerator::LambdaInInitCapture::No}
695 {
696 }
697
700 CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
701 : cgs{_outputFormatHelper, lambdaStack, processingPrimaryTemplate}
702 , ofm{_outputFormatHelper}
703 , cg{}
704 {
705 Set();
706 }
707
708 CodeGeneratorVariant(OutputFormatHelper& _outputFormatHelper, CodeGenerator::LambdaInInitCapture lambdaInitCapture)
709 : cgs{_outputFormatHelper, lambdaInitCapture}
710 , ofm{_outputFormatHelper}
711 , cg{}
712 {
713 Set();
714 }
715
716 CodeGenerator* operator->() { return cg; }
717};
718//-----------------------------------------------------------------------------
719
720} // namespace clang::insights
721
722#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...
void insertInits(OutputFormatHelper &outputFormatHelper)
LambdaHelper(const LambdaCallerType lambdaCallerType, OutputFormatHelper &outputFormatHelper)
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
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)
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 HandleLambdaExpr(const LambdaExpr *stmt, LambdaHelper &lambdaHelper)
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)
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, CodeGenerator::LambdaInInitCapture lambdaInitCapture)
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)
void InsertArg(const CXXThisExpr *stmt) override
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