From caec7904bdfa9a12c7f6d4a68d1b8de946c22c7a Mon Sep 17 00:00:00 2001 From: Andreas Fertig Date: Mon, 15 Jul 2024 21:18:57 +0200 Subject: [PATCH] Fixed object-lifetime visualization for more than one temporary. --- CodeGenerator.cpp | 21 +++++++----- tests/EduLifeTimeTest12.expect | 4 +-- tests/EduLifeTimeTest13.cpp | 29 ++++++++++++++++ tests/EduLifeTimeTest13.expect | 61 ++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 tests/EduLifeTimeTest13.cpp create mode 100644 tests/EduLifeTimeTest13.expect diff --git a/CodeGenerator.cpp b/CodeGenerator.cpp index 973e238..92dd038 100644 --- a/CodeGenerator.cpp +++ b/CodeGenerator.cpp @@ -905,11 +905,12 @@ class BindingDeclFinder : public ConstStmtVisitor /// \brief Find a \c DeclRefExpr belonging to a \c DecompositionDecl class TemporaryDeclFinder : public StmtVisitor { - CodeGenerator& codeGenerator; - bool mFound{}; - bool mHaveTemporary{}; - Stmt* mPrevStmt{}; - std::string mTempName{}; + CodeGenerator& codeGenerator; + bool mFound{}; + bool mHaveTemporary{}; + Stmt* mPrevStmt{}; + std::string mTempName{}; + std::vector mDecls{}; public: TemporaryDeclFinder(CodeGenerator& _codeGenerator, const Stmt* stmt, bool inspectReturn = false) @@ -920,6 +921,10 @@ class TemporaryDeclFinder : public StmtVisitor Visit(mPrevStmt); + for(auto d : mDecls) { + codeGenerator.InsertArg(d); + } + RETURN_IF(not GetInsightsOptions().UseShow2C or mFound or not inspectReturn); if(auto* expr = dyn_cast_or_null(stmt)) { @@ -1001,7 +1006,7 @@ class TemporaryDeclFinder : public StmtVisitor ReplaceNode(mPrevStmt, expr, newValue); } - codeGenerator.InsertArg(vd); + mDecls.push_back(vd); } #if 0 @@ -1031,14 +1036,14 @@ class TemporaryDeclFinder : public StmtVisitor auto* newValue = mkDeclRefExpr(vd); ReplaceNode(mPrevStmt, stmt, newValue); - if(SD_FullExpression == stmt->getStorageDuration()) { + if(SD_FullExpression == stmt->getStorageDuration() and not mHaveTemporary) { codeGenerator.StartLifetimeScope(); mHaveTemporary = true; } else if(const auto* extending = stmt->getExtendingDecl()) { codeGenerator.LifetimeAddExtended(vd, extending); } - codeGenerator.InsertArg(vd); + mDecls.push_back(vd); } void VisitStmt(Stmt* stmt) diff --git a/tests/EduLifeTimeTest12.expect b/tests/EduLifeTimeTest12.expect index 2347729..fa53368 100644 --- a/tests/EduLifeTimeTest12.expect +++ b/tests/EduLifeTimeTest12.expect @@ -18,15 +18,15 @@ int main() const std::pair __temporary10_16 = std::pair{__temporary10_13, __temporary10_15}; S a = {1, __temporary10_16}; /* __temporary10_15 // lifetime ends here */ + /* __temporary10_13 // lifetime ends here */ int __temporary11_21 = 2; int __temporary11_23 = 3; const std::pair __temporary11_24 = std::pair{__temporary11_21, __temporary11_23}; S * p = new S{1, __temporary11_24}; /* __temporary11_24 // lifetime ends here */ - return 0; /* __temporary11_23 // lifetime ends here */ /* __temporary11_21 // lifetime ends here */ - /* __temporary10_13 // lifetime ends here */ + return 0; /* __temporary10_16 // lifetime ends here */ /* a // lifetime ends here */ } diff --git a/tests/EduLifeTimeTest13.cpp b/tests/EduLifeTimeTest13.cpp new file mode 100644 index 0000000..32889b3 --- /dev/null +++ b/tests/EduLifeTimeTest13.cpp @@ -0,0 +1,29 @@ +// cmdlineinsights:-edu-show-lifetime + +template +struct pair { + T first; + U second; + + pair(T&& t, U&& u) + : first{t} + , second{u} + {} + + pair(const T& t, const U& u) + : first{t} + , second{u} + {} +}; + +// From: https://eel.is/c++draft/class.temporary#6.11 +struct S { + int mi; + const pair& failingp; +}; + +int main() +{ + S invalids{1, {2, 3}}; // #A +} + diff --git a/tests/EduLifeTimeTest13.expect b/tests/EduLifeTimeTest13.expect new file mode 100644 index 0000000..22b89bd --- /dev/null +++ b/tests/EduLifeTimeTest13.expect @@ -0,0 +1,61 @@ +/************************************************************************************* + * NOTE: This an educational hand-rolled transformation. Things can be incorrect or * + * buggy. * + *************************************************************************************/ +template +struct pair +{ + T first; + U second; + inline pair(T && t, U && u) + : first{t} + , second{u} + { + } + + inline pair(const T & t, const U & u) + : first{t} + , second{u} + { + } + +}; + +/* First instantiated from: EduLifeTimeTest13.cpp:27 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct pair +{ + int first; + int second; + inline pair(int && t, int && u) + : first{t} + , second{u} + { + } + + inline pair(const int & t, const int & u); + +}; + +#endif + +struct S +{ + int mi; + const pair & failingp; +}; + + +int main() +{ + int __temporary27_18 = 2; + int __temporary27_21 = 3; + const pair __temporary27_22 = pair{__temporary27_18, __temporary27_21}; + S invalids = {1, __temporary27_22}; + /* __temporary27_21 // lifetime ends here */ + /* __temporary27_18 // lifetime ends here */ + return 0; + /* __temporary27_22 // lifetime ends here */ + /* invalids // lifetime ends here */ +}