Skip to content

Commit

Permalink
Merge pull request #8113 from WalterBright/ctorflow2
Browse files Browse the repository at this point in the history
refactor: more use of ctorflow
  • Loading branch information
WalterBright committed Apr 2, 2018
2 parents e1aaf4c + 13b6c56 commit 44d849e
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 32 deletions.
22 changes: 22 additions & 0 deletions src/dmd/ctorflow.d
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ struct CtorFlow
}
return fi;
}

/***********************
* Create a deep copy of `this`
* Returns:
* a copy
*/
CtorFlow clone()
{
return CtorFlow(callSuper, saveFieldInit());
}

/**********************************
* Set CSX bits in flow analysis state
* Params:
* csx = bits to set
*/
void orCSX(CSX csx) nothrow pure
{
callSuper |= csx;
foreach (ref u; fieldinit)
u |= csx;
}
}


Expand Down
16 changes: 14 additions & 2 deletions src/dmd/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ struct Scope
return pop();
}

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

extern (D) void mergeFieldInit(Loc loc, const CSX[] fies)
extern (D) void mergeFieldInit(const ref Loc loc, const CSX[] fies)
{
if (ctorflow.fieldinit.length && fies.length)
{
Expand All @@ -354,6 +354,18 @@ struct Scope
}
}

/*******************************
* Merge results of `ctorflow` into `this`.
* Params:
* loc = for error messages
* ctorflow = flow results to merge in
*/
extern (D) void merge(const ref Loc loc, const ref CtorFlow ctorflow)
{
mergeCallSuper(loc, ctorflow.callSuper);
mergeFieldInit(loc, ctorflow.fieldinit);
}

extern (C++) Module instantiatingModule()
{
// TODO: in speculative context, returning 'module' is correct?
Expand Down
18 changes: 7 additions & 11 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -4373,12 +4373,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor

if (exp.e1.isBool(false))
{
/* This is an `assert(0)` which means halt program execution
*/
FuncDeclaration fd = sc.parent.isFuncDeclaration();
if (fd)
fd.hasReturnExp |= 4;
sc.ctorflow.callSuper |= CSX.halt;
foreach (ref u; sc.ctorflow.fieldinit)
u |= CSX.halt;
sc.ctorflow.orCSX(CSX.halt);

if (global.params.useAssert == CHECKENABLE.off)
{
Expand Down Expand Up @@ -9117,20 +9117,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ec = resolveProperties(sc, ec);
ec = ec.toBoolean(sc);

const cs0 = sc.ctorflow.callSuper;
auto fi0 = sc.ctorflow.saveFieldInit();
CtorFlow ctorflow_root = sc.ctorflow.clone();
Expression e1x = exp.e1.expressionSemantic(sc);
e1x = resolveProperties(sc, e1x);

const cs1 = sc.ctorflow.callSuper;
const fi1 = sc.ctorflow.fieldinit;
sc.ctorflow.callSuper = cs0;
sc.ctorflow.fieldinit = fi0;
CtorFlow ctorflow1 = sc.ctorflow;
sc.ctorflow = ctorflow_root;
Expression e2x = exp.e2.expressionSemantic(sc);
e2x = resolveProperties(sc, e2x);

sc.mergeCallSuper(exp.loc, cs1);
sc.mergeFieldInit(exp.loc, fi1);
sc.merge(exp.loc, ctorflow1);

if (ec.op == TOK.error)
{
Expand Down
31 changes: 12 additions & 19 deletions src/dmd/statementsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2124,11 +2124,8 @@ else
/* https://dlang.org/spec/statement.html#IfStatement
*/

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

// check in syntax level
ifs.condition = checkAssignmentAsCondition(ifs.condition);
Expand Down Expand Up @@ -2187,14 +2184,13 @@ else
ifs.ifbody = ifs.ifbody.semanticNoScope(scd);
scd.pop();

cs1 = sc.ctorflow.callSuper;
fi1 = sc.ctorflow.fieldinit;
sc.ctorflow.callSuper = cs0;
sc.ctorflow.fieldinit = fi0;
CtorFlow ctorflow_then = sc.ctorflow; // move flow results
sc.ctorflow = ctorflow_root; // reset flow analysis back to root
if (ifs.elsebody)
ifs.elsebody = ifs.elsebody.semanticScope(sc, null, null);
sc.mergeCallSuper(ifs.loc, cs1);
sc.mergeFieldInit(ifs.loc, fi1);

// Merge 'then' results into 'else' results
sc.merge(ifs.loc, ctorflow_then);

if (ifs.condition.op == TOK.error ||
(ifs.ifbody && ifs.ifbody.isErrorStatement()) ||
Expand Down Expand Up @@ -3228,23 +3224,22 @@ else
rs.error("`return` without calling constructor");
errors = true;
}
sc.ctorflow.callSuper |= CSX.return_;
if (sc.ctorflow.fieldinit.length)

if (sc.ctorflow.fieldinit.length) // if aggregate fields are being constructed
{
auto ad = fd.isMember2();
assert(ad);
foreach (i; 0 .. sc.ctorflow.fieldinit.length)
foreach (i, v; ad.fields)
{
VarDeclaration v = ad.fields[i];
bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
if (mustInit && !(sc.ctorflow.fieldinit[i] & CSX.this_ctor))
{
rs.error("an earlier `return` statement skips field `%s` initialization", v.toChars());
errors = true;
}
sc.ctorflow.fieldinit[i] |= CSX.return_;
}
}
sc.ctorflow.orCSX(CSX.return_);

if (errors)
return setError();
Expand Down Expand Up @@ -4004,10 +3999,8 @@ else

sc = sc.push();
sc.scopesym = sc.enclosing.scopesym;
sc.ctorflow.callSuper |= CSX.label;

foreach (ref u; sc.ctorflow.fieldinit)
u |= CSX.label;
sc.ctorflow.orCSX(CSX.label);

sc.slabel = ls;
if (ls.statement)
Expand Down

0 comments on commit 44d849e

Please sign in to comment.