Skip to content

Commit

Permalink
Merge pull request #14280 from ibuclaw/merge_stable
Browse files Browse the repository at this point in the history
merge stable
  • Loading branch information
Geod24 authored Jul 9, 2022
2 parents 04d1890 + b7b29ca commit 20bd0ca
Show file tree
Hide file tree
Showing 36 changed files with 414 additions and 27 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.100.0
v2.100.1
23 changes: 23 additions & 0 deletions changelog/deprecate_scope_failure_return.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
`scope(failure)` blocks that contain `return` statements are now deprecated

Starting with this release, having a `return` statement in the body of a `scope(failure)`
statement is deprecated. Having the ability to `return` from such blocks is error prone since currently, Errors are also handled by `scope(failure)`. This leads to the following situation:

---
ulong get () @safe nothrow
{
scope (failure) return 10;
throw new Error("");
}

void main () @safe
{
assert(get() == 10); // passes
}
---

where an error is circumvented by a return. If a return is indeed desired
in such situations, then the solution is to simply use a try-catch block
for the function body.

Note: `scope(exit)` and `scope(success)` already present this restriction.
2 changes: 1 addition & 1 deletion src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ struct ASTBase
{
extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Identifier id, Statement fbody)
{
super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
super(loc, endloc, id ? id : Identifier.generateIdWithLoc("__invariant", loc), stc, null);
this.fbody = fbody;
}

Expand Down
1 change: 1 addition & 0 deletions src/dmd/backend/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,7 @@ void cddiv(ref CodeBuilder cdb,elem *e,regm_t *pretregs)

code cs = void;
cs.Iflags = 0;
cs.IFL2 = 0;
cs.Irex = 0;

switch (e2.Eoper)
Expand Down
4 changes: 4 additions & 0 deletions src/dmd/backend/evalu8.d
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,10 @@ static if (0)
case TYdouble_alias:
e.EV.Vdouble = e1.EV.Vdouble / e2.EV.Vdouble;
break;
case TYldouble:
// cast is required because Vldouble is a soft type on windows
e.EV.Vdouble = cast(double)(e1.EV.Vdouble / e2.EV.Vldouble);
break;
case TYidouble:
e.EV.Vdouble = -e1.EV.Vdouble / e2.EV.Vdouble;
break;
Expand Down
14 changes: 11 additions & 3 deletions src/dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -1106,9 +1106,14 @@ MATCH implicitConvTo(Expression e, Type t)

MATCH visitCond(CondExp e)
{
auto result = visit(e);
if (result != MATCH.nomatch)
return result;
e.econd = e.econd.optimize(WANTvalue);
const opt = e.econd.toBool();
if (opt.isPresent())
{
auto result = visit(e);
if (result != MATCH.nomatch)
return result;
}

MATCH m1 = e.e1.implicitConvTo(t);
MATCH m2 = e.e2.implicitConvTo(t);
Expand Down Expand Up @@ -2942,6 +2947,9 @@ Lagain:

t1 = Type.basic[ty1];
t2 = Type.basic[ty2];

if (!(t1 && t2))
return null;
e1 = e1.castTo(sc, t1);
e2 = e2.castTo(sc, t2);
return Lret(Type.basic[ty]);
Expand Down
3 changes: 3 additions & 0 deletions src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -4442,7 +4442,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
invd.semanticRun < PASS.semantic &&
!ad.isUnionDeclaration() // users are on their own with union fields
)
{
invd.fixupInvariantIdent(ad.invs.length);
ad.invs.push(invd);
}
if (!invd.type)
invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);

Expand Down
14 changes: 13 additions & 1 deletion src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,15 @@ elem* toElem(Expression e, IRState *irs)
return e;
}

/*
https://issues.dlang.org/show_bug.cgi?id=23120
If rhs is a noreturn expression, then there is no point
to generate any code for the noreturen variable.
*/
if (ae.e2.type.isTypeNoreturn())
return setResult(toElem(ae.e2, irs));

Type t1b = ae.e1.type.toBasetype();

// Look for array.length = n
Expand Down Expand Up @@ -6077,7 +6086,10 @@ Lagain:
/* Need to do postblit/destructor.
* void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
*/
assert(op != EXP.construct, "Trying reference _d_arraysetctor, this should not happen!");
if (op == EXP.construct)
{
assert(0, "Trying reference _d_arraysetctor, this should not happen!");
}
r = RTLSYM.ARRAYSETASSIGN;
evalue = el_una(OPaddr, TYnptr, evalue);
// This is a hack so we can call postblits on const/immutable objects.
Expand Down
6 changes: 4 additions & 2 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -9896,9 +9896,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ae.e2.type.nextOf &&
ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);

/* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
* then we do want to make a temporary for it and call its destructor.
*/
const isArraySetCtor =
(ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
ae.e2.isLvalue &&
(ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
ae.e1.type.nextOf &&
ae.e1.type.nextOf.equivalent(ae.e2.type);
Expand Down Expand Up @@ -12638,7 +12640,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
e = new CommaExp(exp.loc, eleft, e);
e.type = Type.tvoid; // ambiguous type?
}
return e;
return e.expressionSemantic(sc);
}
if (auto o = s.isOverloadSet())
{
Expand Down
10 changes: 10 additions & 0 deletions src/dmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -4222,6 +4222,7 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration
{
extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Identifier id, Statement fbody)
{
// Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list.
super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
this.fbody = fbody;
}
Expand Down Expand Up @@ -4258,6 +4259,15 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration
{
v.visit(this);
}

extern (D) void fixupInvariantIdent(size_t offset)
{
OutBuffer idBuf;
idBuf.writestring("__invariant");
idBuf.print(offset);

ident = Identifier.idPool(idBuf[]);
}
}


Expand Down
55 changes: 55 additions & 0 deletions src/dmd/impcnvtab.d
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,57 @@ enum ImpCnvTab impCnvTab = generateImpCnvTab();

ImpCnvTab generateImpCnvTab()
{
TY[TMAX] typeTYs =
[
Tarray,
Tsarray,
Taarray,
Tpointer,
Treference,
Tfunction,
Tident,
Tclass,
Tstruct,
Tenum,
Tdelegate,
Tnone,
Tvoid,
Tint8,
Tuns8,
Tint16,
Tuns16,
Tint32,
Tuns32,
Tint64,
Tuns64,
Tfloat32,
Tfloat64,
Tfloat80,
Timaginary32,
Timaginary64,
Timaginary80,
Tcomplex32,
Tcomplex64,
Tcomplex80,
Tbool,
Tchar,
Twchar,
Tdchar,
Terror,
Tinstance,
Ttypeof,
Ttuple,
Tslice,
Treturn,
Tnull,
Tvector,
Tint128,
Tuns128,
Ttraits,
Tmixin,
Tnoreturn,
Ttag,
];
ImpCnvTab impCnvTab;

// Set conversion tables
Expand Down Expand Up @@ -375,5 +426,9 @@ ImpCnvTab generateImpCnvTab()

X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80);

// "No type is implicitly convertible to noreturn, but noreturn is implicitly convertible to every other type"
foreach(convertToTy; typeTYs)
X(Tnoreturn, convertToTy, convertToTy, convertToTy, convertToTy);

return impCnvTab;
}
4 changes: 3 additions & 1 deletion src/dmd/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public:
auto e1 = doInlineAs!Expression(ifs.ifbody, ids);
assert(ids.foundReturn);
auto e2 = doInlineAs!Expression(s3, ids);

assert(e2);
Expression e = new CondExp(econd.loc, econd, e1, e2);
e.type = e1.type;
if (e.type.ty == Ttuple)
Expand All @@ -250,6 +250,7 @@ public:
}
else
{
ids.foundReturn = false;
auto e = doInlineAs!Expression(sx, ids);
result = Expression.combine(result, e);
}
Expand Down Expand Up @@ -375,6 +376,7 @@ public:

override void visit(ImportStatement s)
{
//printf("ImportStatement.doInlineAs!%s()\n", Result.stringof.ptr);
}

override void visit(ForStatement s)
Expand Down
1 change: 1 addition & 0 deletions src/dmd/root/longdouble.d
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ nothrow @nogc pure:
static if (op == "+") return longdouble_soft(rhs).ld_add(this);
else static if (op == "-") return longdouble_soft(rhs).ld_sub(this);
else static if (op == "*") return longdouble_soft(rhs).ld_mul(this);
else static if (op == "/") return longdouble_soft(rhs).ld_div(this);
else static if (op == "%") return longdouble_soft(rhs).ld_mod(this);
else static assert(false, "Operator `"~op~"` is not implemented");
}
Expand Down
16 changes: 13 additions & 3 deletions src/dmd/statementsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2845,10 +2845,20 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
rs.error("`return` statements cannot be in contracts");
errors = true;
}
if (sc.os && sc.os.tok != TOK.onScopeFailure)
if (sc.os)
{
rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
errors = true;
// @@@DEPRECATED_2.112@@@
// Deprecated in 2.100, transform into an error in 2.112
if (sc.os.tok == TOK.onScopeFailure)
{
rs.deprecation("`return` statements cannot be in `scope(failure)` bodies.");
deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose");
}
else
{
rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
errors = true;
}
}
if (sc.tf)
{
Expand Down
10 changes: 10 additions & 0 deletions test/compilable/backendfloatoptim.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// REQUIRED_ARGS: -O -inline

//https://issues.dlang.org/show_bug.cgi?id=20143
real fun(int x) { return 0.0; }

double bug()
{
// value passed to fun is irrelevant
return 0.0 / fun(420);
}
2 changes: 1 addition & 1 deletion test/compilable/extra-files/vcg-ast.d.cg
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class C : Object
}
invariant
{
this.__invariant1() , this.__invariant2();
this.__invariant0() , this.__invariant1();
}
}
enum __c_wchar_t : dchar;
Expand Down
28 changes: 28 additions & 0 deletions test/compilable/noreturn1.d
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,31 @@ noreturn testdg(noreturn delegate() dg)
{
dg();
}

noreturn func()
{
while(1)
{
}
}
alias AliasSeq(T...) = T;
alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint,
long, ulong, char, wchar, dchar, float, double,
real);
void noreturnImplicit()
{
/*
Testing both ways because, although the underlying table
is symmetrical the code that calls into it may be buggy.
*/
{
int x = 2 + func();
int y = func() + 2;
}
foreach(T; Types)
{
T value;
auto x = value + throw new Exception("Hello");
auto y = (throw new Exception("wow")) + value;
}
}
17 changes: 17 additions & 0 deletions test/compilable/test23082.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// https://issues.dlang.org/show_bug.cgi?id=23082

/*
TEST_OUTPUT:
---
bar
---
*/

void foo()() {}
alias bar = foo;
void bar() { }

void main()
{
pragma(msg, __traits(parent, main).bar.stringof);
}
22 changes: 22 additions & 0 deletions test/compilable/test23166.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// REQUIRED_ARGS: -inline

// https://issues.dlang.org/show_bug.cgi?id=23166

// seg fault with -inline

bool __equals(scope const char[] lhs, scope const char[] rhs)
{
if (lhs.length != rhs.length)
return false;

{
import core.stdc.string : memcmp;
return lhs.length == 0;
}
return true;
}

int test(string type)
{
return __equals(type, "as-is");
}
Loading

0 comments on commit 20bd0ca

Please sign in to comment.