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 <mate.barany@qt.io> (cherry picked from commit a405834ae694ef791d0b648b9a6bb65b67904731) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
5ed1dcd1cc
commit
ef60ea194e
@ -2764,11 +2764,11 @@ enum slackType { Grower = -1, Shrinker = 1 };
|
|||||||
static auto createSlack(QSimplexConstraint *sizeConstraint, qreal interval, slackType type)
|
static auto createSlack(QSimplexConstraint *sizeConstraint, qreal interval, slackType type)
|
||||||
{
|
{
|
||||||
struct R {
|
struct R {
|
||||||
QSimplexVariable *slack;
|
QConcreteSimplexVariable *slack;
|
||||||
QSimplexConstraint *limit;
|
QSimplexConstraint *limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
QSimplexVariable *slack = new QSimplexVariable;
|
auto slack = new QConcreteSimplexVariable;
|
||||||
sizeConstraint->variables.insert(slack, type);
|
sizeConstraint->variables.insert(slack, type);
|
||||||
|
|
||||||
QSimplexConstraint *limit = new QSimplexConstraint;
|
QSimplexConstraint *limit = new QSimplexConstraint;
|
||||||
@ -2783,7 +2783,7 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint
|
|||||||
const QList<AnchorData *> &variables)
|
const QList<AnchorData *> &variables)
|
||||||
{
|
{
|
||||||
QList<QSimplexConstraint *> preferredConstraints;
|
QList<QSimplexConstraint *> preferredConstraints;
|
||||||
QList<QSimplexVariable *> preferredVariables;
|
QList<QConcreteSimplexVariable *> preferredVariables;
|
||||||
QSimplexConstraint objective;
|
QSimplexConstraint objective;
|
||||||
|
|
||||||
// Fill the objective coefficients for this variable. In the
|
// Fill the objective coefficients for this variable. In the
|
||||||
|
@ -156,28 +156,28 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> &newConstraints)
|
|||||||
QList <QSimplexVariable *> artificialList;
|
QList <QSimplexVariable *> artificialList;
|
||||||
|
|
||||||
for (int i = 0; i < constraints.size(); ++i) {
|
for (int i = 0; i < constraints.size(); ++i) {
|
||||||
QSimplexVariable *slack;
|
QConcreteSimplexVariable *slack;
|
||||||
QSimplexVariable *surplus;
|
QConcreteSimplexVariable *surplus;
|
||||||
QSimplexVariable *artificial;
|
QConcreteSimplexVariable *artificial;
|
||||||
|
|
||||||
Q_ASSERT(constraints[i]->helper.first == 0);
|
Q_ASSERT(constraints[i]->helper.first == 0);
|
||||||
Q_ASSERT(constraints[i]->artificial == nullptr);
|
Q_ASSERT(constraints[i]->artificial == nullptr);
|
||||||
|
|
||||||
switch(constraints[i]->ratio) {
|
switch(constraints[i]->ratio) {
|
||||||
case QSimplexConstraint::LessOrEqual:
|
case QSimplexConstraint::LessOrEqual:
|
||||||
slack = new QSimplexVariable;
|
slack = new QConcreteSimplexVariable;
|
||||||
slack->index = ++variableIndex;
|
slack->index = ++variableIndex;
|
||||||
constraints[i]->helper.first = slack;
|
constraints[i]->helper.first = slack;
|
||||||
constraints[i]->helper.second = 1.0;
|
constraints[i]->helper.second = 1.0;
|
||||||
break;
|
break;
|
||||||
case QSimplexConstraint::MoreOrEqual:
|
case QSimplexConstraint::MoreOrEqual:
|
||||||
surplus = new QSimplexVariable;
|
surplus = new QConcreteSimplexVariable;
|
||||||
surplus->index = ++variableIndex;
|
surplus->index = ++variableIndex;
|
||||||
constraints[i]->helper.first = surplus;
|
constraints[i]->helper.first = surplus;
|
||||||
constraints[i]->helper.second = -1.0;
|
constraints[i]->helper.second = -1.0;
|
||||||
Q_FALLTHROUGH();
|
Q_FALLTHROUGH();
|
||||||
case QSimplexConstraint::Equal:
|
case QSimplexConstraint::Equal:
|
||||||
artificial = new QSimplexVariable;
|
artificial = new QConcreteSimplexVariable;
|
||||||
constraints[i]->artificial = artificial;
|
constraints[i]->artificial = artificial;
|
||||||
artificialList += constraints[i]->artificial;
|
artificialList += constraints[i]->artificial;
|
||||||
break;
|
break;
|
||||||
|
@ -29,8 +29,14 @@ struct QSimplexVariable
|
|||||||
|
|
||||||
qreal result;
|
qreal result;
|
||||||
int index;
|
int index;
|
||||||
|
protected:
|
||||||
|
QT_DECLARE_RO5_SMF_AS_DEFAULTED(QSimplexVariable)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// "pure" QSimplexVariable without the protected destructor
|
||||||
|
struct QConcreteSimplexVariable final : QSimplexVariable
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
@ -59,8 +65,8 @@ struct QSimplexConstraint final
|
|||||||
qreal constant;
|
qreal constant;
|
||||||
Ratio ratio;
|
Ratio ratio;
|
||||||
|
|
||||||
std::pair<QSimplexVariable *, qreal> helper;
|
std::pair<QConcreteSimplexVariable *, qreal> helper;
|
||||||
QSimplexVariable * artificial;
|
QConcreteSimplexVariable *artificial;
|
||||||
|
|
||||||
void invert();
|
void invert();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user