From ef60ea194e35a1e7bc0bb96a0f2f5765d3445ff7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 12 Mar 2025 15:03:45 +0100 Subject: [PATCH] QSimplex: split QConcreteSimplexVariable from QSimplexVariable The latter was used both as a concrete type as well as a base class, driving Coverity nuts because it couldn't prove that we weren't deleting derived classes (AnchorData) through a QSimplexVariable pointer. This is the same issue that Coverity took with QBrushData (CIDs 218724, 11772), and the solution is the same (cf. 3bbc9e29ef59683351cf35c19a8bd4a030615c64): Split the Janus-headed class into one that acts only as the base class (and has a protected dtor) and one that only acts as a concrete class (and we can mark it final). The protected dtor in the former now statically ensures we don't delete a derived class object through a QSimplexVariable pointer. We don't need to modify AnchorData subclasses, because AnchorData introduces a virtual destructor. Coverity-Id: 390828 Pick-to: 6.8 6.5 Change-Id: I981c02e69af44ebacd4ba3aec76792e14eb15836 Reviewed-by: Mate Barany (cherry picked from commit a405834ae694ef791d0b648b9a6bb65b67904731) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp | 6 +++--- src/widgets/graphicsview/qsimplex_p.cpp | 12 ++++++------ src/widgets/graphicsview/qsimplex_p.h | 10 ++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index 2bcd9589798..5239ef2fb12 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -2764,11 +2764,11 @@ enum slackType { Grower = -1, Shrinker = 1 }; static auto createSlack(QSimplexConstraint *sizeConstraint, qreal interval, slackType type) { struct R { - QSimplexVariable *slack; + QConcreteSimplexVariable *slack; QSimplexConstraint *limit; }; - QSimplexVariable *slack = new QSimplexVariable; + auto slack = new QConcreteSimplexVariable; sizeConstraint->variables.insert(slack, type); QSimplexConstraint *limit = new QSimplexConstraint; @@ -2783,7 +2783,7 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList &variables) { QList preferredConstraints; - QList preferredVariables; + QList preferredVariables; QSimplexConstraint objective; // Fill the objective coefficients for this variable. In the diff --git a/src/widgets/graphicsview/qsimplex_p.cpp b/src/widgets/graphicsview/qsimplex_p.cpp index 4586e0d008c..326aa1c36b5 100644 --- a/src/widgets/graphicsview/qsimplex_p.cpp +++ b/src/widgets/graphicsview/qsimplex_p.cpp @@ -156,28 +156,28 @@ bool QSimplex::setConstraints(const QList &newConstraints) QList artificialList; for (int i = 0; i < constraints.size(); ++i) { - QSimplexVariable *slack; - QSimplexVariable *surplus; - QSimplexVariable *artificial; + QConcreteSimplexVariable *slack; + QConcreteSimplexVariable *surplus; + QConcreteSimplexVariable *artificial; Q_ASSERT(constraints[i]->helper.first == 0); Q_ASSERT(constraints[i]->artificial == nullptr); switch(constraints[i]->ratio) { case QSimplexConstraint::LessOrEqual: - slack = new QSimplexVariable; + slack = new QConcreteSimplexVariable; slack->index = ++variableIndex; constraints[i]->helper.first = slack; constraints[i]->helper.second = 1.0; break; case QSimplexConstraint::MoreOrEqual: - surplus = new QSimplexVariable; + surplus = new QConcreteSimplexVariable; surplus->index = ++variableIndex; constraints[i]->helper.first = surplus; constraints[i]->helper.second = -1.0; Q_FALLTHROUGH(); case QSimplexConstraint::Equal: - artificial = new QSimplexVariable; + artificial = new QConcreteSimplexVariable; constraints[i]->artificial = artificial; artificialList += constraints[i]->artificial; break; diff --git a/src/widgets/graphicsview/qsimplex_p.h b/src/widgets/graphicsview/qsimplex_p.h index 4ae4e544ca5..a64208f7740 100644 --- a/src/widgets/graphicsview/qsimplex_p.h +++ b/src/widgets/graphicsview/qsimplex_p.h @@ -29,8 +29,14 @@ struct QSimplexVariable qreal result; int index; +protected: + QT_DECLARE_RO5_SMF_AS_DEFAULTED(QSimplexVariable) }; +// "pure" QSimplexVariable without the protected destructor +struct QConcreteSimplexVariable final : QSimplexVariable +{ +}; /*! \internal @@ -59,8 +65,8 @@ struct QSimplexConstraint final qreal constant; Ratio ratio; - std::pair helper; - QSimplexVariable * artificial; + std::pair helper; + QConcreteSimplexVariable *artificial; void invert();