Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream stable #3658

Merged
merged 3 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions dmd/cli.d
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,14 @@ dmd -cov -unittest myprog.d
unittesting a library, as it enables running the unittests
in a library without having to manually define an entry-point function.`,
),
Option("makedeps",
"print module dependencies in Makefile compatible format to stdout"
),
Option("makedeps=<filename>",
"write module dependencies in Makefile compatible format to filename (only imports)"
Option("makedeps[=<filename>]",
"print dependencies in Makefile compatible format to filename or stdout.",
`Print dependencies in Makefile compatible format.
If filename is omitted, it prints to stdout.
The emitted targets are the compiled artifacts (executable, object files, libraries).
The emitted dependencies are imported modules and imported string files (via $(B -J) switch).
Special characters in a dependency or target filename are escaped in the GNU Make manner.
`,
),
Option("man",
"open web browser on manual page",
Expand Down
54 changes: 27 additions & 27 deletions dmd/dmangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,12 @@ public:
AssocArray!(Type, size_t) types; // Type => (offset+1) in buf
AssocArray!(Identifier, size_t) idents; // Identifier => (offset+1) in buf
OutBuffer* buf;
Type rootType;

extern (D) this(OutBuffer* buf)
extern (D) this(OutBuffer* buf, Type rootType = null)
{
this.buf = buf;
this.rootType = rootType;
}

/**
Expand Down Expand Up @@ -228,9 +230,29 @@ public:
*/
bool backrefType(Type t)
{
if (!t.isTypeBasic())
return backrefImpl(types, t);
return false;
if (t.isTypeBasic())
return false;

/**
* https://issues.dlang.org/show_bug.cgi?id=21591
*
* Special case for unmerged TypeFunctions: use the generic merged
* function type as backref cache key to avoid missed backrefs.
*
* Merging is based on mangling, so we need to avoid an infinite
* recursion by excluding the case where `t` is the root type passed to
* `mangleToBuffer()`.
*/
if (t != rootType)
{
if (t.ty == Tfunction || t.ty == Tdelegate ||
(t.ty == Tpointer && t.nextOf().ty == Tfunction))
{
t = t.merge2();
}
}

return backrefImpl(types, t);
}

/**
Expand Down Expand Up @@ -1178,7 +1200,7 @@ extern (C++) void mangleToBuffer(Type t, OutBuffer* buf)
buf.writestring(t.deco);
else
{
scope Mangler v = new Mangler(buf);
scope Mangler v = new Mangler(buf, t);
v.visitWithMask(t, 0);
}
}
Expand All @@ -1200,25 +1222,3 @@ extern (C++) void mangleToBuffer(TemplateInstance ti, OutBuffer* buf)
scope Mangler v = new Mangler(buf);
v.mangleTemplateInstance(ti);
}

/******************************************************************************
* Mangle function signatures ('this' qualifier, and parameter types)
* to check conflicts in function overloads.
* It's different from fd.type.deco. For example, fd.type.deco would be null
* if fd is an auto function.
*
* Params:
* buf = `OutBuffer` to write the mangled function signature to
* fd = `FuncDeclaration` to mangle
*/
void mangleToFuncSignature(ref OutBuffer buf, FuncDeclaration fd)
{
auto tf = fd.type.isTypeFunction();

scope Mangler v = new Mangler(&buf);

MODtoDecoBuffer(&buf, tf.mod);
foreach (idx, param; tf.parameterList)
param.accept(v);
buf.writeByte('Z' - tf.parameterList.varargs);
}
7 changes: 2 additions & 5 deletions dmd/dmodule.d
Original file line number Diff line number Diff line change
Expand Up @@ -803,12 +803,9 @@ else
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
auto readResult = File.read(srcfile.toChars());

if (global.params.makeDeps && global.params.oneobj)
if (global.params.emitMakeDeps)
{
OutBuffer* ob = global.params.makeDeps;
ob.writestringln(" \\");
ob.writestring(" ");
ob.writestring(toPosixPath(srcfile.toString()));
global.params.makeDeps.push(srcfile.toChars());
}

return loadSourceBuffer(loc, readResult);
Expand Down
10 changes: 10 additions & 0 deletions dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,11 @@ extern (C++) /* IN_LLVM abstract */ class Expression : ASTNode
inout(ClassReferenceExp) isClassReferenceExp() { return op == TOK.classReference ? cast(typeof(return))this : null; }
}

inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
{
return null;
}

override void accept(Visitor v)
{
v.visit(this);
Expand Down Expand Up @@ -4634,6 +4639,11 @@ extern (C++) class BinAssignExp : BinExp
return toLvalue(sc, this);
}

override inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
{
return this;
}

override void accept(Visitor v)
{
v.visit(this);
Expand Down
2 changes: 2 additions & 0 deletions dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class Expression : public ASTNode
FuncInitExp* isFuncInitExp();
PrettyFuncInitExp* isPrettyFuncInitExp();
ClassReferenceExp* isClassReferenceExp();
virtual BinAssignExp* isBinAssignExp();

void accept(Visitor *v) { v->visit(this); }
};
Expand Down Expand Up @@ -737,6 +738,7 @@ class BinAssignExp : public BinExp
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *ex);
Expression *modifiableLvalue(Scope *sc, Expression *e);
BinAssignExp* isBinAssignExp();
void accept(Visitor *v) { v->visit(this); }
};

Expand Down
57 changes: 40 additions & 17 deletions dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -5984,12 +5984,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ob.writestring(")");
ob.writenl();
}
if (global.params.makeDeps && global.params.oneobj)
if (global.params.emitMakeDeps)
{
OutBuffer* ob = global.params.makeDeps;
ob.writestringln(" \\");
ob.writestring(" ");
escapePath(ob, toPosixPath(name));
global.params.makeDeps.push(name);
}

{
Expand Down Expand Up @@ -6060,6 +6057,26 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
op = resolveProperties(sc, op);
if (op.hasSideEffect)
{
// https://issues.dlang.org/show_bug.cgi?id=21590
// Don't create unnecessary temporaries and detect `assert(a = b)`
if (op.isAssignExp() || op.isBinAssignExp())
{
auto left = (cast(BinExp) op).e1;

// Find leftmost expression to handle other rewrites,
// e.g. --(++a) => a += 1 -= 1
while (left.isAssignExp() || left.isBinAssignExp())
left = (cast(BinExp) left).e1;

// Only use the assignee if it's a variable and skip
// other lvalues (e.g. ref's returned by functions)
if (left.isVarExp())
return left;

// Sanity check that `op` can be converted to boolean
op.toBoolean(sc);
}

const stc = op.isLvalue() ? STC.ref_ : 0;
auto tmp = copyToTemp(stc, "__assertOp", op);
tmp.dsymbolSemantic(sc);
Expand Down Expand Up @@ -8769,22 +8786,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
// https://issues.dlang.org/show_bug.cgi?id=21586
// Rewrite CondExp or e1 will miss direct construction, e.g.
// e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
// a temporary created and an extra destructor call.
// AST will be rewritten to:
// a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
if (e2x.op == TOK.question)
{
/* Rewrite as:
* a ? e1 = b : e1 = c;
*/
CondExp econd = cast(CondExp)e2x;
Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
result = e.expressionSemantic(sc);
return;
}
if (sd.postblit || sd.hasCopyCtor)
{
/* We have a copy constructor for this
*/
if (e2x.op == TOK.question)
{
/* Rewrite as:
* a ? e1 = b : e1 = c;
*/
CondExp econd = cast(CondExp)e2x;
Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2);
Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
result = e.expressionSemantic(sc);
return;
}

if (e2x.isLvalue())
{
Expand Down
3 changes: 2 additions & 1 deletion dmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,9 @@ extern (C++) struct Param
const(char)[] moduleDepsFile; // filename for deps output
OutBuffer* moduleDeps; // contents to be written to deps file

bool emitMakeDeps; // whether to emit makedeps
const(char)[] makeDepsFile; // filename for makedeps output
OutBuffer* makeDeps; // contents to be written to makedeps file
Array!(const(char)*) makeDeps; // dependencies for makedeps

MessageStyle messageStyle = MessageStyle.digitalmars; // style of file/line annotations on messages

Expand Down
5 changes: 3 additions & 2 deletions dmd/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ struct Param
DString moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file

DString makeDepsFile; // filename for makedeps output
OutBuffer *makeDeps; // contents to be written to makedeps file
bool emitMakeDeps; // whether to emit makedeps
DString makeDepsFile; // filename for makedeps output
Array<const char *> makeDeps; // dependencies for makedeps

MessageStyle messageStyle; // style of file/line annotations on messages

Expand Down
Loading