mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +03:00
Refactor checkGC (#21058)
This commit is contained in:
parent
7fb4d613af
commit
90e1a584b5
7 changed files with 46 additions and 41 deletions
|
@ -306,6 +306,7 @@ extern (C++) abstract class Expression : ASTNode
|
|||
{
|
||||
bool parens; // if this is a parenthesized expression
|
||||
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue
|
||||
bool gcPassDone; // `checkGC` has been run on this expression
|
||||
}
|
||||
import dmd.common.bitfields;
|
||||
mixin(generateBitFields!(BitFields, ubyte));
|
||||
|
|
|
@ -11762,6 +11762,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
res = new LoweredAssignExp(ae, res);
|
||||
res.type = ae.type;
|
||||
res = res.checkGC(sc);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -2368,14 +2368,17 @@ public:
|
|||
{
|
||||
bool parens;
|
||||
bool rvalue;
|
||||
bool gcPassDone;
|
||||
BitFields() :
|
||||
parens(),
|
||||
rvalue()
|
||||
rvalue(),
|
||||
gcPassDone()
|
||||
{
|
||||
}
|
||||
BitFields(bool parens, bool rvalue = false) :
|
||||
BitFields(bool parens, bool rvalue = false, bool gcPassDone = false) :
|
||||
parens(parens),
|
||||
rvalue(rvalue)
|
||||
rvalue(rvalue),
|
||||
gcPassDone(gcPassDone)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -2383,6 +2386,8 @@ public:
|
|||
bool parens(bool v);
|
||||
bool rvalue() const;
|
||||
bool rvalue(bool v);
|
||||
bool gcPassDone() const;
|
||||
bool gcPassDone(bool v);
|
||||
private:
|
||||
uint8_t bitFields;
|
||||
public:
|
||||
|
@ -7584,6 +7589,7 @@ class NOGCVisitor final : public StoppableVisitor
|
|||
public:
|
||||
using StoppableVisitor::visit;
|
||||
FuncDeclaration* f;
|
||||
Scope* sc;
|
||||
bool checkOnly;
|
||||
bool err;
|
||||
bool nogcExceptions;
|
||||
|
|
|
@ -45,13 +45,15 @@ extern (C++) final class NOGCVisitor : StoppableVisitor
|
|||
alias visit = typeof(super).visit;
|
||||
public:
|
||||
FuncDeclaration f;
|
||||
Scope* sc;
|
||||
bool checkOnly; // don't print errors
|
||||
bool err;
|
||||
bool nogcExceptions; // -preview=dip1008 enabled
|
||||
|
||||
extern (D) this(FuncDeclaration f) scope @safe
|
||||
extern (D) this(FuncDeclaration f, Scope* sc) scope @safe
|
||||
{
|
||||
this.f = f;
|
||||
this.sc = sc;
|
||||
}
|
||||
|
||||
void doCond(Expression exp)
|
||||
|
@ -86,6 +88,8 @@ public:
|
|||
*/
|
||||
private bool setGC(Expression e, const(char)* msg)
|
||||
{
|
||||
if (sc.debug_)
|
||||
return false;
|
||||
if (checkOnly)
|
||||
{
|
||||
err = true;
|
||||
|
@ -208,9 +212,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Expression checkGC(Scope* sc, Expression e)
|
||||
Expression checkGC(Expression e, Scope* sc)
|
||||
{
|
||||
if (sc.ctfeBlock) // ignore GC in ctfe blocks
|
||||
// printf("%s checkGC(%s)\n", e.loc.toChars, e.toChars);
|
||||
if (e.gcPassDone || sc.ctfeBlock || sc.ctfe || sc.intypeof == 1 || !sc.func)
|
||||
return e;
|
||||
|
||||
/* If betterC, allow GC to happen in non-CTFE code.
|
||||
|
@ -219,28 +224,20 @@ Expression checkGC(Scope* sc, Expression e)
|
|||
*/
|
||||
const betterC = !global.params.useGC;
|
||||
FuncDeclaration f = sc.func;
|
||||
if (e && e.op != EXP.error && f && sc.intypeof != 1 &&
|
||||
(!sc.ctfe || betterC) &&
|
||||
(f.type.ty == Tfunction &&
|
||||
(cast(TypeFunction)f.type).isNogc || f.nogcInprocess || global.params.v.gc) &&
|
||||
!sc.debug_)
|
||||
{
|
||||
scope NOGCVisitor gcv = new NOGCVisitor(f);
|
||||
gcv.checkOnly = betterC;
|
||||
gcv.nogcExceptions = sc.previews.dip1008;
|
||||
walkPostorder(e, gcv);
|
||||
if (gcv.err)
|
||||
{
|
||||
if (betterC)
|
||||
{
|
||||
/* Allow ctfe to use the gc code, but don't let it into the runtime
|
||||
*/
|
||||
f.skipCodegen = true;
|
||||
}
|
||||
else
|
||||
return ErrorExp.get();
|
||||
}
|
||||
}
|
||||
scope NOGCVisitor gcv = new NOGCVisitor(f, sc);
|
||||
gcv.checkOnly = betterC && (f.type.isTypeFunction().isNogc || f.nogcInprocess);
|
||||
gcv.nogcExceptions = sc.previews.dip1008;
|
||||
walkPostorder(e, gcv);
|
||||
e.gcPassDone = true;
|
||||
|
||||
if (!gcv.err)
|
||||
return e;
|
||||
|
||||
if (!betterC)
|
||||
return ErrorExp.get();
|
||||
|
||||
// Allow ctfe to use the gc code, but don't let it into the runtime
|
||||
f.skipCodegen = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -855,7 +855,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
if (tret.ty == Terror)
|
||||
{
|
||||
// https://issues.dlang.org/show_bug.cgi?id=13702
|
||||
exp = checkGC(sc2, exp);
|
||||
exp = exp.checkGC(sc2);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -977,7 +977,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
checkReturnEscape(*sc2, exp, false);
|
||||
}
|
||||
|
||||
exp = checkGC(sc2, exp);
|
||||
exp = exp.checkGC(sc2);
|
||||
|
||||
if (funcdecl.vresult)
|
||||
{
|
||||
|
|
|
@ -219,7 +219,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
s.exp = ErrorExp.get();
|
||||
|
||||
s.exp = s.exp.optimize(WANTvalue);
|
||||
s.exp = checkGC(sc, s.exp);
|
||||
s.exp = s.exp.checkGC(sc);
|
||||
if (s.exp.op == EXP.error)
|
||||
return setError();
|
||||
result = s;
|
||||
|
@ -585,7 +585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
if (checkNonAssignmentArrayOp(ds.condition))
|
||||
ds.condition = ErrorExp.get();
|
||||
ds.condition = ds.condition.optimize(WANTvalue);
|
||||
ds.condition = checkGC(sc, ds.condition);
|
||||
ds.condition = ds.condition.checkGC(sc);
|
||||
|
||||
ds.condition = ds.condition.toBoolean(sc);
|
||||
|
||||
|
@ -658,7 +658,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
if (checkNonAssignmentArrayOp(fs.condition))
|
||||
fs.condition = ErrorExp.get();
|
||||
fs.condition = fs.condition.optimize(WANTvalue);
|
||||
fs.condition = checkGC(sc, fs.condition);
|
||||
fs.condition = fs.condition.checkGC(sc);
|
||||
|
||||
fs.condition = fs.condition.toBoolean(sc);
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
if (checkNonAssignmentArrayOp(fs.increment))
|
||||
fs.increment = ErrorExp.get();
|
||||
fs.increment = fs.increment.optimize(WANTvalue);
|
||||
fs.increment = checkGC(sc, fs.increment);
|
||||
fs.increment = fs.increment.checkGC(sc);
|
||||
}
|
||||
|
||||
sc.sbreak = fs;
|
||||
|
@ -1709,7 +1709,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
|
||||
// checkGC after optimizing the condition so that
|
||||
// compile time constants are reduced.
|
||||
ifs.condition = checkGC(scd, ifs.condition);
|
||||
ifs.condition = ifs.condition.checkGC(scd);
|
||||
|
||||
// Save 'root' of two branches (then and else) at the point where it forks
|
||||
CtorFlow ctorflow_root = scd.ctorflow.clone();
|
||||
|
@ -1897,7 +1897,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
if (checkNonAssignmentArrayOp(ss.condition))
|
||||
ss.condition = ErrorExp.get();
|
||||
ss.condition = ss.condition.optimize(WANTvalue);
|
||||
ss.condition = checkGC(sc, ss.condition);
|
||||
ss.condition = ss.condition.checkGC(sc);
|
||||
if (ss.condition.op == EXP.error)
|
||||
conditionError = true;
|
||||
|
||||
|
@ -2636,7 +2636,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
if (e0)
|
||||
{
|
||||
e0 = e0.optimize(WANTvalue);
|
||||
e0 = checkGC(sc, e0);
|
||||
e0 = e0.checkGC(sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3054,7 +3054,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
ss.exp = ss.exp.expressionSemantic(sc);
|
||||
ss.exp = resolveProperties(sc, ss.exp);
|
||||
ss.exp = ss.exp.optimize(WANTvalue);
|
||||
ss.exp = checkGC(sc, ss.exp);
|
||||
ss.exp = ss.exp.checkGC(sc);
|
||||
if (ss.exp.op == EXP.error)
|
||||
{
|
||||
if (ss._body)
|
||||
|
@ -3178,7 +3178,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
|||
ws.exp = ws.exp.expressionSemantic(sc);
|
||||
ws.exp = resolveProperties(sc, ws.exp);
|
||||
ws.exp = ws.exp.optimize(WANTvalue);
|
||||
ws.exp = checkGC(sc, ws.exp);
|
||||
ws.exp = ws.exp.checkGC(sc);
|
||||
if (ws.exp.op == EXP.error)
|
||||
return setError();
|
||||
if (ws.exp.op == EXP.scope_)
|
||||
|
@ -3740,7 +3740,7 @@ public bool throwSemantic(Loc loc, ref Expression exp, Scope* sc)
|
|||
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = checkGC(sc, exp);
|
||||
exp = exp.checkGC(sc);
|
||||
if (exp.isErrorExp())
|
||||
return false;
|
||||
if (!exp.type.isNaked())
|
||||
|
|
|
@ -1847,7 +1847,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
const tf = sc2.func.type.isTypeFunction();
|
||||
err |= tf.isNothrow && canThrow(ex, sc2.func, null);
|
||||
}
|
||||
ex = checkGC(sc2, ex);
|
||||
ex = ex.checkGC(sc2);
|
||||
if (ex.op == EXP.error)
|
||||
err = true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue