Skip to content

Commit 44d849e

Browse files
authored
Merge pull request #8113 from WalterBright/ctorflow2
refactor: more use of ctorflow
2 parents e1aaf4c + 13b6c56 commit 44d849e

File tree

4 files changed

+55
-32
lines changed

4 files changed

+55
-32
lines changed

src/dmd/ctorflow.d

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,28 @@ struct CtorFlow
6363
}
6464
return fi;
6565
}
66+
67+
/***********************
68+
* Create a deep copy of `this`
69+
* Returns:
70+
* a copy
71+
*/
72+
CtorFlow clone()
73+
{
74+
return CtorFlow(callSuper, saveFieldInit());
75+
}
76+
77+
/**********************************
78+
* Set CSX bits in flow analysis state
79+
* Params:
80+
* csx = bits to set
81+
*/
82+
void orCSX(CSX csx) nothrow pure
83+
{
84+
callSuper |= csx;
85+
foreach (ref u; fieldinit)
86+
u |= csx;
87+
}
6688
}
6789

6890

src/dmd/dscope.d

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ struct Scope
277277
return pop();
278278
}
279279

280-
extern (C++) void mergeCallSuper(Loc loc, CSX cs)
280+
extern (C++) void mergeCallSuper(const ref Loc loc, CSX cs)
281281
{
282282
// This does a primitive flow analysis to support the restrictions
283283
// regarding when and how constructors can appear.
@@ -334,7 +334,7 @@ struct Scope
334334
}
335335
}
336336

337-
extern (D) void mergeFieldInit(Loc loc, const CSX[] fies)
337+
extern (D) void mergeFieldInit(const ref Loc loc, const CSX[] fies)
338338
{
339339
if (ctorflow.fieldinit.length && fies.length)
340340
{
@@ -354,6 +354,18 @@ struct Scope
354354
}
355355
}
356356

357+
/*******************************
358+
* Merge results of `ctorflow` into `this`.
359+
* Params:
360+
* loc = for error messages
361+
* ctorflow = flow results to merge in
362+
*/
363+
extern (D) void merge(const ref Loc loc, const ref CtorFlow ctorflow)
364+
{
365+
mergeCallSuper(loc, ctorflow.callSuper);
366+
mergeFieldInit(loc, ctorflow.fieldinit);
367+
}
368+
357369
extern (C++) Module instantiatingModule()
358370
{
359371
// TODO: in speculative context, returning 'module' is correct?

src/dmd/expressionsem.d

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4373,12 +4373,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
43734373

43744374
if (exp.e1.isBool(false))
43754375
{
4376+
/* This is an `assert(0)` which means halt program execution
4377+
*/
43764378
FuncDeclaration fd = sc.parent.isFuncDeclaration();
43774379
if (fd)
43784380
fd.hasReturnExp |= 4;
4379-
sc.ctorflow.callSuper |= CSX.halt;
4380-
foreach (ref u; sc.ctorflow.fieldinit)
4381-
u |= CSX.halt;
4381+
sc.ctorflow.orCSX(CSX.halt);
43824382

43834383
if (global.params.useAssert == CHECKENABLE.off)
43844384
{
@@ -9117,20 +9117,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
91179117
ec = resolveProperties(sc, ec);
91189118
ec = ec.toBoolean(sc);
91199119

9120-
const cs0 = sc.ctorflow.callSuper;
9121-
auto fi0 = sc.ctorflow.saveFieldInit();
9120+
CtorFlow ctorflow_root = sc.ctorflow.clone();
91229121
Expression e1x = exp.e1.expressionSemantic(sc);
91239122
e1x = resolveProperties(sc, e1x);
91249123

9125-
const cs1 = sc.ctorflow.callSuper;
9126-
const fi1 = sc.ctorflow.fieldinit;
9127-
sc.ctorflow.callSuper = cs0;
9128-
sc.ctorflow.fieldinit = fi0;
9124+
CtorFlow ctorflow1 = sc.ctorflow;
9125+
sc.ctorflow = ctorflow_root;
91299126
Expression e2x = exp.e2.expressionSemantic(sc);
91309127
e2x = resolveProperties(sc, e2x);
91319128

9132-
sc.mergeCallSuper(exp.loc, cs1);
9133-
sc.mergeFieldInit(exp.loc, fi1);
9129+
sc.merge(exp.loc, ctorflow1);
91349130

91359131
if (ec.op == TOK.error)
91369132
{

src/dmd/statementsem.d

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,11 +2124,8 @@ else
21242124
/* https://dlang.org/spec/statement.html#IfStatement
21252125
*/
21262126

2127-
// Evaluate at runtime
2128-
CSX cs0 = sc.ctorflow.callSuper;
2129-
CSX cs1;
2130-
CSX[] fi0 = sc.ctorflow.saveFieldInit();
2131-
CSX[] fi1 = null;
2127+
// Save 'root' of two branches (then and else)
2128+
CtorFlow ctorflow_root = sc.ctorflow.clone();
21322129

21332130
// check in syntax level
21342131
ifs.condition = checkAssignmentAsCondition(ifs.condition);
@@ -2187,14 +2184,13 @@ else
21872184
ifs.ifbody = ifs.ifbody.semanticNoScope(scd);
21882185
scd.pop();
21892186

2190-
cs1 = sc.ctorflow.callSuper;
2191-
fi1 = sc.ctorflow.fieldinit;
2192-
sc.ctorflow.callSuper = cs0;
2193-
sc.ctorflow.fieldinit = fi0;
2187+
CtorFlow ctorflow_then = sc.ctorflow; // move flow results
2188+
sc.ctorflow = ctorflow_root; // reset flow analysis back to root
21942189
if (ifs.elsebody)
21952190
ifs.elsebody = ifs.elsebody.semanticScope(sc, null, null);
2196-
sc.mergeCallSuper(ifs.loc, cs1);
2197-
sc.mergeFieldInit(ifs.loc, fi1);
2191+
2192+
// Merge 'then' results into 'else' results
2193+
sc.merge(ifs.loc, ctorflow_then);
21982194

21992195
if (ifs.condition.op == TOK.error ||
22002196
(ifs.ifbody && ifs.ifbody.isErrorStatement()) ||
@@ -3228,23 +3224,22 @@ else
32283224
rs.error("`return` without calling constructor");
32293225
errors = true;
32303226
}
3231-
sc.ctorflow.callSuper |= CSX.return_;
3232-
if (sc.ctorflow.fieldinit.length)
3227+
3228+
if (sc.ctorflow.fieldinit.length) // if aggregate fields are being constructed
32333229
{
32343230
auto ad = fd.isMember2();
32353231
assert(ad);
3236-
foreach (i; 0 .. sc.ctorflow.fieldinit.length)
3232+
foreach (i, v; ad.fields)
32373233
{
3238-
VarDeclaration v = ad.fields[i];
32393234
bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
32403235
if (mustInit && !(sc.ctorflow.fieldinit[i] & CSX.this_ctor))
32413236
{
32423237
rs.error("an earlier `return` statement skips field `%s` initialization", v.toChars());
32433238
errors = true;
32443239
}
3245-
sc.ctorflow.fieldinit[i] |= CSX.return_;
32463240
}
32473241
}
3242+
sc.ctorflow.orCSX(CSX.return_);
32483243

32493244
if (errors)
32503245
return setError();
@@ -4004,10 +3999,8 @@ else
40043999

40054000
sc = sc.push();
40064001
sc.scopesym = sc.enclosing.scopesym;
4007-
sc.ctorflow.callSuper |= CSX.label;
40084002

4009-
foreach (ref u; sc.ctorflow.fieldinit)
4010-
u |= CSX.label;
4003+
sc.ctorflow.orCSX(CSX.label);
40114004

40124005
sc.slabel = ls;
40134006
if (ls.statement)

0 commit comments

Comments
 (0)