d: Merge upstream dmd d579c467c1, phobos 88aa69b14.

D front-end changes:

    - Throwing from contracts of `nothrow' functions has been
      deprecated, as this breaks the guarantees of `nothrow'.
    - Added language support for initializing the interior pointer of
      associative arrays using `new' keyword.

Phobos changes:

    - The std.digest.digest module has been removed.
    - The std.xml module has been removed.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd d579c467c1.
	* decl.cc (layout_struct_initializer): Update for new front-end
	interface.
	* expr.cc (ExprVisitor::visit (AssignExp *)): Remove lowering of array
	assignments.
	(ExprVisitor::visit (NewExp *)): Add new lowering of new'ing
	associative arrays to an _aaNew() library call.
	* runtime.def (ARRAYSETASSIGN): Remove.
	(AANEW): Define.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime d579c467c1.
	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Remove
	rt/arrayassign.d.
	* libdruntime/Makefile.in: Regenerate.
	* src/MERGE: Merge upstream phobos 88aa69b14.
	* src/Makefile.am (PHOBOS_DSOURCES): Remove std/digest/digest.d,
	std/xml.d.
	* src/Makefile.in: Regenerate.
This commit is contained in:
Iain Buclaw 2022-09-27 10:43:32 +02:00
parent be4a6551ed
commit c8dfa79c99
171 changed files with 3175 additions and 5197 deletions

View file

@ -2335,7 +2335,7 @@ layout_struct_initializer (StructDeclaration *sd)
{
StructLiteralExp *sle = StructLiteralExp::create (sd->loc, sd, NULL);
if (!sd->fill (sd->loc, sle->elements, true))
if (!sd->fill (sd->loc, *sle->elements, true))
gcc_unreachable ();
sle->type = sd->type;

View file

@ -1,4 +1,4 @@
817610b16d0f0f469b9fbb28c000956fb910c43f
4219ba670ce9ff92f3e874f0f048f2c28134c008
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -355,23 +355,22 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* false if any errors occur.
* Otherwise, returns true and the missing arguments will be pushed in elements[].
*/
final bool fill(const ref Loc loc, Expressions* elements, bool ctorinit)
final bool fill(const ref Loc loc, ref Expressions elements, bool ctorinit)
{
//printf("AggregateDeclaration::fill() %s\n", toChars());
assert(sizeok == Sizeok.done);
assert(elements);
const nfields = nonHiddenFields();
bool errors = false;
size_t dim = elements.dim;
elements.setDim(nfields);
foreach (size_t i; dim .. nfields)
(*elements)[i] = null;
elements[i] = null;
// Fill in missing any elements with default initializers
foreach (i; 0 .. nfields)
{
if ((*elements)[i])
if (elements[i])
continue;
auto vd = fields[i];
@ -389,7 +388,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
if (!vd.isOverlappedWith(v2))
continue;
if ((*elements)[j])
if (elements[j])
{
vx = null;
break;
@ -489,10 +488,10 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
else
e = telem.defaultInitLiteral(loc);
}
(*elements)[fieldi] = e;
elements[fieldi] = e;
}
}
foreach (e; *elements)
foreach (e; elements)
{
if (e && e.op == EXP.error)
return false;

View file

@ -125,7 +125,7 @@ public:
bool determineSize(const Loc &loc);
virtual void finalizeSize() = 0;
uinteger_t size(const Loc &loc) override final;
bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
bool fill(const Loc &loc, Expressions &elements, bool ctorinit);
Type *getType() override final;
bool isDeprecated() const override final; // is aggregate deprecated?
void setDeprecated();

View file

@ -16,6 +16,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.expression;
import dmd.root.array;
import dmd.visitor;
bool walkPostorder(Expression e, StoppableVisitor v)
@ -86,12 +87,10 @@ public:
return stop;
}
bool doCond(Expressions* e)
extern(D) bool doCond(Expression[] e)
{
if (!e)
return false;
for (size_t i = 0; i < e.dim && !stop; i++)
doCond((*e)[i]);
for (size_t i = 0; i < e.length && !stop; i++)
doCond(e[i]);
return stop;
}
@ -110,13 +109,13 @@ public:
override void visit(NewExp e)
{
//printf("NewExp::apply(): %s\n", toChars());
doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(NewAnonClassExp e)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(TypeidExp e)
@ -143,13 +142,13 @@ public:
override void visit(CallExp e)
{
//printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
doCond(e.e1) || doCond(e.arguments) || applyTo(e);
doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(ArrayExp e)
{
//printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
doCond(e.e1) || doCond(e.arguments) || applyTo(e);
doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
}
override void visit(SliceExp e)
@ -159,12 +158,12 @@ public:
override void visit(ArrayLiteralExp e)
{
doCond(e.basis) || doCond(e.elements) || applyTo(e);
doCond(e.basis) || doCond(e.elements.peekSlice()) || applyTo(e);
}
override void visit(AssocArrayLiteralExp e)
{
doCond(e.keys) || doCond(e.values) || applyTo(e);
doCond(e.keys.peekSlice()) || doCond(e.values.peekSlice()) || applyTo(e);
}
override void visit(StructLiteralExp e)
@ -173,13 +172,13 @@ public:
return;
int old = e.stageflags;
e.stageflags |= stageApply;
doCond(e.elements) || applyTo(e);
doCond(e.elements.peekSlice()) || applyTo(e);
e.stageflags = old;
}
override void visit(TupleExp e)
{
doCond(e.e0) || doCond(e.exps) || applyTo(e);
doCond(e.e0) || doCond(e.exps.peekSlice()) || applyTo(e);
}
override void visit(CondExp e)

View file

@ -129,8 +129,7 @@ Expression arrayOp(BinExp e, Scope* sc)
return arrayOpInvalidError(e);
auto tiargs = new Objects();
auto args = new Expressions();
buildArrayOp(sc, e, tiargs, args);
auto args = buildArrayOp(sc, e, tiargs);
import dmd.dtemplate : TemplateDeclaration;
__gshared TemplateDeclaration arrayOp;
@ -184,7 +183,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
* using reverse polish notation (RPN) to encode order of operations.
* Encode operations as string arguments, using a "u" prefix for unary operations.
*/
private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions* args)
private Expressions* buildArrayOp(Scope* sc, Expression e, Objects* tiargs)
{
extern (C++) final class BuildArrayOpVisitor : Visitor
{
@ -194,11 +193,11 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
Expressions* args;
public:
extern (D) this(Scope* sc, Objects* tiargs, Expressions* args)
extern (D) this(Scope* sc, Objects* tiargs)
{
this.sc = sc;
this.tiargs = tiargs;
this.args = args;
this.args = new Expressions();
}
override void visit(Expression e)
@ -252,8 +251,9 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
}
}
scope v = new BuildArrayOpVisitor(sc, tiargs, args);
scope v = new BuildArrayOpVisitor(sc, tiargs);
e.accept(v);
return v.args;
}
/***********************************************

View file

@ -1431,7 +1431,7 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
if (auto sc = _scope)
{
_scope = null;
arrayExpressionSemantic(atts, sc);
arrayExpressionSemantic(atts.peekSlice(), sc);
}
auto exps = new Expressions();
if (userAttribDecl && userAttribDecl !is this)
@ -1554,7 +1554,7 @@ int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
return 0;
auto udas = sym.userAttribDecl.getAttributes();
arrayExpressionSemantic(udas, sc, true);
arrayExpressionSemantic(udas.peekSlice(), sc, true);
return udas.each!((uda) {
if (!uda.isTupleExp())

View file

@ -111,13 +111,9 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
auto ts = tbNext.baseElemOf().isTypeStruct();
if (ts)
{
import dmd.id : Id;
auto sd = ts.sym;
const id = ce.f.ident;
if (sd.postblit &&
(id == Id._d_arrayctor || id == Id._d_arraysetctor ||
id == Id._d_arrayassign_l || id == Id._d_arrayassign_r))
if (sd.postblit && isArrayConstructionOrAssign(id))
{
checkFuncThrows(ce, sd.postblit);
return;

View file

@ -1079,386 +1079,210 @@ Format parseGenericFormatSpecifier(scope const char[] format,
return specifier; // success
}
unittest
@("parseGenericFormatSpecifier") unittest
{
/* parseGenericFormatSpecifier
*/
char genSpecifier;
size_t idx;
assert(parseGenericFormatSpecifier("hhd", idx, genSpecifier) == Format.hhd);
assert(genSpecifier == 'd');
void testG(string fmtStr, Format expectedFormat, char expectedGenSpecifier)
{
idx = 0;
assert(parseGenericFormatSpecifier(fmtStr, idx, genSpecifier) == expectedFormat);
assert(genSpecifier == expectedGenSpecifier);
}
idx = 0;
assert(parseGenericFormatSpecifier("hn", idx, genSpecifier) == Format.hn);
assert(genSpecifier == 'n');
idx = 0;
assert(parseGenericFormatSpecifier("ji", idx, genSpecifier) == Format.jd);
assert(genSpecifier == 'i');
idx = 0;
assert(parseGenericFormatSpecifier("lu", idx, genSpecifier) == Format.lu);
assert(genSpecifier == 'u');
testG("hhd", Format.hhd, 'd');
testG("hn", Format.hn, 'n');
testG("ji", Format.jd, 'i');
testG("lu", Format.lu, 'u');
idx = 0;
assert(parseGenericFormatSpecifier("k", idx, genSpecifier) == Format.error);
}
/* parsePrintfFormatSpecifier
*/
@("parsePrintfFormatSpecifier") unittest
{
bool useGNUExts = false;
bool widthStar;
bool precisionStar;
size_t idx = 0;
bool widthStar;
bool precisionStar;
// one for each Format
idx = 0;
assert(parsePrintfFormatSpecifier("%d", idx, widthStar, precisionStar) == Format.d);
assert(idx == 2);
assert(!widthStar && !precisionStar);
idx = 0;
assert(parsePrintfFormatSpecifier("%ld", idx, widthStar, precisionStar) == Format.ld);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%lld", idx, widthStar, precisionStar) == Format.lld);
assert(idx == 4);
idx = 0;
assert(parsePrintfFormatSpecifier("%jd", idx, widthStar, precisionStar) == Format.jd);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%zd", idx, widthStar, precisionStar) == Format.zd);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%td", idx, widthStar, precisionStar) == Format.td);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%g", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%Lg", idx, widthStar, precisionStar) == Format.Lg);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%p", idx, widthStar, precisionStar) == Format.p);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%n", idx, widthStar, precisionStar) == Format.n);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%ln", idx, widthStar, precisionStar) == Format.ln);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%lln", idx, widthStar, precisionStar) == Format.lln);
assert(idx == 4);
idx = 0;
assert(parsePrintfFormatSpecifier("%hn", idx, widthStar, precisionStar) == Format.hn);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%hhn", idx, widthStar, precisionStar) == Format.hhn);
assert(idx == 4);
idx = 0;
assert(parsePrintfFormatSpecifier("%jn", idx, widthStar, precisionStar) == Format.jn);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%zn", idx, widthStar, precisionStar) == Format.zn);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%tn", idx, widthStar, precisionStar) == Format.tn);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%c", idx, widthStar, precisionStar) == Format.c);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%lc", idx, widthStar, precisionStar) == Format.lc);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%s", idx, widthStar, precisionStar) == Format.s);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%ls", idx, widthStar, precisionStar) == Format.ls);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%%", idx, widthStar, precisionStar) == Format.percent);
assert(idx == 2);
// Synonyms
idx = 0;
assert(parsePrintfFormatSpecifier("%i", idx, widthStar, precisionStar) == Format.d);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%u", idx, widthStar, precisionStar) == Format.u);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%o", idx, widthStar, precisionStar) == Format.u);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%x", idx, widthStar, precisionStar) == Format.u);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%X", idx, widthStar, precisionStar) == Format.u);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%f", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%F", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%G", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%La", idx, widthStar, precisionStar) == Format.Lg);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%A", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%lg", idx, widthStar, precisionStar) == Format.lg);
assert(idx == 3);
// width, precision
idx = 0;
assert(parsePrintfFormatSpecifier("%*d", idx, widthStar, precisionStar) == Format.d);
assert(idx == 3);
assert(widthStar && !precisionStar);
idx = 0;
assert(parsePrintfFormatSpecifier("%.*d", idx, widthStar, precisionStar) == Format.d);
assert(idx == 4);
assert(!widthStar && precisionStar);
idx = 0;
assert(parsePrintfFormatSpecifier("%*.*d", idx, widthStar, precisionStar) == Format.d);
assert(idx == 5);
assert(widthStar && precisionStar);
// Too short formats
{
foreach (s; ["%", "%-", "%+", "% ", "%#", "%0", "%*", "%1", "%19", "%.", "%.*", "%.1", "%.12",
"%j", "%z", "%t", "%l", "%h", "%ll", "%hh"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar) == Format.error);
assert(idx == s.length);
}
}
// Undefined format combinations
{
foreach (s; ["%#d", "%llg", "%jg", "%zg", "%tg", "%hg", "%hhg",
"%#c", "%0c", "%jc", "%zc", "%tc", "%Lc", "%hc", "%hhc", "%llc",
"%#s", "%0s", "%js", "%zs", "%ts", "%Ls", "%hs", "%hhs", "%lls",
"%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
"%-n", "%+n", "% n", "%#n", "%0n", "%*n", "%1n", "%19n", "%.n", "%.*n", "%.1n", "%.12n", "%Ln", "%K"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar) == Format.error);
assert(idx == s.length);
}
}
/* parseScanfFormatSpecifier
*/
bool asterisk;
void testP(string fmtStr, Format expectedFormat, size_t expectedIdx)
{
idx = 0;
assert(parsePrintfFormatSpecifier(fmtStr, idx, widthStar, precisionStar, useGNUExts) == expectedFormat);
assert(idx == expectedIdx);
}
// one for each Format
idx = 0;
assert(parseScanfFormatSpecifier("%d", idx, asterisk) == Format.d);
assert(idx == 2);
assert(!asterisk);
testP("%d", Format.d, 2);
assert(!widthStar && !precisionStar);
idx = 0;
assert(parseScanfFormatSpecifier("%hhd", idx, asterisk) == Format.hhd);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%hd", idx, asterisk) == Format.hd);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%ld", idx, asterisk) == Format.ld);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%lld", idx, asterisk) == Format.lld);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%jd", idx, asterisk) == Format.jd);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%zd", idx, asterisk) == Format.zd);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%td", idx, asterisk,) == Format.td);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%u", idx, asterisk) == Format.u);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%hhu", idx, asterisk,) == Format.hhu);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%hu", idx, asterisk) == Format.hu);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%lu", idx, asterisk) == Format.lu);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%llu", idx, asterisk) == Format.llu);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%ju", idx, asterisk) == Format.ju);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%g", idx, asterisk) == Format.g);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%lg", idx, asterisk) == Format.lg);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%Lg", idx, asterisk) == Format.Lg);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%p", idx, asterisk) == Format.p);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%s", idx, asterisk) == Format.s);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%ls", idx, asterisk,) == Format.ls);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%%", idx, asterisk) == Format.percent);
assert(idx == 2);
testP("%ld", Format.ld, 3);
testP("%lld", Format.lld, 4);
testP("%jd", Format.jd, 3);
testP("%zd", Format.zd, 3);
testP("%td", Format.td, 3);
testP("%g", Format.g, 2);
testP("%Lg", Format.Lg, 3);
testP("%p", Format.p, 2);
testP("%n", Format.n, 2);
testP("%ln", Format.ln, 3);
testP("%lln", Format.lln, 4);
testP("%hn", Format.hn, 3);
testP("%hhn", Format.hhn, 4);
testP("%jn", Format.jn, 3);
testP("%zn", Format.zn, 3);
testP("%tn", Format.tn, 3);
testP("%c", Format.c, 2);
testP("%lc", Format.lc, 3);
testP("%s", Format.s, 2);
testP("%ls", Format.ls, 3);
testP("%%", Format.percent, 2);
// Synonyms
idx = 0;
assert(parseScanfFormatSpecifier("%i", idx, asterisk) == Format.d);
assert(idx == 2);
testP("%i", Format.d, 2);
testP("%u", Format.u, 2);
testP("%o", Format.u, 2);
testP("%x", Format.u, 2);
testP("%X", Format.u, 2);
testP("%f", Format.g, 2);
testP("%F", Format.g, 2);
testP("%G", Format.g, 2);
testP("%a", Format.g, 2);
testP("%La", Format.Lg, 3);
testP("%A", Format.g, 2);
testP("%lg", Format.lg, 3);
idx = 0;
assert(parseScanfFormatSpecifier("%n", idx, asterisk) == Format.n);
assert(idx == 2);
// width, precision
testP("%*d", Format.d, 3);
assert(widthStar && !precisionStar);
idx = 0;
assert(parseScanfFormatSpecifier("%o", idx, asterisk) == Format.u);
assert(idx == 2);
testP("%.*d", Format.d, 4);
assert(!widthStar && precisionStar);
idx = 0;
assert(parseScanfFormatSpecifier("%x", idx, asterisk) == Format.u);
assert(idx == 2);
testP("%*.*d", Format.d, 5);
assert(widthStar && precisionStar);
idx = 0;
assert(parseScanfFormatSpecifier("%f", idx, asterisk) == Format.g);
assert(idx == 2);
// Too short formats
foreach (s; ["%", "%-", "%+", "% ", "%#", "%0", "%*", "%1", "%19", "%.", "%.*", "%.1", "%.12",
"%j", "%z", "%t", "%l", "%h", "%ll", "%hh"])
{
testP(s, Format.error, s.length);
}
idx = 0;
assert(parseScanfFormatSpecifier("%e", idx, asterisk) == Format.g);
assert(idx == 2);
// Undefined format combinations
foreach (s; ["%#d", "%llg", "%jg", "%zg", "%tg", "%hg", "%hhg",
"%#c", "%0c", "%jc", "%zc", "%tc", "%Lc", "%hc", "%hhc", "%llc",
"%#s", "%0s", "%js", "%zs", "%ts", "%Ls", "%hs", "%hhs", "%lls",
"%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
"%-n", "%+n", "% n", "%#n", "%0n", "%*n", "%1n", "%19n", "%.n", "%.*n", "%.1n", "%.12n", "%Ln", "%K"])
{
testP(s, Format.error, s.length);
}
idx = 0;
assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
assert(idx == 2);
testP("%C", Format.lc, 2);
testP("%S", Format.ls, 2);
idx = 0;
assert(parseScanfFormatSpecifier("%c", idx, asterisk) == Format.c);
assert(idx == 2);
// GNU extensions: explicitly toggle ISO/GNU flag.
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%#m", "%+m", "%-m", "% m", "%0m"])
{
useGNUExts = false;
testP(s, Format.error, s.length);
useGNUExts = true;
testP(s, Format.error, s.length);
}
foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
{
// valid cases, all parsed as `%m`
// GNU printf()
useGNUExts = true;
testP(s, Format.GNU_m, 2);
// ISO printf()
useGNUExts = false;
testP(s, Format.error, 2);
}
}
@("parseScanfFormatSpecifier") unittest
{
size_t idx;
bool asterisk;
void testS(string fmtStr, Format expectedFormat, size_t expectedIdx)
{
idx = 0;
assert(parseScanfFormatSpecifier(fmtStr, idx, asterisk) == expectedFormat);
assert(idx == expectedIdx);
}
// one for each Format
testS("%d", Format.d, 2);
testS("%hhd", Format.hhd, 4);
testS("%hd", Format.hd, 3);
testS("%ld", Format.ld, 3);
testS("%lld", Format.lld, 4);
testS("%jd", Format.jd, 3);
testS("%zd", Format.zd, 3);
testS("%td", Format.td, 3);
testS("%u", Format.u, 2);
testS("%hhu", Format.hhu, 4);
testS("%hu", Format.hu, 3);
testS("%lu", Format.lu, 3);
testS("%llu", Format.llu, 4);
testS("%ju", Format.ju, 3);
testS("%g", Format.g, 2);
testS("%lg", Format.lg, 3);
testS("%Lg", Format.Lg, 3);
testS("%p", Format.p, 2);
testS("%s", Format.s, 2);
testS("%ls", Format.ls, 3);
testS("%%", Format.percent, 2);
// Synonyms
testS("%i", Format.d, 2);
testS("%n", Format.n, 2);
testS("%o", Format.u, 2);
testS("%x", Format.u, 2);
testS("%f", Format.g, 2);
testS("%e", Format.g, 2);
testS("%a", Format.g, 2);
testS("%c", Format.c, 2);
// asterisk
idx = 0;
assert(parseScanfFormatSpecifier("%*d", idx, asterisk) == Format.d);
assert(idx == 3);
testS("%*d", Format.d, 3);
assert(asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%9ld", idx, asterisk) == Format.ld);
assert(idx == 4);
testS("%9ld", Format.ld, 4);
assert(!asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%*25984hhd", idx, asterisk) == Format.hhd);
assert(idx == 10);
testS("%*25984hhd", Format.hhd, 10);
assert(asterisk);
// scansets
idx = 0;
assert(parseScanfFormatSpecifier("%[a-zA-Z]", idx, asterisk) == Format.s);
assert(idx == 9);
testS("%[a-zA-Z]", Format.s, 9);
assert(!asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%*25l[a-z]", idx, asterisk) == Format.ls);
assert(idx == 10);
testS("%*25l[a-z]", Format.ls, 10);
assert(asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%[]]", idx, asterisk) == Format.s);
assert(idx == 4);
testS("%[]]", Format.s, 4);
assert(!asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%[^]]", idx, asterisk) == Format.s);
assert(idx == 5);
testS("%[^]]", Format.s, 5);
assert(!asterisk);
// Too short formats
foreach (s; ["%", "% ", "%#", "%0", "%*", "%1", "%19",
"%j", "%z", "%t", "%l", "%h", "%ll", "%hh", "%K"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
testS(s, Format.error, s.length);
}
@ -1468,18 +1292,16 @@ unittest
"%jp", "%zp", "%tp", "%Lp", "%hp", "%lp", "%hhp", "%llp",
"%-", "%+", "%#", "%0", "%.", "%Ln"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
testS(s, Format.error, s.length);
}
// Invalid scansets
foreach (s; ["%[]", "%[^", "%[^]", "%[s", "%[0-9lld", "%[", "%l[^]"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
testS(s, Format.error, s.length);
}
// Posix extensions
@ -1488,95 +1310,19 @@ unittest
"%LC", "%lC", "%llC", "%jC", "%tC", "%hC", "%hhC", "%zC",
"%LS", "%lS", "%llS", "%jS", "%tS", "%hS", "%hhS", "%zS"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
testS(s, Format.error, s.length);
}
idx = 0;
assert(parseScanfFormatSpecifier("%mc", idx, asterisk) == Format.POSIX_ms);
assert(idx == 3);
testS("%mc", Format.POSIX_ms, 3);
testS("%ms", Format.POSIX_ms, 3);
testS("%m[0-9]", Format.POSIX_ms, 7);
testS("%mlc", Format.POSIX_mls, 4);
testS("%mls", Format.POSIX_mls, 4);
testS("%ml[^0-9]", Format.POSIX_mls, 9);
testS("%mC", Format.POSIX_mls, 3);
testS("%mS", Format.POSIX_mls, 3);
idx = 0;
assert(parseScanfFormatSpecifier("%ms", idx, asterisk) == Format.POSIX_ms);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%m[0-9]", idx, asterisk) == Format.POSIX_ms);
assert(idx == 7);
idx = 0;
assert(parseScanfFormatSpecifier("%mlc", idx, asterisk) == Format.POSIX_mls);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%mls", idx, asterisk) == Format.POSIX_mls);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%ml[^0-9]", idx, asterisk) == Format.POSIX_mls);
assert(idx == 9);
idx = 0;
assert(parseScanfFormatSpecifier("%mC", idx, asterisk) == Format.POSIX_mls);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%mS", idx, asterisk) == Format.POSIX_mls);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%C", idx, widthStar, precisionStar) == Format.lc);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%C", idx, asterisk) == Format.lc);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%S", idx, widthStar, precisionStar) == Format.ls);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%S", idx, asterisk) == Format.ls);
assert(idx == 2);
// GNU extensions: explicitly toggle ISO/GNU flag.
// ISO printf()
bool useGNUExts = false;
{
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%#m", "%+m", "%-m", "% m", "%0m"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == s.length);
}
foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == 2);
}
}
// GNU printf()
useGNUExts = true;
{
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%#m", "%+m", "%-m", "% m", "%0m"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == s.length);
}
// valid cases, all parsed as `%m`
foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.GNU_m);
assert(idx == 2);
}
}
testS("%C", Format.lc, 2);
testS("%S", Format.ls, 2);
}

View file

@ -105,8 +105,7 @@ FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc)
scope er = new NullExp(ad.loc, ad.type); // dummy rvalue
scope el = new IdentifierExp(ad.loc, Id.p); // dummy lvalue
el.type = ad.type;
Expressions a;
a.setDim(1);
auto a = Expressions(1);
const errors = global.startGagging(); // Do not report errors, even if the template opAssign fbody makes it.
sc = sc.push();
sc.tinst = null;
@ -465,8 +464,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc)
*/
scope er = new NullExp(ad.loc, null); // dummy rvalue
scope el = new IdentifierExp(ad.loc, Id.p); // dummy lvalue
Expressions a;
a.setDim(1);
auto a = Expressions(1);
bool hasIt(Type tthis)
{

View file

@ -1886,15 +1886,6 @@ final class CParser(AST) : Parser!AST
}
if (s !is null)
{
s = applySpecifier(s, specifier);
if (level == LVL.local)
{
// Wrap the declaration in `extern (C) { declaration }`
// Necessary for function pointers, but harmless to apply to all.
auto decls = new AST.Dsymbols(1);
(*decls)[0] = s;
s = new AST.LinkDeclaration(s.loc, linkage, decls);
}
// Saw `asm("name")` in the function, type, or variable definition.
// This is equivalent to `pragma(mangle, "name")` in D
if (asmName)
@ -1917,6 +1908,15 @@ final class CParser(AST) : Parser!AST
p.mangleOverride = str;
}
}
s = applySpecifier(s, specifier);
if (level == LVL.local)
{
// Wrap the declaration in `extern (C) { declaration }`
// Necessary for function pointers, but harmless to apply to all.
auto decls = new AST.Dsymbols(1);
(*decls)[0] = s;
s = new AST.LinkDeclaration(s.loc, linkage, decls);
}
symbols.push(s);
}
first = false;
@ -2603,7 +2603,6 @@ final class CParser(AST) : Parser!AST
{
//printf("cparseDeclarator(%d, %p)\n", declarator, t);
AST.Types constTypes; // all the Types that will need `const` applied to them
constTypes.setDim(0);
AST.Type parseDecl(AST.Type t)
{

View file

@ -2979,10 +2979,10 @@ Lagain:
return Lret(t);
if (t1n.ty == Tvoid) // pointers to void are always compatible
return Lret(t2);
return Lret(t1);
if (t2n.ty == Tvoid)
return Lret(t);
return Lret(t2);
if (t1.implicitConvTo(t2))
return convert(e1, t2);

View file

@ -210,7 +210,7 @@ public:
Dsymbol *aliassym;
const char *kind() const override;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
bool overloadInsert(Dsymbol *s) override;
Dsymbol *toAlias() override;
@ -625,7 +625,7 @@ public:
FuncDeclaration *syntaxCopy(Dsymbol *) override;
bool functionSemantic();
bool functionSemantic3();
bool equals(const RootObject *o) const override final;
bool equals(const RootObject * const o) const override final;
int overrides(FuncDeclaration *fd);
int findVtblIndex(Dsymbols *vtbl, int dim);

View file

@ -265,11 +265,16 @@ extern (C++) final class Import : Dsymbol
scopesym.addAccessiblePackage(p, visibility);
foreach (id; packages[1 .. $]) // [b, c]
{
p = cast(Package) p.symtab.lookup(id);
auto sym = p.symtab.lookup(id);
// https://issues.dlang.org/show_bug.cgi?id=17991
// An import of truly empty file/package can happen
// https://issues.dlang.org/show_bug.cgi?id=20151
// Package in the path conflicts with a module name
if (sym is null)
break;
// https://issues.dlang.org/show_bug.cgi?id=23327
// Package conflicts with symbol of the same name
p = sym.isPackage();
if (p is null)
break;
scopesym.addAccessiblePackage(p, visibility);

View file

@ -2830,7 +2830,7 @@ public:
(*exps)[i] = ex;
}
}
sd.fill(e.loc, exps, false);
sd.fill(e.loc, *exps, false);
auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, sd, exps, e.newtype);
se.origin = se;
@ -4778,12 +4778,6 @@ public:
// If `_d_HookTraceImpl` is found, resolve the underlying hook and replace `e` and `fd` with it.
removeHookTraceImpl(e, fd);
bool isArrayConstructionOrAssign(FuncDeclaration fd)
{
return fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor ||
fd.ident == Id._d_arrayassign_l || fd.ident == Id._d_arrayassign_r;
}
if (fd.ident == Id.__ArrayPostblit || fd.ident == Id.__ArrayDtor)
{
assert(e.arguments.dim == 1);
@ -4837,11 +4831,11 @@ public:
result = interpretRegion(ae, istate);
return;
}
else if (isArrayConstructionOrAssign(fd))
else if (isArrayConstructionOrAssign(fd.ident))
{
// In expressionsem.d, the following lowerings were performed:
// * `T[x] ea = eb;` to `_d_array{,set}ctor(ea[], eb[]);`.
// * `ea = eb` (ea and eb are arrays) to `_d_arrayassign_{l,r}(ea[], eb[])`.
// * `ea = eb` to `_d_array{,setassign,assign_l,assign_r}(ea[], eb)`.
// The following code will rewrite them back to `ea = eb` and
// then interpret that expression.

View file

@ -833,6 +833,23 @@ public:
printf(" parent = %s %s", s.parent.kind(), s.parent.toChars());
printf("\n");
}
if (s.parent && s.ident)
{
if (auto m = s.parent.isModule())
{
if (m.filetype == FileType.c)
{
/* C types at global level get mangled into the __C global namespace
* to get the same mangling regardless of which module it
* is declared in. This works because types are the same if the mangling
* is the same.
*/
mangleIdentifier(Id.ImportC, s); // parent
mangleIdentifier(s.ident, s);
return;
}
}
}
mangleParent(s);
if (s.ident)
mangleIdentifier(s.ident, s);

View file

@ -3294,7 +3294,7 @@ private struct MarkdownLink
* Params:
* buf = an OutBuffer containing the DDoc
* i = the index within `buf` that points to the first character of the URL.
* If this function succeeds `i` will point just after the the end of the URL.
* If this function succeeds `i` will point just after the end of the URL.
* Returns: whether a URL was found and parsed
*/
private bool parseHref(ref OutBuffer buf, ref size_t i)
@ -3362,7 +3362,7 @@ private struct MarkdownLink
* Params:
* buf = an OutBuffer containing the DDoc
* i = the index within `buf` that points to the first character of the title.
* If this function succeeds `i` will point just after the the end of the title.
* If this function succeeds `i` will point just after the end of the title.
* Returns: whether a title was found and parsed
*/
private bool parseTitle(ref OutBuffer buf, ref size_t i)

View file

@ -1544,6 +1544,12 @@ public:
if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
return null;
/* If two imports from C import files, pick first one, as C has global name space
*/
if (s.isCsymbol() && s2.isCsymbol())
continue;
if (!(flags & IgnoreErrors))
ScopeDsymbol.multiplyDefined(loc, s, s2);
break;

View file

@ -189,7 +189,7 @@ public:
virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments
Loc getLoc();
const char *locToChars();
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
bool isAnonymous() const;
void error(const Loc &loc, const char *format, ...);
void error(const char *format, ...);

View file

@ -58,6 +58,7 @@ import dmd.nspace;
import dmd.objc;
import dmd.opover;
import dmd.parse;
import dmd.root.array;
import dmd.root.filename;
import dmd.common.outbuffer;
import dmd.root.rmem;
@ -983,7 +984,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// possibilities.
if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
{
//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
//printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
if (!ei)
{
ArrayInitializer ai = dsym._init.isArrayInitializer();
@ -1014,24 +1015,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
}
Expression exp = ei.exp;
Expression e1 = new VarExp(dsym.loc, dsym);
if (isBlit)
exp = new BlitExp(dsym.loc, e1, exp);
else
exp = new ConstructExp(dsym.loc, e1, exp);
dsym.canassign++;
exp = exp.expressionSemantic(sc);
dsym.canassign--;
exp = exp.optimize(WANTvalue);
if (exp.op == EXP.error)
{
dsym._init = new ErrorInitializer();
ei = null;
}
else
ei.exp = exp;
if (ei && dsym.isScope())
{
Expression ex = ei.exp.lastComma();
@ -1054,6 +1037,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
f.tookAddressOf--;
}
}
Expression exp = ei.exp;
Expression e1 = new VarExp(dsym.loc, dsym);
if (isBlit)
exp = new BlitExp(dsym.loc, e1, exp);
else
exp = new ConstructExp(dsym.loc, e1, exp);
dsym.canassign++;
exp = exp.expressionSemantic(sc);
dsym.canassign--;
exp = exp.optimize(WANTvalue);
if (exp.op == EXP.error)
{
dsym._init = new ErrorInitializer();
ei = null;
}
else
ei.exp = exp;
}
else
{
@ -1956,7 +1957,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
//printf("UserAttributeDeclaration::semantic() %p\n", this);
if (uad.decl && !uad._scope)
uad.Dsymbol.setScope(sc); // for function local symbols
arrayExpressionSemantic(uad.atts, sc, true);
arrayExpressionSemantic(uad.atts.peekSlice(), sc, true);
return attribSemantic(uad);
}
@ -4182,6 +4183,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dd.errors = true;
return;
}
if (ad.isClassDeclaration() && ad.classKind == ClassKind.d)
{
// Class destructors are implicitly `scope`
dd.storage_class |= STC.scope_;
}
if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
ad.userDtors.push(dd);
if (!dd.type)

View file

@ -1327,7 +1327,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Loc instLoc = ti.loc;
Objects* tiargs = ti.tiargs;
auto dedargs = new Objects();
auto dedargs = new Objects(parameters.dim);
Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
version (none)
@ -1346,7 +1346,6 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
assert(_scope);
dedargs.setDim(parameters.dim);
dedargs.zero();
dedtypes.setDim(parameters.dim);
@ -1511,7 +1510,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
}
if (toParent().isModule() || (_scope.stc & STC.static_))
if (toParent().isModule())
tthis = null;
if (tthis)
{
@ -1534,7 +1533,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
// Match attributes of tthis against attributes of fd
if (fd.type && !fd.isCtorDeclaration())
if (fd.type && !fd.isCtorDeclaration() && !(_scope.stc & STC.static_))
{
StorageClass stc = _scope.stc | fd.storage_class2;
// Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
@ -2716,14 +2715,27 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
if (mfa == MATCH.nomatch)
return 0;
if (mfa > m.last) goto LfIsBetter;
if (mfa < m.last) goto LlastIsBetter;
int firstIsBetter()
{
td_best = null;
ti_best = null;
ta_last = MATCH.exact;
m.last = mfa;
m.lastf = fd;
tthis_best = tthis_fd;
ov_index = 0;
m.count = 1;
return 0;
}
if (mfa > m.last) return firstIsBetter();
if (mfa < m.last) return 0;
/* See if one of the matches overrides the other.
*/
assert(m.lastf);
if (m.lastf.overrides(fd)) goto LlastIsBetter;
if (fd.overrides(m.lastf)) goto LfIsBetter;
if (m.lastf.overrides(fd)) return 0;
if (fd.overrides(m.lastf)) return firstIsBetter();
/* Try to disambiguate using template-style partial ordering rules.
* In essence, if f() and g() are ambiguous, if f() can call g(),
@ -2734,8 +2746,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
MATCH c1 = fd.leastAsSpecialized(m.lastf);
MATCH c2 = m.lastf.leastAsSpecialized(fd);
//printf("c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2) goto LfIsBetter;
if (c1 < c2) goto LlastIsBetter;
if (c1 > c2) return firstIsBetter();
if (c1 < c2) return 0;
}
/* The 'overrides' check above does covariant checking only
@ -2756,12 +2768,12 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
{
if (firstCovariant != Covariant.yes && firstCovariant != Covariant.no)
{
goto LlastIsBetter;
return 0;
}
}
else if (firstCovariant == Covariant.yes || firstCovariant == Covariant.no)
{
goto LfIsBetter;
return firstIsBetter();
}
}
@ -2780,37 +2792,22 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
fd._linkage == m.lastf._linkage)
{
if (fd.fbody && !m.lastf.fbody)
goto LfIsBetter;
return firstIsBetter();
if (!fd.fbody)
goto LlastIsBetter;
return 0;
}
// https://issues.dlang.org/show_bug.cgi?id=14450
// Prefer exact qualified constructor for the creating object type
if (isCtorCall && tf.mod != m.lastf.type.mod)
{
if (tthis.mod == tf.mod) goto LfIsBetter;
if (tthis.mod == m.lastf.type.mod) goto LlastIsBetter;
if (tthis.mod == tf.mod) return firstIsBetter();
if (tthis.mod == m.lastf.type.mod) return 0;
}
m.nextf = fd;
m.count++;
return 0;
LlastIsBetter:
return 0;
LfIsBetter:
td_best = null;
ti_best = null;
ta_last = MATCH.exact;
m.last = mfa;
m.lastf = fd;
tthis_best = tthis_fd;
ov_index = 0;
m.count = 1;
return 0;
}
int applyTemplate(TemplateDeclaration td)
@ -3844,10 +3841,20 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
tp = (*parameters)[i];
else
{
Loc loc;
// The "type" (it hasn't been resolved yet) of the function parameter
// does not have a location but the parameter it is related to does,
// so we use that for the resolution (better error message).
if (inferStart < parameters.dim)
{
TemplateParameter loctp = (*parameters)[inferStart];
loc = loctp.loc;
}
Expression e;
Type tx;
Dsymbol s;
taa.index.resolve(Loc.initial, sc, e, tx, s);
taa.index.resolve(loc, sc, e, tx, s);
edim = s ? getValue(s) : getValue(e);
}
}

View file

@ -1423,10 +1423,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
* auto dg = () return { return &x; }
* Because dg.ptr points to x, this is returning dt.ptr+offset
*/
if (global.params.useDIP1000 == FeatureState.enabled)
{
sc.func.storage_class |= STC.return_ | STC.returninferred;
}
sc.func.storage_class |= STC.return_ | STC.returninferred;
}
}

View file

@ -7197,6 +7197,26 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
}
}
/**
* Verify if the given identifier is any of
* _d_array{ctor,setctor,setassign,assign_l, assign_r}.
*
* Params:
* id = the identifier to verify
*
* Returns:
* `true` if the identifier corresponds to a construction of assignement
* runtime hook, `false` otherwise.
*/
bool isArrayConstructionOrAssign(const Identifier id)
{
import dmd.id : Id;
return id == Id._d_arrayctor || id == Id._d_arraysetctor ||
id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
id == Id._d_arraysetassign;
}
/******************************
* Provide efficient way to implement isUnaExp(), isBinExp(), isBinAssignExp()
*/

View file

@ -250,7 +250,7 @@ public:
static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type);
static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
real_t toReal() override;
real_t toImaginary() override;
@ -280,7 +280,7 @@ public:
static RealExp *create(const Loc &loc, real_t value, Type *type);
static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
@ -297,7 +297,7 @@ public:
static ComplexExp *create(const Loc &loc, complex_t value, Type *type);
static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
@ -358,7 +358,7 @@ public:
class NullExp final : public Expression
{
public:
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
Optional<bool> toBool() override;
StringExp *toStringExp() override;
void accept(Visitor *v) override { v->visit(this); }
@ -377,7 +377,7 @@ public:
static StringExp *create(const Loc &loc, const char *s);
static StringExp *create(const Loc &loc, const void *s, d_size_t len);
static void emplace(UnionExp *pue, const Loc &loc, const char *s);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
char32_t getCodeUnit(d_size_t i) const;
void setCodeUnit(d_size_t i, char32_t c);
StringExp *toStringExp() override;
@ -408,7 +408,7 @@ public:
static TupleExp *create(const Loc &loc, Expressions *exps);
TupleExp *syntaxCopy() override;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -423,7 +423,7 @@ public:
static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
ArrayLiteralExp *syntaxCopy() override;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
Expression *getElement(d_size_t i); // use opIndex instead
Expression *opIndex(d_size_t i);
Optional<bool> toBool() override;
@ -439,7 +439,7 @@ public:
Expressions *values;
OwnedBy ownedByCtfe;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
AssocArrayLiteralExp *syntaxCopy() override;
Optional<bool> toBool() override;
@ -477,7 +477,7 @@ public:
OwnedBy ownedByCtfe;
static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
Expression *getField(Type *type, unsigned offset);
int getFieldIndex(Type *type, unsigned offset);
@ -583,7 +583,7 @@ class VarExp final : public SymbolExp
public:
bool delegateWasExtracted;
static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
@ -612,7 +612,7 @@ public:
TemplateDeclaration *td;
TOK tok;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
FuncExp *syntaxCopy() override;
const char *toChars() const override;
bool checkType() override;

View file

@ -62,6 +62,7 @@ import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.printast;
import dmd.root.array;
import dmd.root.ctfloat;
import dmd.root.file;
import dmd.root.filename;
@ -336,22 +337,18 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
/******************************
* Perform semantic() on an array of Expressions.
*/
bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
extern(D) bool arrayExpressionSemantic(
Expression[] exps, Scope* sc, bool preserveErrors = false)
{
bool err = false;
if (exps)
foreach (ref e; exps)
{
foreach (ref e; *exps)
{
if (e)
{
auto e2 = e.expressionSemantic(sc);
if (e2.op == EXP.error)
err = true;
if (preserveErrors || e2.op != EXP.error)
e = e2;
}
}
if (e is null) continue;
auto e2 = e.expressionSemantic(sc);
if (e2.op == EXP.error)
err = true;
if (preserveErrors || e2.op != EXP.error)
e = e2;
}
return err;
}
@ -443,7 +440,7 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
}
if (!s)
return ue.e1.type.getProperty(sc, loc, ident, 0);
return ue.e1.type.getProperty(sc, loc, ident, 0, ue.e1);
FuncDeclaration f = s.isFuncDeclaration();
if (f)
@ -550,7 +547,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
if (!global.endGagging(errors))
return e;
if (arrayExpressionSemantic(originalArguments, sc))
if (arrayExpressionSemantic(originalArguments.peekSlice(), sc))
return ErrorExp.get();
/* fall down to UFCS */
@ -3111,7 +3108,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (e.basis)
e.basis = e.basis.expressionSemantic(sc);
if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == EXP.error))
if (arrayExpressionSemantic(e.elements.peekSlice(), sc) || (e.basis && e.basis.op == EXP.error))
return setError();
expandTuples(e.elements);
@ -3154,8 +3151,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Run semantic() on each element
bool err_keys = arrayExpressionSemantic(e.keys, sc);
bool err_vals = arrayExpressionSemantic(e.values, sc);
bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc);
bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc);
if (err_keys || err_vals)
return setError();
@ -3201,7 +3198,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
// run semantic() on each element
if (arrayExpressionSemantic(e.elements, sc))
if (arrayExpressionSemantic(e.elements.peekSlice(), sc))
return setError();
expandTuples(e.elements);
@ -3213,7 +3210,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Fill out remainder of elements[] with default initializers for fields[]
*/
if (!e.sd.fill(e.loc, e.elements, false))
if (!e.sd.fill(e.loc, *e.elements, false))
{
/* An error in the initializer needs to be recorded as an error
* in the enclosing function or template, since the initializer
@ -3524,7 +3521,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.newtype = exp.type; // in case type gets cast to something else
Type tb = exp.type.toBasetype();
//printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
if (arrayExpressionSemantic(exp.arguments, sc))
if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc))
{
return setError();
}
@ -3672,7 +3669,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
if (cd.disableNew)
if (cd.disableNew && !exp.onstack)
{
exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
originalNewtype.toChars());
@ -3807,7 +3804,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!sd.fit(exp.loc, sc, exp.arguments, tb))
return setError();
if (!sd.fill(exp.loc, exp.arguments, false))
if (!sd.fill(exp.loc, *exp.arguments, false))
return setError();
if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
@ -4259,7 +4256,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (FuncExp fe = exp.e1.isFuncExp())
{
if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
preFunctionParameters(sc, exp.arguments))
return setError();
// Run e1 semantic even if arguments have any errors
@ -4497,7 +4495,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp.e1;
return;
}
if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
preFunctionParameters(sc, exp.arguments))
return setError();
// Check for call operator overload
@ -4543,7 +4542,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
goto Lx;
auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
if (!sd.fill(exp.loc, sle.elements, true))
if (!sd.fill(exp.loc, *sle.elements, true))
return setError();
if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
return setError();
@ -4614,7 +4613,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
Expression e;
// Make sure to use the the enum type itself rather than its
// Make sure to use the enum type itself rather than its
// base type
// https://issues.dlang.org/show_bug.cgi?id=16346
if (exp.e1.type.ty == Tenum)
@ -8661,7 +8660,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (sd.isNested())
{
auto sle = new StructLiteralExp(loc, sd, null, t);
if (!sd.fill(loc, sle.elements, true))
if (!sd.fill(loc, *sle.elements, true))
return ErrorExp.get();
if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
return ErrorExp.get();
@ -9991,15 +9990,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
/***************************************
* Lower AssignExp to `_d_arrayassign_{l,r}` if needed.
* Lower AssignExp to `_d_array{setassign,assign_l,assign_r}` if needed.
*
* Params:
* ae = the AssignExp to be lowered
* fromCommaExp = indicates whether `ae` is part of a CommaExp or not,
* so no unnecessary temporay variable is created.
* Returns:
* a CommaExp contiaining call a to `_d_arrayassign_{l,r}` if needed or
* `ae` otherwise
* a CommaExp contiaining call a to `_d_array{setassign,assign_l,assign_r}`
* if needed or `ae` otherwise
*/
private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false)
{
@ -10007,12 +10006,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (t1b.ty != Tsarray && t1b.ty != Tarray)
return ae;
const isArrayAssign =
(ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
(ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
(ae.e1.type.nextOf && ae.e2.type.nextOf && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf));
(ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
if (!isArrayAssign)
const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
(ae.e1.type.nextOf() && ae.e2.type.implicitConvTo(ae.e1.type.nextOf()));
if (!isArrayAssign && !isArraySetAssign)
return ae;
const ts = t1b.nextOf().baseElemOf().isTypeStruct();
@ -10020,9 +10021,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return ae;
Expression res;
auto func = ae.e2.isLvalue || ae.e2.isSliceExp ? Id._d_arrayassign_l : Id._d_arrayassign_r;
Identifier func = isArraySetAssign ? Id._d_arraysetassign :
ae.e2.isLvalue() || ae.e2.isSliceExp() ? Id._d_arrayassign_l : Id._d_arrayassign_r;
// Lower to `.object._d_arrayassign_l{r}(e1, e2)``
// Lower to `.object._d_array{setassign,assign_l,assign_r}(e1, e2)``
Expression id = new IdentifierExp(ae.loc, Id.empty);
id = new DotIdExp(ae.loc, id, Id.object);
id = new DotIdExp(ae.loc, id, func);
@ -10032,10 +10034,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
.expressionSemantic(sc));
Expression eValue2, value2 = ae.e2;
if (ae.e2.isLvalue)
value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf)
if (isArrayAssign && value2.isLvalue())
value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf())
.expressionSemantic(sc);
else if (!fromCommaExp)
else if (!fromCommaExp &&
(isArrayAssign || (isArraySetAssign && !value2.isLvalue())))
{
// Rvalues from CommaExps were introduced in `visit(AssignExp)`
// and are temporary variables themselves. Rvalues from trivial
@ -10044,7 +10047,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// `__assigntmp` will be destroyed together with the array `ae.e1`.
// When `ae.e2` is a variadic arg array, it is also `scope`, so
// `__assigntmp` may also be scope.
auto vd = copyToTemp(STC.rvalue | STC.nodtor | STC.scope_, "__assigntmp", ae.e2);
StorageClass stc = STC.nodtor;
if (isArrayAssign)
stc |= STC.rvalue | STC.scope_;
auto vd = copyToTemp(stc, "__assigntmp", ae.e2);
eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
value2 = new VarExp(vd.loc, vd).expressionSemantic(sc);
}
@ -10052,7 +10059,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression ce = new CallExp(ae.loc, id, arguments);
res = Expression.combine(eValue2, ce).expressionSemantic(sc);
res = Expression.combine(res, ae.e1).expressionSemantic(sc);
if (isArrayAssign)
res = Expression.combine(res, ae.e1).expressionSemantic(sc);
if (global.params.verbose)
message("lowered %s =>\n %s", ae.toChars(), res.toChars());

View file

@ -3216,11 +3216,12 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
}
}
if (tiargs && arrayObjectIsError(tiargs) ||
fargs && arrayObjectIsError(cast(Objects*)fargs))
{
if (tiargs && arrayObjectIsError(tiargs))
return null;
}
if (fargs !is null)
foreach (arg; *fargs)
if (isError(arg))
return null;
MatchAccumulator m;
functionResolve(m, s, loc, sc, tiargs, tthis, fargs, null);
@ -3758,9 +3759,9 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
// backend
bool deferToObj;
extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null)
extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null, StorageClass storage_class = STC.undefined_)
{
super(loc, endloc, null, STC.undefined_, type);
super(loc, endloc, null, storage_class, type);
this.ident = id ? id : Id.empty;
this.tok = tok;
this.fes = fes;
@ -3774,7 +3775,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
{
//printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
assert(!s);
auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident);
auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident, storage_class & STC.auto_);
f.treq = treq; // don't need to copy
FuncDeclaration.syntaxCopy(f);
return f;
@ -3833,9 +3834,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
{
Expression exp = s.exp;
if (exp && !exp.type.equals(tret))
{
s.exp = exp.castTo(sc, tret);
}
s.exp = exp.implicitCastTo(sc, tret);
}
}

View file

@ -84,13 +84,10 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
case TOK.string_:
constraint = p.parsePrimaryExp();
// @@@DEPRECATED_2.101@@@
// Old parser allowed omitting parentheses around the expression.
// Deprecated in 2.091. Can be made permanent error after 2.100
if (p.token.value != TOK.leftParenthesis)
{
arg = p.parseAssignExp();
deprecation(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
}
else
{
@ -527,6 +524,9 @@ unittest
// Found ',' when expecting ':'
q{ asm { "", "";
} },
// https://issues.dlang.org/show_bug.cgi?id=20593
q{ asm { "instruction" : : "operand" 123; } },
];
foreach (test; passAsmTests)

View file

@ -319,6 +319,7 @@ immutable Msgtable[] msgtable =
{ "_aaApply2" },
{ "_d_arrayctor" },
{ "_d_arraysetctor" },
{ "_d_arraysetassign" },
{ "_d_arrayassign_l" },
{ "_d_arrayassign_r" },
@ -511,6 +512,7 @@ immutable Msgtable[] msgtable =
{ "wchar_t" },
// for C compiler
{ "ImportC", "__C" },
{ "__tag" },
{ "dllimport" },
{ "dllexport" },

View file

@ -167,6 +167,7 @@ extern (C++) final class ArrayInitializer : Initializer
uint dim; // length of array being initialized
Type type; // type that array will be used to initialize
bool sem; // true if semantic() is run
bool isCarray; // C array semantics
extern (D) this(const ref Loc loc)
{

View file

@ -78,6 +78,7 @@ public:
unsigned dim; // length of array being initialized
Type *type; // type that array will be used to initialize
bool sem; // true if semantic() is run
bool isCarray; // C array semantics
bool isAssociativeArray() const;
Expression *toAssocArrayLiteral();

View file

@ -225,7 +225,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
assert(sc);
auto tm = vd.type.addMod(t.mod);
auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
auto ex = iz.initializerToExpression();
auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
if (ex.op == EXP.error)
{
errors = true;
@ -243,7 +243,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// Make a StructLiteralExp out of elements[]
auto sle = new StructLiteralExp(i.loc, sd, elements, t);
if (!sd.fill(i.loc, elements, false))
if (!sd.fill(i.loc, *elements, false))
return err();
sle.type = t;
auto ie = new ExpInitializer(i.loc, sle);
@ -272,7 +272,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
uint length;
const(uint) amax = 0x80000000;
bool errors = false;
//printf("ArrayInitializer::semantic(%s)\n", t.toChars());
//printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i);
if (i.sem) // if semantic() already run
{
return i;
@ -374,11 +374,22 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
if (auto tsa = t.isTypeSArray())
{
uinteger_t edim = tsa.dim.toInteger();
if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
if (sc.flags & SCOPE.Cfile && tsa.isIncomplete())
{
error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
return err();
// Change to array of known length
auto tn = tsa.next.toBasetype();
tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t));
tx = tsa; // rewrite caller's type
i.type = tsa; // remember for later passes
}
else
{
uinteger_t edim = tsa.dim.toInteger();
if (i.dim > edim)
{
error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
return err();
}
}
}
if (errors)
@ -394,6 +405,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
return err();
}
//printf("returns ai: %s\n", i.toChars());
return i;
}
@ -661,295 +673,380 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
Initializer visitC(CInitializer ci)
{
if (ci.sem) // if semantic() already run
return ci;
//printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
ci.sem = true;
/* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
*/
t = t.toBasetype();
ci.type = t; // later passes will need this
auto dil = ci.initializerList[];
size_t i = 0; // index into dil[]
const uint amax = 0x8000_0000;
bool errors;
/* If `{ expression }` return the expression initializer
*/
ExpInitializer isBraceExpression()
{
auto dil = ci.initializerList[];
return (dil.length == 1 && !dil[0].designatorList)
? dil[0].initializer.isExpInitializer()
: null;
}
/* Convert struct initializer into ExpInitializer
/********************************
*/
Initializer structs(TypeStruct ts)
bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si)
{
//printf("structs %s\n", ts.toChars());
foreach (fld; fields)
{
if (field.isOverlappedWith(fld))
{
// look for initializer corresponding with fld
foreach (i, ident; si.field[])
{
if (ident == fld.ident && si.value[i])
return true; // already an initializer for `field`
}
}
}
return false;
}
/* Run semantic on ExpInitializer, see if it represents entire struct ts
*/
bool representsStruct(ExpInitializer ei, TypeStruct ts)
{
if (needInterpret)
sc = sc.startCTFE();
ei.exp = ei.exp.expressionSemantic(sc);
ei.exp = resolveProperties(sc, ei.exp);
if (needInterpret)
sc = sc.endCTFE();
return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct
}
/* If { } are omitted from substructs, use recursion to reconstruct where
* brackets go
* Params:
* ts = substruct to initialize
* index = index into ci.initializer, updated
* Returns: struct initializer for this substruct
*/
Initializer subStruct()(TypeStruct ts, ref size_t index)
{
//printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);
auto si = new StructInitializer(ci.loc);
StructDeclaration sd = ts.sym;
sd.size(ci.loc);
if (sd.sizeok != Sizeok.done)
{
errors = true;
index = ci.initializerList.length;
return err();
}
const nfields = sd.nonHiddenFields();
auto elements = new Expressions(nfields);
auto elems = (*elements)[];
foreach (ref elem; elems)
elem = null;
const nfields = sd.fields.length;
FieldLoop:
for (size_t fieldi = 0; fieldi < nfields; ++fieldi)
foreach (fieldi; 0 .. nfields)
{
if (i == dil.length)
break;
auto di = dil[i];
if (di.designatorList)
if (index >= ci.initializerList.length)
break; // ran out of initializers
auto di = ci.initializerList[index];
if (di.designatorList && fieldi != 0)
break; // back to top level
else
{
error(ci.loc, "C designator-list not supported yet");
errors = true;
break;
}
VarDeclaration vd = sd.fields[fieldi];
// Check for overlapping initializations (can happen with unions)
foreach (k, v2; sd.fields[0 .. nfields])
{
if (vd.isOverlappedWith(v2) && elems[k])
VarDeclaration field;
while (1) // skip field if it overlaps with previously seen fields
{
continue FieldLoop; // skip it
field = sd.fields[fieldi];
++fieldi;
if (!overlaps(field, sd.fields[], si))
break;
if (fieldi == nfields)
break;
}
auto tn = field.type.toBasetype();
auto tnsa = tn.isTypeSArray();
auto tns = tn.isTypeStruct();
auto ix = di.initializer;
if (tnsa && ix.isExpInitializer())
{
ExpInitializer ei = ix.isExpInitializer();
if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
si.addInit(field.ident, ei);
++index;
}
else
si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
}
else if (tns && ix.isExpInitializer())
{
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
{
si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
else // field initializers for struct
si.addInit(field.ident, subStruct(tns, index)); // the first field
}
else
{
si.addInit(field.ident, ix);
++index;
}
}
++i;
// Convert initializer to Expression `ex`
assert(sc);
auto tm = vd.type.addMod(ts.mod);
auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
auto ex = iz.initializerToExpression(null, true);
if (ex.op == EXP.error)
{
errors = true;
continue;
}
elems[fieldi] = ex;
}
if (errors)
return err();
//printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
return si;
}
// Make a StructLiteralExp out of elements[]
Type tx = ts;
auto sle = new StructLiteralExp(ci.loc, sd, elements, tx);
if (!sd.fill(ci.loc, elements, false))
return err();
sle.type = tx;
auto ie = new ExpInitializer(ci.loc, sle);
return ie.initializerSemantic(sc, tx, needInterpret);
/* If { } are omitted from subarrays, use recursion to reconstruct where
* brackets go
* Params:
* tsa = subarray to initialize
* index = index into ci.initializer, updated
* Returns: array initializer for this subarray
*/
Initializer subArray(TypeSArray tsa, ref size_t index)
{
//printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index);
if (tsa.isIncomplete())
{
// C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
assert(0); // should have been detected by parser
}
auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
auto ai = new ArrayInitializer(ci.loc);
ai.isCarray = true;
foreach (n; 0 .. cast(size_t)tsa.dim.toInteger())
{
if (index >= ci.initializerList.length)
break; // ran out of initializers
auto di = ci.initializerList[index];
if (di.designatorList)
break; // back to top level
else if (tnsa && di.initializer.isExpInitializer())
{
ExpInitializer ei = di.initializer.isExpInitializer();
if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
ai.addInit(null, ei);
++index;
}
else
ai.addInit(null, subArray(tnsa, index));
}
else
{
ai.addInit(null, di.initializer);
++index;
}
}
//printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index);
return ai;
}
if (auto ts = t.isTypeStruct())
{
auto ei = structs(ts);
if (errors)
return err();
if (i < dil.length)
auto si = new StructInitializer(ci.loc);
StructDeclaration sd = ts.sym;
sd.size(ci.loc); // run semantic() on sd to get fields
if (sd.sizeok != Sizeok.done)
{
error(ci.loc, "%d extra initializer(s) for `struct %s`", cast(int)(dil.length - i), ts.toChars());
return err();
}
return ei;
}
const nfields = sd.fields.length;
auto tsa = t.isTypeSArray();
if (!tsa)
{
/* Not an array. See if it is `{ exp }` which can be
* converted to an ExpInitializer
*/
if (ExpInitializer ei = isBraceExpression())
size_t fieldi = 0;
for (size_t index = 0; index < ci.initializerList.length; )
{
return ei.initializerSemantic(sc, t, needInterpret);
}
error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars());
return err();
}
/* If it's an array of integral being initialized by `{ string }`
* replace with `string`
*/
auto tn = t.nextOf();
if (tn.isintegral())
{
if (ExpInitializer ei = isBraceExpression())
{
if (ei.exp.isStringExp())
return ei.initializerSemantic(sc, t, needInterpret);
}
}
/* Support recursion to handle un-braced array initializers
* Params:
* t = element type
* dim = max number of elements
* simple = true if array of simple elements
* Returns:
* # of elements in array
*/
size_t array(Type t, size_t dim, ref bool simple)
{
//printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
auto tn = t.nextOf().toBasetype();
auto tnsa = tn.isTypeSArray();
if (tnsa && tnsa.isIncomplete())
{
// C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
error(ci.loc, "incomplete element type `%s` not allowed", tnsa.toChars());
errors = true;
return 1;
}
if (i == dil.length)
return 0;
size_t n;
const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
/* Run initializerSemantic on a single element.
*/
Initializer elem(Initializer ie)
{
++i;
auto tnx = tn; // in case initializerSemantic tries to change it
ie = ie.initializerSemantic(sc, tnx, needInterpret);
if (ie.isErrorInitializer())
errors = true;
assert(tnx == tn); // sub-types should not be modified
return ie;
}
foreach (j; 0 .. dim)
{
auto di = dil[i];
if (di.designatorList)
auto di = ci.initializerList[index];
auto dlist = di.designatorList;
if (dlist)
{
error(ci.loc, "C designator-list not supported yet");
errors = true;
break;
}
if (tnsa && di.initializer.isExpInitializer())
{
// no braces enclosing array initializer, so recurse
array(tnsa, nelems, simple);
}
else if (auto tns = tn.isTypeStruct())
{
if (auto ei = di.initializer.isExpInitializer())
const length = (*dlist).length;
if (length == 0 || !(*dlist)[0].ident)
{
// no braces enclosing struct initializer
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (needInterpret)
sc = sc.startCTFE();
ei.exp = ei.exp.expressionSemantic(sc);
ei.exp = resolveProperties(sc, ei.exp);
if (needInterpret)
sc = sc.endCTFE();
if (ei.exp.implicitConvTo(tn))
di.initializer = elem(di.initializer); // the whole struct
else
error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", ci.toChars());
return err();
}
if (length > 1)
{
error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", ci.toChars());
return err();
}
auto id = (*dlist)[0].ident;
foreach (k, f; sd.fields[]) // linear search for now
{
if (f.ident == id)
{
simple = false;
dil[n].initializer = structs(tns); // the first field
fieldi = k;
si.addInit(id, di.initializer);
++fieldi;
++index;
break;
}
}
else
dil[n].initializer = elem(di.initializer);
}
else
{
di.initializer = elem(di.initializer);
if (fieldi == nfields)
break;
VarDeclaration field;
while (1) // skip field if it overlaps with previously seen fields
{
field = sd.fields[fieldi];
++fieldi;
if (!overlaps(field, sd.fields[], si))
break;
if (fieldi == nfields)
break;
}
auto tn = field.type.toBasetype();
auto tnsa = tn.isTypeSArray();
auto tns = tn.isTypeStruct();
auto ix = di.initializer;
if (tnsa && ix.isExpInitializer())
{
ExpInitializer ei = ix.isExpInitializer();
if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
si.addInit(field.ident, ei);
++index;
}
else
si.addInit(field.ident, subArray(tnsa, index));
}
else if (tns && ix.isExpInitializer())
{
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
{
si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
else // field initializers for struct
si.addInit(field.ident, subStruct(tns, index)); // the first field
}
else
{
si.addInit(field.ident, di.initializer);
++index;
}
}
++n;
if (i == dil.length)
break;
}
//printf(" n: %d i: %d\n", cast(int)n, cast(int)i);
return n;
return initializerSemantic(si, sc, t, needInterpret);
}
size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
bool simple = true;
auto newdim = array(t, dim, simple);
if (errors)
return err();
if (tsa.isIncomplete()) // array of unknown length
else if (auto ta = t.isTypeSArray())
{
// Change to array of known length
tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, newdim, Type.tsize_t));
tx = tsa; // rewrite caller's type
ci.type = tsa; // remember for later passes
}
const uinteger_t edim = tsa.dim.toInteger();
if (i < dil.length)
{
error(ci.loc, "%d extra initializer(s) for static array length of %d", cast(int)(dil.length - i), cast(int)edim);
return err();
}
auto tn = t.nextOf().toBasetype(); // element type of array
const sz = tn.size(); // element size
if (sz == SIZE_INVALID)
return err();
bool overflow;
const max = mulu(edim, sz, overflow);
if (overflow || max >= amax)
{
error(ci.loc, "array dimension %llu exceeds max of %llu", ulong(edim), ulong(amax / sz));
return err();
}
/* If an array of simple elements, replace with an ArrayInitializer
*/
auto tnb = tn.toBasetype();
if (!tnb.isTypeSArray() && (!tnb.isTypeStruct() || simple))
{
auto ai = new ArrayInitializer(ci.loc);
ai.dim = cast(uint) dil.length;
ai.index.setDim(dil.length);
ai.value.setDim(dil.length);
foreach (const j; 0 .. dil.length)
/* If it's an array of integral being initialized by `{ string }`
* replace with `string`
*/
if (tn.isintegral())
{
ai.index[j] = null;
ai.value[j] = dil[j].initializer;
if (ExpInitializer ei = isBraceExpression())
{
if (ei.exp.isStringExp())
return ei.initializerSemantic(sc, t, needInterpret);
}
}
auto ty = tx;
return ai.initializerSemantic(sc, ty, needInterpret);
}
if (newdim < ci.initializerList.length && tnb.isTypeStruct())
auto tnsa = tn.isTypeSArray(); // array of array
auto tns = tn.isTypeStruct(); // array of struct
auto ai = new ArrayInitializer(ci.loc);
ai.isCarray = true;
for (size_t index = 0; index < ci.initializerList.length; )
{
auto di = ci.initializerList[index];
if (auto dlist = di.designatorList)
{
const length = (*dlist).length;
if (length == 0 || !(*dlist)[0].exp)
{
error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", ci.toChars());
return err();
}
if (length > 1)
{
error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", ci.toChars());
return err();
}
//printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
auto ix = di.initializer;
if (tnsa && ix.isExpInitializer())
{
// Wrap initializer in [ ]
auto ain = new ArrayInitializer(ci.loc);
ain.addInit(null, di.initializer);
ix = ain;
ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
else if (tns && ix.isExpInitializer())
{
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
{
ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
else // field initializers for struct
ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field
}
else
{
ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
}
else if (tnsa && di.initializer.isExpInitializer())
{
ExpInitializer ei = di.initializer.isExpInitializer();
if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
ai.addInit(null, ei);
++index;
}
else
ai.addInit(null, subArray(tnsa, index));
}
else if (tns && di.initializer.isExpInitializer())
{
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct
{
ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
++index;
}
else // field initializers for struct
ai.addInit(null, subStruct(tns, index)); // the first field
}
else
{
ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
++index;
}
}
return initializerSemantic(ai, sc, tx, needInterpret);
}
else if (ExpInitializer ei = isBraceExpression())
return visitExp(ei);
else
{
// https://issues.dlang.org/show_bug.cgi?id=22375
// initializerList can be bigger than the number of actual elements
// to initialize for array of structs because it is not required
// for values to have proper bracing.
// i.e: These are all valid initializers for `struct{int a,b;}[3]`:
// {1,2,3,4}, {{1,2},3,4}, {1,2,{3,4}}, {{1,2},{3,4}}
// In all examples above, the new length of the initializer list
// has been shortened from four elements to two. This is important,
// because `dil` is written back to directly, making the lowered
// initializer `{{1,2},{3,4}}` and not `{{1,2},{3,4},3,4}`.
ci.initializerList.length = newdim;
assert(0);
}
return ci;
}
final switch (init.kind)

View file

@ -2582,8 +2582,13 @@ class Lexer
{
/* C11 6.4.4.2 doesn't actually care if it is not representable if it is not hex
*/
const char* suffix = (result == TOK.float32Literal || result == TOK.imaginary32Literal) ? "f" : "";
error(scanloc, "number `%s%s` is not representable", sbufptr, suffix);
const char* suffix = result == TOK.float32Literal ? "f" : result == TOK.float80Literal ? "L" : "";
const char* type = [TOK.float32Literal: "`float`".ptr,
TOK.float64Literal: "`double`".ptr,
TOK.float80Literal: "`real` for the current target".ptr][result];
error(scanloc, "number `%s%s` is not representable as a %s", sbufptr, suffix, type);
const char* extra = result == TOK.float64Literal ? "`real` literals can be written using the `L` suffix. " : "";
errorSupplemental(scanloc, "%shttps://dlang.org/spec/lex.html#floatliteral", extra);
}
debug
{

View file

@ -37,7 +37,7 @@ public:
const char *kind() const override;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
Package *isPackage() override final { return this; }

View file

@ -936,7 +936,7 @@ extern (C++) abstract class Type : ASTNode
else
{
// If `typeSemantic` succeeded, there may have been deprecations that
// were gagged due the the `startGagging` above. Run again to display
// were gagged due the `startGagging` above. Run again to display
// those deprecations. https://issues.dlang.org/show_bug.cgi?id=19107
if (global.gaggedWarnings > 0)
typeSemantic(tcopy, loc, sc);
@ -4656,7 +4656,7 @@ extern (C++) final class TypeFunction : TypeNext
// suppress early exit if an error message is wanted,
// so we can check any matching args are valid
if (!pMessage)
goto Nomatch;
return MATCH.nomatch;
}
// too many args; no match
match = MATCH.convert; // match ... with a "conversion" match level
@ -4669,7 +4669,7 @@ extern (C++) final class TypeFunction : TypeNext
buf.printf("too few arguments, expected `%d`, got `%d`", cast(int)nparams, cast(int)nargs);
if (pMessage)
*pMessage = buf.extractChars();
goto Nomatch;
return MATCH.nomatch;
}
foreach (u, p; parameterList)
@ -4710,226 +4710,16 @@ extern (C++) final class TypeFunction : TypeNext
MATCH m;
assert(p);
if (u >= nargs)
{
if (p.defaultArg)
continue;
// try typesafe variadics
goto L1;
}
// One or more arguments remain
if (u < nargs)
{
Expression arg = args[u];
assert(arg);
//printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
Type targ = arg.type;
Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
m = MATCH.convert;
else
{
//printf("%s of type %s implicitConvTo %s\n", arg.toChars(), targ.toChars(), tprm.toChars());
if (flag)
{
// for partial ordering, value is an irrelevant mockup, just look at the type
m = targ.implicitConvTo(tprm);
}
else
{
const isRef = p.isReference();
StructDeclaration argStruct, prmStruct;
// first look for a copy constructor
if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct)
{
// if the argument and the parameter are of the same unqualified struct type
argStruct = (cast(TypeStruct)targ).sym;
prmStruct = (cast(TypeStruct)tprm).sym;
}
// check if the copy constructor may be called to copy the argument
if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor)
{
/* this is done by seeing if a call to the copy constructor can be made:
*
* typeof(tprm) __copytmp;
* copytmp.__copyCtor(arg);
*/
auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null);
tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe;
tmp.dsymbolSemantic(sc);
Expression ve = new VarExp(arg.loc, tmp);
Expression e = new DotIdExp(arg.loc, ve, Id.ctor);
e = new CallExp(arg.loc, e, arg);
//printf("e = %s\n", e.toChars());
if(.trySemantic(e, sc))
m = MATCH.exact;
else
{
if (pMessage)
{
/* https://issues.dlang.org/show_bug.cgi?id=22202
*
* If a function was deduced by semantic on the CallExp,
* it means that resolveFuncCall completed succesfully.
* Therefore, there exists a callable copy constructor,
* however, it cannot be called because scope constraints
* such as purity, safety or nogc.
*/
OutBuffer buf;
auto callExp = e.isCallExp();
if (auto f = callExp.f)
{
char[] s;
if (!f.isPure && sc.func.setImpure())
s ~= "pure ";
if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe())
s ~= "@safe ";
if (!f.isNogc && sc.func.setGC())
s ~= "nogc ";
if (s)
{
s[$-1] = '\0';
buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
}
else if (f.isGenerated() && f.isDisabled())
{
/* https://issues.dlang.org/show_bug.cgi?id=23097
* Compiler generated copy constructor failed.
*/
buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable",
argStruct.toChars());
}
else
{
/* Although a copy constructor may exist, no suitable match was found.
* i.e: `inout` constructor creates `const` object, not mutable.
* Fallback to using the original generic error before bugzilla 22202.
*/
goto Lnocpctor;
}
}
else
{
Lnocpctor:
buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies",
argStruct.toChars(), targ.toChars(), tprm.toChars());
}
*pMessage = buf.extractChars();
}
m = MATCH.nomatch;
goto Nomatch;
}
}
else
{
import dmd.dcast : cimplicitConvTo;
m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
}
}
//printf("match %d\n", m);
}
// Non-lvalues do not match ref or out parameters
if (p.isReference())
{
// https://issues.dlang.org/show_bug.cgi?id=13783
// Don't use toBasetype() to handle enum types.
Type ta = targ;
Type tp = tprm;
//printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars());
if (m && !arg.isLvalue())
{
if (p.storageClass & STC.out_)
{
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
if (arg.op == EXP.string_ && tp.ty == Tsarray)
{
if (ta.ty != Tsarray)
{
Type tn = tp.nextOf().castMod(ta.nextOf().mod);
dinteger_t dim = (cast(StringExp)arg).len;
ta = tn.sarrayOf(dim);
}
}
else if (arg.op == EXP.slice && tp.ty == Tsarray)
{
// Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
if (ta.ty != Tsarray)
{
Type tn = ta.nextOf();
dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
ta = tn.sarrayOf(dim);
}
}
else if ((p.storageClass & STC.in_) && global.params.previewIn)
{
// Allow converting a literal to an `in` which is `ref`
if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray)
{
Type tn = tp.nextOf();
dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
ta = tn.sarrayOf(dim);
}
// Need to make this a rvalue through a temporary
m = MATCH.convert;
}
else if (global.params.rvalueRefParam != FeatureState.enabled ||
p.storageClass & STC.out_ ||
!arg.type.isCopyable()) // can't copy to temp for ref parameter
{
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
else
{
/* in functionParameters() we'll convert this
* rvalue into a temporary
*/
m = MATCH.convert;
}
}
/* If the match is not already perfect or if the arg
is not a lvalue then try the `alias this` chain
see https://issues.dlang.org/show_bug.cgi?id=15674
and https://issues.dlang.org/show_bug.cgi?id=21905
*/
if (ta != tp || !arg.isLvalue())
{
Type firsttab = ta.toBasetype();
while (1)
{
Type tab = ta.toBasetype();
Type tat = tab.aliasthisOf();
if (!tat || !tat.implicitConvTo(tprm))
break;
if (tat == tab || tat == firsttab)
break;
ta = tat;
}
}
/* A ref variable should work like a head-const reference.
* e.g. disallows:
* ref T <- an lvalue of const(T) argument
* ref T[dim] <- an lvalue of const(T[dim]) argument
*/
if (!ta.constConv(tp))
{
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
}
m = argumentMatchParameter(this, p, arg, wildmatch, flag, sc, pMessage);
}
else if (p.defaultArg)
continue;
/* prefer matching the element type rather than the array
* type when more arguments are present with T[]...
@ -4943,100 +4733,33 @@ extern (C++) final class TypeFunction : TypeNext
L1:
if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param
{
Type tb = p.type.toBasetype();
TypeSArray tsa;
dinteger_t sz;
switch (tb.ty)
{
case Tsarray:
tsa = cast(TypeSArray)tb;
sz = tsa.dim.toInteger();
if (sz != nargs - u)
{
if (pMessage)
// Windows (Vista) OutBuffer.vprintf issue? 2nd argument always zero
//*pMessage = getMatchError("expected %d variadic argument(s), not %d", sz, nargs - u);
if (!global.gag || global.params.showGaggedErrors)
{
OutBuffer buf;
buf.printf("expected %llu variadic argument(s)", sz);
buf.printf(", not %zu", nargs - u);
*pMessage = buf.extractChars();
}
goto Nomatch;
}
goto case Tarray;
case Tarray:
{
TypeArray ta = cast(TypeArray)tb;
foreach (arg; args[u .. nargs])
{
assert(arg);
/* If lazy array of delegates,
* convert arg(s) to delegate(s)
*/
Type tret = p.isLazyArray();
if (tret)
{
if (ta.next.equals(arg.type))
m = MATCH.exact;
else if (tret.toBasetype().ty == Tvoid)
m = MATCH.convert;
else
{
m = arg.implicitConvTo(tret);
if (m == MATCH.nomatch)
m = arg.implicitConvTo(ta.next);
}
}
else
m = arg.implicitConvTo(ta.next);
if (m == MATCH.nomatch)
{
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
if (m < match)
match = m;
}
goto Ldone;
}
case Tclass:
// Should see if there's a constructor match?
// Or just leave it ambiguous?
goto Ldone;
default:
break;
}
auto trailingArgs = args[u .. $];
if (auto vmatch = matchTypeSafeVarArgs(this, p, trailingArgs, pMessage))
return vmatch < match ? vmatch : match;
// Error message was already generated in `matchTypeSafeVarArgs`
return MATCH.nomatch;
}
if (pMessage && u < nargs)
*pMessage = getParamError(args[u], p);
else if (pMessage)
if (pMessage && u >= nargs)
*pMessage = getMatchError("missing argument for parameter #%d: `%s`",
u + 1, parameterToChars(p, this, false));
goto Nomatch;
// If an error happened previously, `pMessage` was already filled
else if (pMessage && !*pMessage)
*pMessage = getParamError(args[u], p);
return MATCH.nomatch;
}
if (m < match)
match = m; // pick worst match
}
Ldone:
if (pMessage && !parameterList.varargs && nargs > nparams)
{
// all parameters had a match, but there are surplus args
*pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs);
goto Nomatch;
return MATCH.nomatch;
}
//printf("match = %d\n", match);
return match;
Nomatch:
//printf("no match\n");
return MATCH.nomatch;
}
/+
@ -6194,6 +5917,11 @@ extern (C++) final class TypeClass : Type
if (t && t.ty == Tclass)
{
ClassDeclaration cd = (cast(TypeClass)t).sym;
if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete())
cd.dsymbolSemantic(null);
if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
sym.dsymbolSemantic(null);
if (sym.isBaseOf(cd, poffset))
return true;
}
@ -6355,10 +6083,9 @@ extern (C++) final class TypeTuple : Type
extern (D) this(Expressions* exps)
{
super(Ttuple);
auto arguments = new Parameters();
auto arguments = new Parameters(exps ? exps.dim : 0);
if (exps)
{
arguments.setDim(exps.dim);
for (size_t i = 0; i < exps.dim; i++)
{
Expression e = (*exps)[i];
@ -7330,3 +7057,325 @@ const(char)* toChars(ScopeRef sr) pure nothrow @nogc @safe
return names[sr];
}
}
/**
* Used by `callMatch` to check if the copy constructor may be called to
* copy the argument
*
* This is done by seeing if a call to the copy constructor can be made:
* ```
* typeof(tprm) __copytmp;
* copytmp.__copyCtor(arg);
* ```
*/
private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
Expression arg, Type tprm, Scope* sc, const(char)** pMessage)
{
auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null);
tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe;
tmp.dsymbolSemantic(sc);
Expression ve = new VarExp(arg.loc, tmp);
Expression e = new DotIdExp(arg.loc, ve, Id.ctor);
e = new CallExp(arg.loc, e, arg);
//printf("e = %s\n", e.toChars());
if (.trySemantic(e, sc))
return true;
if (pMessage)
{
/* https://issues.dlang.org/show_bug.cgi?id=22202
*
* If a function was deduced by semantic on the CallExp,
* it means that resolveFuncCall completed succesfully.
* Therefore, there exists a callable copy constructor,
* however, it cannot be called because scope constraints
* such as purity, safety or nogc.
*/
OutBuffer buf;
auto callExp = e.isCallExp();
if (auto f = callExp.f)
{
char[] s;
if (!f.isPure && sc.func.setImpure())
s ~= "pure ";
if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe())
s ~= "@safe ";
if (!f.isNogc && sc.func.setGC())
s ~= "nogc ";
if (s)
{
s[$-1] = '\0';
buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
}
else if (f.isGenerated() && f.isDisabled())
{
/* https://issues.dlang.org/show_bug.cgi?id=23097
* Compiler generated copy constructor failed.
*/
buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable",
argStruct.toChars());
}
else
{
/* Although a copy constructor may exist, no suitable match was found.
* i.e: `inout` constructor creates `const` object, not mutable.
* Fallback to using the original generic error before bugzilla 22202.
*/
goto Lnocpctor;
}
}
else
{
Lnocpctor:
buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies",
argStruct.toChars(), arg.type.toChars(), tprm.toChars());
}
*pMessage = buf.extractChars();
}
return false;
}
/**
* Match a single parameter to an argument.
*
* This function is called by `TypeFunction.callMatch` while iterating over
* the list of parameter. Here we check if `arg` is a match for `p`,
* which is mostly about checking if `arg.type` converts to `p`'s type
* and some check about value reference.
*
* Params:
* tf = The `TypeFunction`, only used for error reporting
* p = The parameter of `tf` being matched
* arg = Argument being passed (bound) to `p`
* wildmatch = Wild (`inout`) matching level, derived from the full argument list
* flag = A non-zero value means we're doing a partial ordering check
* (no value semantic check)
* sc = Scope we are in
* pMessage = A buffer to write the error in, or `null`
*
* Returns: Whether `trailingArgs` match `p`.
*/
private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p,
Expression arg, ubyte wildmatch, int flag, Scope* sc, const(char)** pMessage)
{
//printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
MATCH m;
Type targ = arg.type;
Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
m = MATCH.convert;
else if (flag)
{
// for partial ordering, value is an irrelevant mockup, just look at the type
m = targ.implicitConvTo(tprm);
}
else
{
const isRef = p.isReference();
StructDeclaration argStruct, prmStruct;
// first look for a copy constructor
if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct)
{
// if the argument and the parameter are of the same unqualified struct type
argStruct = (cast(TypeStruct)targ).sym;
prmStruct = (cast(TypeStruct)tprm).sym;
}
// check if the copy constructor may be called to copy the argument
if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor)
{
if (!isCopyConstructorCallable(argStruct, arg, tprm, sc, pMessage))
return MATCH.nomatch;
m = MATCH.exact;
}
else
{
import dmd.dcast : cimplicitConvTo;
m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
}
}
// Non-lvalues do not match ref or out parameters
if (p.isReference())
{
// https://issues.dlang.org/show_bug.cgi?id=13783
// Don't use toBasetype() to handle enum types.
Type ta = targ;
Type tp = tprm;
//printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars());
if (m && !arg.isLvalue())
{
if (p.storageClass & STC.out_)
{
if (pMessage) *pMessage = tf.getParamError(arg, p);
return MATCH.nomatch;
}
if (arg.op == EXP.string_ && tp.ty == Tsarray)
{
if (ta.ty != Tsarray)
{
Type tn = tp.nextOf().castMod(ta.nextOf().mod);
dinteger_t dim = (cast(StringExp)arg).len;
ta = tn.sarrayOf(dim);
}
}
else if (arg.op == EXP.slice && tp.ty == Tsarray)
{
// Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
if (ta.ty != Tsarray)
{
Type tn = ta.nextOf();
dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
ta = tn.sarrayOf(dim);
}
}
else if ((p.storageClass & STC.in_) && global.params.previewIn)
{
// Allow converting a literal to an `in` which is `ref`
if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray)
{
Type tn = tp.nextOf();
dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger();
ta = tn.sarrayOf(dim);
}
// Need to make this a rvalue through a temporary
m = MATCH.convert;
}
else if (global.params.rvalueRefParam != FeatureState.enabled ||
p.storageClass & STC.out_ ||
!arg.type.isCopyable()) // can't copy to temp for ref parameter
{
if (pMessage) *pMessage = tf.getParamError(arg, p);
return MATCH.nomatch;
}
else
{
/* in functionParameters() we'll convert this
* rvalue into a temporary
*/
m = MATCH.convert;
}
}
/* If the match is not already perfect or if the arg
is not a lvalue then try the `alias this` chain
see https://issues.dlang.org/show_bug.cgi?id=15674
and https://issues.dlang.org/show_bug.cgi?id=21905
*/
if (ta != tp || !arg.isLvalue())
{
Type firsttab = ta.toBasetype();
while (1)
{
Type tab = ta.toBasetype();
Type tat = tab.aliasthisOf();
if (!tat || !tat.implicitConvTo(tprm))
break;
if (tat == tab || tat == firsttab)
break;
ta = tat;
}
}
/* A ref variable should work like a head-const reference.
* e.g. disallows:
* ref T <- an lvalue of const(T) argument
* ref T[dim] <- an lvalue of const(T[dim]) argument
*/
if (!ta.constConv(tp))
{
if (pMessage) *pMessage = tf.getParamError(arg, p);
return MATCH.nomatch;
}
}
return m;
}
/**
* Match the remaining arguments `trailingArgs` with parameter `p`.
*
* Assume we already checked that `p` is the last parameter of `tf`,
* and we want to know whether the arguments would match `p`.
*
* Params:
* tf = The `TypeFunction`, only used for error reporting
* p = The last parameter of `tf` which is variadic
* trailingArgs = The remaining arguments that should match `p`
* pMessage = A buffer to write the error in, or `null`
*
* Returns: Whether `trailingArgs` match `p`.
*/
private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p,
Expression[] trailingArgs, const(char)** pMessage)
{
Type tb = p.type.toBasetype();
switch (tb.ty)
{
case Tsarray:
TypeSArray tsa = cast(TypeSArray)tb;
dinteger_t sz = tsa.dim.toInteger();
if (sz != trailingArgs.length)
{
if (pMessage)
*pMessage = tf.getMatchError("expected %llu variadic argument(s), not %zu",
sz, trailingArgs.length);
return MATCH.nomatch;
}
goto case Tarray;
case Tarray:
{
MATCH match = MATCH.exact;
TypeArray ta = cast(TypeArray)tb;
foreach (arg; trailingArgs)
{
MATCH m;
assert(arg);
/* If lazy array of delegates,
* convert arg(s) to delegate(s)
*/
Type tret = p.isLazyArray();
if (tret)
{
if (ta.next.equals(arg.type))
m = MATCH.exact;
else if (tret.toBasetype().ty == Tvoid)
m = MATCH.convert;
else
{
m = arg.implicitConvTo(tret);
if (m == MATCH.nomatch)
m = arg.implicitConvTo(ta.next);
}
}
else
m = arg.implicitConvTo(ta.next);
if (m == MATCH.nomatch)
{
if (pMessage) *pMessage = tf.getParamError(arg, p);
return MATCH.nomatch;
}
if (m < match)
match = m;
}
return match;
}
case Tclass:
// We leave it up to the actual constructor call to do the matching.
return MATCH.exact;
default:
// We can have things as `foo(int[int] wat...)` but they only match
// with an associative array proper.
if (pMessage && trailingArgs.length) *pMessage = tf.getParamError(trailingArgs[0], p);
return MATCH.nomatch;
}
}

View file

@ -221,7 +221,7 @@ public:
virtual const char *kind();
Type *copy() const;
virtual Type *syntaxCopy();
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
bool equivalent(Type *t);
// kludge for template.isType()
DYNCAST dyncast() const override final { return DYNCAST_TYPE; }
@ -877,7 +877,7 @@ public:
static TypeTuple *create(Type *t1, Type *t2);
const char *kind() override;
TypeTuple *syntaxCopy() override;
bool equals(const RootObject *o) const override;
bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};

View file

@ -1247,13 +1247,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
args2[0] = e.e2;
expandTuples(&args2);
MatchAccumulator m;
if (s)
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
return ErrorExp.get();
}
if (m.count > 1)
{

View file

@ -2756,7 +2756,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
auto parameters = new AST.Parameters();
VarArg varargs = VarArg.none;
int hasdefault = 0;
StorageClass varargsStc;
// Attributes allowed for ...
@ -2921,27 +2920,23 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
//if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_)))
//error("scope cannot be ref or out");
if (tpl && token.value == TOK.identifier)
const tv = peekNext();
if (tpl && token.value == TOK.identifier &&
(tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot))
{
const tv = peekNext();
if (tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot)
{
Identifier id = Identifier.generateId("__T");
const loc = token.loc;
at = new AST.TypeIdentifier(loc, id);
if (!*tpl)
*tpl = new AST.TemplateParameters();
AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null);
(*tpl).push(tp);
Identifier id = Identifier.generateId("__T");
const loc = token.loc;
at = new AST.TypeIdentifier(loc, id);
if (!*tpl)
*tpl = new AST.TemplateParameters();
AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null);
(*tpl).push(tp);
ai = token.ident;
nextToken();
}
else goto _else;
ai = token.ident;
nextToken();
}
else
{
_else:
at = parseType(&ai);
}
ae = null;
@ -2949,12 +2944,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
nextToken();
ae = parseDefaultInitExp();
hasdefault = 1;
}
else
{
if (hasdefault)
error("default argument expected for `%s`", ai ? ai.toChars() : at.toChars());
}
auto param = new AST.Parameter(storageClass | STC.parameter, at, ai, ae, null);
if (udas)
@ -4484,7 +4473,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
const loc = token.loc;
Identifier ident;
auto t = parseDeclarator(ts, alt, &ident, &tpl, storage_class, &disable, &udas);
assert(t);
if (!tfirst)
@ -4868,6 +4856,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
token.value == TOK.identifier && peekNext() == TOK.goesTo ||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
skipAttributes(peekPastParen(peek(&token)), &tk) &&
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
token.value == TOK.auto_ && peekNext() == TOK.ref_ &&
peekNext2() == TOK.leftParenthesis &&
skipAttributes(peekPastParen(peek(peek(&token))), &tk) &&
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
)
{
@ -4879,6 +4871,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// identifier => expression
// ref (parameters) { statements... }
// ref (parameters) => expression
// auto ref (parameters) { statements... }
// auto ref (parameters) => expression
s = parseFunctionLiteral();
@ -5006,7 +5000,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.delegate_:
save = token.value;
nextToken();
if (token.value == TOK.ref_)
if (token.value == TOK.auto_)
{
nextToken();
if (token.value == TOK.ref_)
{
// function auto ref (parameters) { statements... }
// delegate auto ref (parameters) { statements... }
stc = STC.auto_ | STC.ref_;
nextToken();
}
else
error("`auto` can only be used as part of `auto ref` for function literal return values");
}
else if (token.value == TOK.ref_)
{
// function ref (parameters) { statements... }
// delegate ref (parameters) { statements... }
@ -5034,6 +5041,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
goto case TOK.leftParenthesis;
case TOK.auto_:
{
nextToken();
if (token.value == TOK.ref_)
{
// auto ref (parameters) => expression
// auto ref (parameters) { statements... }
stc = STC.auto_ | STC.ref_;
nextToken();
}
else
error("`auto` can only be used as part of `auto ref` for function literal return values");
goto case TOK.leftParenthesis;
}
case TOK.ref_:
{
// ref (parameters) => expression
@ -5086,7 +5107,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
auto tf = new AST.TypeFunction(parameterList, tret, linkage, stc);
tf = cast(AST.TypeFunction)tf.addSTC(stc);
auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null);
auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null, null, stc & STC.auto_);
if (token.value == TOK.goesTo)
{
@ -5209,7 +5230,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
else
{
f.frequires.push(parseStatement(ParseStatementFlags.curly | ParseStatementFlags.scope_));
auto ret = parseStatement(ParseStatementFlags.curly | ParseStatementFlags.scope_);
assert(ret);
f.frequires.push(ret);
requireDo = true;
}
goto L1;
@ -6550,7 +6573,7 @@ LagainStc:
nextToken();
if (token.value == TOK.semicolon)
nextToken();
s = null;
s = new AST.ErrorStatement;
break;
}
if (pEndloc)
@ -8394,6 +8417,22 @@ LagainStc:
e = parseNewExp(null);
break;
case TOK.auto_:
{
if (peekNext() == TOK.ref_ && peekNext2() == TOK.leftParenthesis)
{
Token* tk = peekPastParen(peek(peek(&token)));
if (skipAttributes(tk, &tk) && (tk.value == TOK.goesTo || tk.value == TOK.leftCurly))
{
// auto ref (arguments) => expression
// auto ref (arguments) { statements... }
goto case_delegate;
}
}
nextToken();
error("found `%s` when expecting `ref` and function literal following `auto`", token.toChars());
goto Lerr;
}
case TOK.ref_:
{
if (peekNext() == TOK.leftParenthesis)
@ -8630,7 +8669,7 @@ LagainStc:
if (token.value != TOK.identifier)
{
error("identifier expected following `(type)`.");
return null;
return AST.ErrorExp.get();
}
e = new AST.DotIdExp(loc, new AST.TypeExp(loc, t), token.ident);
nextToken();
@ -8749,7 +8788,8 @@ LagainStc:
if (peekNext() != TOK.identifier && peekNext() != TOK.new_)
{
error("identifier or new keyword expected following `(...)`.");
return null;
nextToken();
return AST.ErrorExp.get();
}
e = new AST.TypeExp(loc, t);
e.parens = true;

View file

@ -39,7 +39,7 @@ class RootObject
public:
RootObject() { }
virtual bool equals(const RootObject *o) const;
virtual bool equals(const RootObject * const o) const;
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.

View file

@ -167,11 +167,18 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc = sc.push(tmix.argsym);
sc = sc.push(tmix);
uint olderrors = global.errors;
for (size_t i = 0; i < tmix.members.dim; i++)
{
Dsymbol s = (*tmix.members)[i];
s.semantic3(sc);
}
if (global.errors != olderrors)
errorSupplemental(tmix.loc, "parent scope from here: `mixin %s`", tmix.toChars());
sc = sc.pop();
sc.pop();
}
@ -969,6 +976,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
if (freq)
{
/* frequire is composed of the [in] contracts
@ -980,10 +988,22 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.require;
// BUG: need to error if accessing out parameters
// BUG: need to disallow returns and throws
// BUG: need to disallow returns
// BUG: verify that all in and ref parameters are read
freq = freq.statementSemantic(sc2);
freq.blockExit(funcdecl, false);
// @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
const blockExit = freq.blockExit(funcdecl, false);
if (blockExit & BE.throw_)
{
if (isnothrow)
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, can be made an error in 2.111
deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
funcdecl.toPrettyChars());
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
f.isnothrow = false;
}
funcdecl.flags &= ~FUNCFLAG.noEH;
@ -992,6 +1012,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (global.params.useIn == CHECKENABLE.off)
freq = null;
}
if (fens)
{
/* fensure is composed of the [out] contracts
@ -1017,7 +1038,19 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.buildResultVar(scout, f.next);
fens = fens.statementSemantic(sc2);
fens.blockExit(funcdecl, false);
// @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
const blockExit = fens.blockExit(funcdecl, false);
if (blockExit & BE.throw_)
{
if (isnothrow)
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, can be made an error in 2.111
deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
funcdecl.toPrettyChars());
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
f.isnothrow = false;
}
funcdecl.flags &= ~FUNCFLAG.noEH;
@ -1144,7 +1177,6 @@ private extern(C++) final class Semantic3Visitor : Visitor
s = s.statementSemantic(sc2);
immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
const blockexit = s.blockExit(funcdecl, isnothrow);
if (blockexit & BE.throw_)
{

View file

@ -28,6 +28,7 @@ extern(C++) class ParseTimeTransitiveVisitor(AST) : PermissiveVisitor!AST
*/
package mixin template ParseVisitMethods(AST)
{
import dmd.root.array;
// Statement Nodes
//===========================================================
@ -46,7 +47,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.CompileStatement s)
{
//printf("Visiting CompileStatement\n");
visitArgs(s.exps);
visitArgs(s.exps.peekSlice());
}
override void visit(AST.CompoundStatement s)
@ -181,11 +182,9 @@ package mixin template ParseVisitMethods(AST)
s.elsebody.accept(this);
}
void visitArgs(AST.Expressions* expressions, AST.Expression basis = null)
private extern(D) void visitArgs(AST.Expression[] expressions, AST.Expression basis = null)
{
if (!expressions || !expressions.dim)
return;
foreach (el; *expressions)
foreach (el; expressions)
{
if (!el)
el = basis;
@ -197,8 +196,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.PragmaStatement s)
{
//printf("Visiting PragmaStatement\n");
if (s.args && s.args.dim)
visitArgs(s.args);
visitArgs(s.args.peekSlice());
if (s._body)
s._body.accept(this);
}
@ -346,19 +344,14 @@ package mixin template ParseVisitMethods(AST)
foreach (p; *td.origParameters)
p.accept(this);
}
visitParameters(t.parameterList.parameters);
visitParameters(t.parameterList.parameters.peekSlice());
}
void visitParameters(AST.Parameters* parameters)
private extern(D) final void visitParameters(AST.Parameter[] parameters)
{
if (parameters)
foreach (i; 0 .. parameters.length)
{
size_t dim = AST.Parameter.dim(parameters);
foreach(i; 0..dim)
{
AST.Parameter fparam = AST.Parameter.getNth(parameters, i);
fparam.accept(this);
}
parameters[i].accept(this);
}
}
@ -469,7 +462,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.TypeTuple t)
{
//printf("Visiting TypeTuple\n");
visitParameters(t.arguments);
visitParameters(t.arguments.peekSlice());
}
override void visit(AST.TypeSlice t)
@ -487,7 +480,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.TypeMixin t)
{
visitArgs(t.exps);
visitArgs(t.exps.peekSlice());
}
// Miscellaneous
@ -571,8 +564,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.PragmaDeclaration d)
{
//printf("Visiting PragmaDeclaration\n");
if (d.args && d.args.dim)
visitArgs(d.args);
visitArgs(d.args.peekSlice());
visitAttribDeclaration(cast(AST.AttribDeclaration)d);
}
@ -580,24 +572,22 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting ConditionalDeclaration\n");
d.condition.accept(this);
if (d.decl)
foreach (de; *d.decl)
de.accept(this);
if (d.elsedecl)
foreach (de; *d.elsedecl)
de.accept(this);
foreach (de; d.decl.peekSlice())
de.accept(this);
foreach (de; d.elsedecl.peekSlice())
de.accept(this);
}
override void visit(AST.CompileDeclaration d)
{
//printf("Visiting compileDeclaration\n");
visitArgs(d.exps);
visitArgs(d.exps.peekSlice());
}
override void visit(AST.UserAttributeDeclaration d)
{
//printf("Visiting UserAttributeDeclaration\n");
visitArgs(d.atts);
visitArgs(d.atts.peekSlice());
visitAttribDeclaration(cast(AST.AttribDeclaration)d);
}
@ -791,6 +781,15 @@ package mixin template ParseVisitMethods(AST)
s.accept(this);
}
override void visit(AST.UnionDeclaration d)
{
//printf("Visiting UnionDeclaration\n");
if (!d.members)
return;
foreach (s; *d.members)
s.accept(this);
}
override void visit(AST.ClassDeclaration d)
{
//printf("Visiting ClassDeclaration\n");
@ -840,7 +839,7 @@ package mixin template ParseVisitMethods(AST)
auto tf = f.type.isTypeFunction();
if (!f.inferRetType && tf.next)
visitType(tf.next);
visitParameters(tf.parameterList.parameters);
visitParameters(tf.parameterList.parameters.peekSlice());
AST.CompoundStatement cs = f.fbody.isCompoundStatement();
AST.Statement s = !cs ? f.fbody : null;
AST.ReturnStatement rs = s ? s.isReturnStatement() : null;
@ -946,7 +945,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.ArrayLiteralExp e)
{
//printf("Visiting ArrayLiteralExp\n");
visitArgs(e.elements, e.basis);
visitArgs(e.elements.peekSlice(), e.basis);
}
override void visit(AST.AssocArrayLiteralExp e)
@ -978,8 +977,7 @@ package mixin template ParseVisitMethods(AST)
if (e.thisexp)
e.thisexp.accept(this);
visitType(e.newtype);
if (e.arguments && e.arguments.dim)
visitArgs(e.arguments);
visitArgs(e.arguments.peekSlice());
}
override void visit(AST.NewAnonClassExp e)
@ -987,8 +985,7 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting NewAnonClassExp\n");
if (e.thisexp)
e.thisexp.accept(this);
if (e.arguments && e.arguments.dim)
visitArgs(e.arguments);
visitArgs(e.arguments.peekSlice());
if (e.cd)
e.cd.accept(this);
}
@ -998,7 +995,7 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting TupleExp\n");
if (e.e0)
e.e0.accept(this);
visitArgs(e.exps);
visitArgs(e.exps.peekSlice());
}
override void visit(AST.FuncExp e)
@ -1056,7 +1053,7 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.MixinExp e)
{
//printf("Visiting MixinExp\n");
visitArgs(e.exps);
visitArgs(e.exps.peekSlice());
}
override void visit(AST.ImportExp e)
@ -1090,7 +1087,7 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting CallExp\n");
e.e1.accept(this);
visitArgs(e.arguments);
visitArgs(e.arguments.peekSlice());
}
override void visit(AST.PtrExp e)
@ -1124,7 +1121,7 @@ package mixin template ParseVisitMethods(AST)
{
//printf("Visiting ArrayExp\n");
e.e1.accept(this);
visitArgs(e.arguments);
visitArgs(e.arguments.peekSlice());
}
override void visit(AST.PostExp e)

View file

@ -1388,6 +1388,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// extended index), as we need to run semantic when `oidx` changes.
size_t tupleOrigIdx = size_t.max;
size_t tupleExtIdx = size_t.max;
bool hasDefault;
foreach (oidx, oparam, eidx, eparam; tf.parameterList)
{
// oparam (original param) will always have the default arg
@ -1396,6 +1397,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// position to get the offset in it later on.
if (oparam.defaultArg)
{
hasDefault = true;
// Get the obvious case out of the way
if (oparam is eparam)
errors |= !defaultArgSemantic(eparam, argsc);
@ -1422,6 +1424,11 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
eparam.defaultArg = (*te.exps)[eidx - tupleExtIdx];
}
}
else if (hasDefault)
{
.error(loc, "default argument expected for `%s`", oparam.toChars());
errors = true;
}
// We need to know the default argument to resolve `auto ref`,
// hence why this has to take place as the very last step.
@ -2089,10 +2096,12 @@ extern (C++) Type merge(Type type)
* loc = the location where the property is encountered
* ident = the identifier of the property
* flag = if flag & 1, don't report "not a property" error and just return NULL.
* src = expression for type `t` or null.
* Returns:
* expression representing the property, or null if not a property and (flag & 1)
*/
Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag)
Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag,
Expression src = null)
{
Expression visitType(Type mt)
{
@ -2169,7 +2178,10 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr);
else
{
error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
if (src)
error(loc, "no property `%s` for `%s` of type `%s`", ident.toChars(), src.toChars(), mt.toPrettyChars(true));
else
error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
if (auto dsym = mt.toDsymbol(scope_))
if (auto sym = dsym.isAggregateDeclaration())
{
@ -4457,7 +4469,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
/************************
* Get the the default initialization expression for a type.
* Get the default initialization expression for a type.
* Params:
* mt = the type for which the init expression is returned
* loc = the location where the expression needs to be evaluated

View file

@ -908,21 +908,12 @@ public:
if ((postblit || destructor) && e->op != EXP::blit)
{
/* Need to call postblit/destructor as part of assignment.
Construction has already been handled by the front-end. */
gcc_assert (e->op != EXP::construct);
/* So we can call postblits on const/immutable objects. */
Type *tm = etype->unSharedOf ()->mutableOf ();
tree ti = build_typeinfo (e, tm);
/* Generate: _d_arraysetassign (t1.ptr, &t2, t1.length, ti); */
result = build_libcall (LIBCALL_ARRAYSETASSIGN, Type::tvoid, 4,
d_array_ptr (t1),
build_address (t2),
d_array_length (t1), ti);
/* This case should have been rewritten to `_d_arraysetassign`
in the semantic phase. */
gcc_unreachable ();
}
else if (integer_zerop (t2))
if (integer_zerop (t2))
{
tree size = size_mult_expr (d_array_length (t1),
size_int (etype->size ()));
@ -2473,6 +2464,20 @@ public:
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
}
else if (tb->ty == TY::Taarray)
{
/* Allocating memory for a new associative array. */
tree arg = build_typeinfo (e, e->newtype);
tree mem = build_libcall (LIBCALL_AANEW, Type::tvoidptr, 1, arg);
/* Return an associative array pointed to by MEM. */
tree aatype = build_ctype (tb);
vec <constructor_elt, va_gc> *ce = NULL;
CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
result = build_nop (build_ctype (e->type),
build_constructor (aatype, ce));
}
else
gcc_unreachable ();

View file

@ -115,10 +115,6 @@ DEF_D_RUNTIME (ALLOCMEMORY, "_d_allocmemory", RT(VOIDPTR), P1(SIZE_T),
DEF_D_RUNTIME (ARRAYCOPY, "_d_arraycopy", RT(ARRAY_VOID),
P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), 0)
/* Used for array assignments from a single element. */
DEF_D_RUNTIME (ARRAYSETASSIGN, "_d_arraysetassign", RT(VOIDPTR),
P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0)
/* Used for concatenating two or more arrays together. Then `n' variant is
for when there is more than two arrays to handle. */
DEF_D_RUNTIME (ARRAYCATT, "_d_arraycatT", RT(ARRAY_BYTE),
@ -140,6 +136,7 @@ DEF_D_RUNTIME (ARRAYAPPENDWD, "_d_arrayappendwd", RT(ARRAY_VOID),
/* Used for allocating a new associative array. */
DEF_D_RUNTIME (ASSOCARRAYLITERALTX, "_d_assocarrayliteralTX", RT(VOIDPTR),
P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0)
DEF_D_RUNTIME (AANEW, "_aaNew", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
/* Used for value equality of two associative arrays. */
DEF_D_RUNTIME (AAEQUAL, "_aaEqual", RT(INT),

View file

@ -151,19 +151,19 @@ static assert(Error!( uint*, int* ));
static assert(is( X!( int function(), int function() ) == int function() ));
// void pointer
static assert(is( X!( void*, int* ) == int* ));
static assert(is( X!( int*, void* ) == int* ));
static assert(is( X!( const(int)*, void* ) == const(int)* ));
static assert(is( X!( const(int*), void* ) == const(int*) ));
static assert(is( X!( int*, const(void)* ) == int* )); // `const`
static assert(is( X!( int*, const(void*) ) == int* )); // `const`
static assert(is( X!( int*, shared(void*) ) == int* )); // should fail
static assert(is( X!( int*, shared(void)* ) == int* )); // should fail
static assert(is( X!( void*, int* ) == void* ));
static assert(is( X!( int*, void* ) == void* ));
static assert(is( X!( const(int)*, void* ) == void* ));
static assert(is( X!( const(int*), void* ) == void* ));
static assert(is( X!( int*, const(void)* ) == const(void)* )); // `const`
static assert(is( X!( int*, const(void*) ) == const(void*) )); // `const`
static assert(is( X!( int*, shared(void*) ) == shared(void*) )); // should fail
static assert(is( X!( int*, shared(void)* ) == shared(void)* )); // should fail
static assert(Error!( int**, void** )); // should work
static assert(is( X!( void*, int function() ) == int function() ));
static assert(is( X!( immutable(void*), int function() ) == int function() )); // `const`
static assert(is( X!( void*, int function() ) == void* ));
static assert(is( X!( immutable(void*), int function() ) == immutable(void*) )); // `const`
// implicit conversion
static assert(is( X!( int*, const(int*) ) == const(int*) ));

View file

@ -0,0 +1,4 @@
extern int xx;
typedef struct Foo *FooRef;
FooRef make_foo(void);

View file

@ -0,0 +1,4 @@
extern int xx;
typedef struct Foo *FooRef;
void free_foo(FooRef foo);

View file

@ -0,0 +1,7 @@
module imports.format23327;
import imports.format23327.write;
immutable(string) format23327() { }
import imports.format23327.internal.write;

View file

@ -0,0 +1,50 @@
// https://issues.dlang.org/show_bug.cgi?id=23351
enum strings =
[
"a[(b).",
"[(a)(b).",
"a(={@.()(",
"a[b,[(c).",
"a[b#([(c).",
"[a@b[(c).",
"[((a).",
"[a)b[(c).",
"a[b)[(c).",
"a(b[(c).",
"a[b()c[(d).",
"a[(b[(c).",
"a(b[(c).",
"[(@@a b[(c).",
"a[(!b)c[(d).",
"[(^a)b[(c).",
"a(b[(c).",
"~[a.b[(c).",
"[a).[(b c d(e[(f).",
"[((a).",
"[a}b[(c).",
"a[b[c..(d).",
"[1a.[(b).",
"a[({in){,",
"a[^in(b[c=])S....,",
"a[({in[({)){,"
];
template KidNamedFinger(T)
{
}
void dummy()
{
static foreach(str; strings)
{
/*
The above strings are all gibberish, they should
fail to parse but not segfault the compiler.
*/
{
enum exp = __traits(compiles, mixin(str));
static assert(!exp);
enum t = __traits(compiles, KidNamedFinger!(mixin(str)));
static assert(!t);
}
}
}

View file

@ -0,0 +1,45 @@
mixin template Constructors(){
this(){ }
this()immutable{ }
this()shared{ }
}
class A {
public:
static T getInstance(this T)() {
return new T();
}
private:
mixin Constructors;
}
class B : A {
private:
mixin Constructors;
}
void f(){
auto a = (new A).getInstance;
auto b = (new B).getInstance;
static assert(is(typeof(a) == A));
static assert(is(typeof(b) == B));
auto ca = (new immutable A).getInstance;
auto sb = (new shared B).getInstance;
static assert(is(typeof(ca) == immutable A));
static assert(is(typeof(sb) == shared B));
}
// https://issues.dlang.org/show_bug.cgi?id=10488
version(none)
void g(){
auto a = A.getInstance();
auto b = B.getInstance();
static assert(is(typeof(a)==A));
static assert(is(typeof(b)==B));
auto ai = (immutable(A)).getInstance();
auto bs = (shared(B)).getInstance();
static assert(is(typeof(ai)==immutable(A)));
static assert(is(typeof(bs)==shared(B)));
}

View file

@ -0,0 +1,38 @@
auto inferNothrow()
in
{
}
out
{
}
do
{
return 1;
}
auto dontInferNothrowIn()
in
{
throw new Exception(null);
}
do
{
return 1;
}
auto dontInferNothrowOut()
out
{
throw new Exception(null);
}
do
{
return 1;
}
enum isNothrow(Attr...) = (Attr.length >= 1)
&& (Attr[0] == "nothrow" || isNothrow!(Attr[1 .. $]));
static assert(isNothrow!(__traits(getFunctionAttributes, inferNothrow)));
static assert(!isNothrow!(__traits(getFunctionAttributes, dontInferNothrowIn)));
static assert(!isNothrow!(__traits(getFunctionAttributes, dontInferNothrowOut)));

View file

@ -0,0 +1,21 @@
// Parsing - expressions
auto a = auto ref (int x) => x;
auto b = auto ref (int x) { return x; };
auto c = function auto ref (int x) { return x; };
auto d = delegate auto ref (int x) { return x; };
// Parsing - aliases
alias e = auto ref (int x) => x;
alias f = auto ref (int x) { return x; };
alias g = function auto ref (int x) { return x; };
alias h = delegate auto ref (int x) { return x; };
// Semantic
void test()
{
alias fun(alias x) = auto ref () => x;
int n = 123;
auto _ = fun!123();
static assert(!__traits(compiles, &fun!123())); // rvalue
fun!n() = 456; // lvalue
}

View file

@ -0,0 +1,16 @@
// https://issues.dlang.org/show_bug.cgi?id=21956
noreturn[noreturn] nrnr;
void gun()
{
foreach (a; nrnr){}
}
int main()
{
noreturn[] empty;
int val;
foreach(el; empty) val++;
return val;
}

View file

@ -0,0 +1,10 @@
// https://issues.dlang.org/show_bug.cgi?id=22674
// EXTRA_FILES: imports/cimports2a.i imports/cimports2b.i
import imports.cimports2a;
import imports.cimports2b;
void do_foo(){
FooRef f = make_foo(); // use_foo.d(5)
free_foo(f); // use_foo.d(6)
}

View file

@ -0,0 +1,6 @@
// REQUIRED_ARGS: -o-
// https://issues.dlang.org/show_bug.cgi?id=23173
mixin("long l = ", long.min, ";");
static assert(mixin(long.min) == long.min);
static assert(is(typeof(mixin(long.min)) == long));

View file

@ -0,0 +1,21 @@
// https://issues.dlang.org/show_bug.cgi?id=23258
struct SumType(Types...)
{
this(Types[0])
{
}
this(Types[1])
{
}
}
alias A2 = SumType!(C1[], C2[]);
class C1
{
}
class C2
{
}

View file

@ -0,0 +1,7 @@
class A {
@disable new();
}
void main() {
scope A a = new A();
}

View file

@ -0,0 +1,3 @@
// https://issues.dlang.org/show_bug.cgi?id=23327
// EXTRA_FILES: imports/format23327.d imports/format23327/write.d
import imports.format23327;

View file

@ -0,0 +1,20 @@
void main ()
{
variance([1.0, 2, 3]);
}
alias meanType(T) = T;
template variance(bool stable = true)
{
void variance(Range)(Range r, bool isPopulation = false)
{
.variance!(double, stable)(r, isPopulation);
}
}
template variance(F, bool stable = true)
{
void variance(Range)(Range r, bool isPopulation = false) {}
void variance(scope const F[] ar...) {}
}

View file

@ -2,7 +2,7 @@
EXTRA_FILES: imports/a10169.d
TEST_OUTPUT:
---
fail_compilation/diag10169.d(12): Error: no property `x` for type `imports.a10169.B`
fail_compilation/diag10169.d(12): Error: no property `x` for `B(0)` of type `imports.a10169.B`
---
*/
import imports.a10169;

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag10783.d(14): Error: no property `type` for type `diag10783.Event`
fail_compilation/diag10783.d(14): Error: no property `type` for `event` of type `diag10783.Event`
fail_compilation/diag10783.d(14): Error: undefined identifier `En`
---
*/

View file

@ -1,10 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag13528.d(13): Error: value of `this` is not known at compile time
fail_compilation/diag13528.d(13): while evaluating `pragma(msg, __traits(getMember, A, "foo"))`
fail_compilation/diag13528.d(6): Error: value of `this` is not known at compile time
fail_compilation/diag13528.d(6): while evaluating `pragma(msg, __traits(getMember, A, "foo"))`
fail_compilation/diag13528.d(12): parent scope from here: `mixin MyTemplate!()`
---
*/
#line 1
mixin template MyTemplate()
{

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag14145.d(15): Error: no property `i` for type `diag14145.main.Capture!(i)`
fail_compilation/diag14145.d(15): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)`
fail_compilation/diag14145.d(15): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
fail_compilation/diag14145.d(34): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int`
fail_compilation/diag14145.d(16): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag15713.d(19): Error: no property `widthSign` for type `diag15713.WrData.Data`
fail_compilation/diag15713.d(19): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data`
fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating
fail_compilation/diag15713.d(44): instantiated from here: `conwritefImpl!("main", "\n", Data(null))`
fail_compilation/diag15713.d(49): instantiated from here: `fdwritef!()`

View file

@ -0,0 +1,16 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag23355.d(1): Error: undefined identifier `n`
fail_compilation/diag23355.d(4): Error: none of the overloads of template `diag23355.ffi1` are callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(1): Candidate is: `ffi1(T)(T[n] s)`
fail_compilation/diag23355.d(2): Error: undefined identifier `n`
fail_compilation/diag23355.d(4): Error: none of the overloads of template `diag23355.ffi2` are callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(2): Candidate is: `ffi2()(T[n] s)`
---
*/
#line 1
void ffi1(T)(T[n] s) { }
void ffi2()(T[n] s) { }
void main() { int[4] x; ffi1(x); ffi2(x); }

View file

@ -1,4 +1,3 @@
// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
@ -8,6 +7,7 @@ fail_compilation/diag3438.d(20): Error: constructor `diag3438.F5.this` is marked
fail_compilation/diag3438.d(20): Use `@disable this();` if you want to disable default initialization.
fail_compilation/diag3438.d(21): Error: constructor `diag3438.F6.this` is marked `@disable`, so it cannot have default arguments for all parameters.
fail_compilation/diag3438.d(21): Use `@disable this();` if you want to disable default initialization.
fail_compilation/diag3438.d(24): Error: default argument expected for `y`
---
*/
@ -19,3 +19,6 @@ struct F3 { this(...) { } } // ok
struct F4 { this(int[] x...) { } } // ok
struct F5 { @disable this(int x = 1); }
struct F6 { @disable this(int x = 1) { } }
// Make sure the deprecation doesn't interfere w/ the check for default arguments
struct S { this(int x = 1, int y) { } }

View file

@ -1,9 +0,0 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag3438b.d(9): Error: default argument expected for `y`
---
*/
// Make sure the deprecation doesn't interfere w/ the check for default arguments
struct S { this(int x = 1, int y) { } }

View file

@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag8894.d(16): Error: no property `x` for type `diag8894.Foo`
fail_compilation/diag8894.d(17): Error: no property `y` for type `diag8894.Foo`
fail_compilation/diag8894.d(18): Error: no property `x` for type `diag8894.Foo`
fail_compilation/diag8894.d(19): Error: no property `x` for type `diag8894.Foo`
fail_compilation/diag8894.d(16): Error: no property `x` for `f` of type `diag8894.Foo`
fail_compilation/diag8894.d(17): Error: no property `y` for `f` of type `diag8894.Foo`
fail_compilation/diag8894.d(18): Error: no property `x` for `f` of type `diag8894.Foo`
fail_compilation/diag8894.d(19): Error: no property `x` for `f` of type `diag8894.Foo`
---
*/

View file

@ -2,11 +2,11 @@
EXTRA_FILES: imports/dip22a.d
TEST_OUTPUT:
---
fail_compilation/dip22a.d(16): Error: no property `bar` for type `imports.dip22a.Klass`
fail_compilation/dip22a.d(17): Error: no property `bar` for type `imports.dip22a.Struct`
fail_compilation/dip22a.d(16): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass`
fail_compilation/dip22a.d(17): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct`
fail_compilation/dip22a.d(18): Error: undefined identifier `bar` in module `imports.dip22a`
fail_compilation/dip22a.d(19): Error: no property `bar` for type `void`
fail_compilation/dip22a.d(20): Error: no property `bar` for type `int`
fail_compilation/dip22a.d(19): Error: no property `bar` for `Template!int` of type `void`
fail_compilation/dip22a.d(20): Error: no property `bar` for `12` of type `int`
---
*/
import imports.dip22a;

View file

@ -1,14 +1,15 @@
/*
TEST_OUTPUT:
---
fail_compilation/e15876_1.d(15): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `)`
fail_compilation/e15876_1.d(16): Error: found `End of File` instead of statement
fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_1.d(16): Error: found `End of File` when expecting `]`
fail_compilation/e15876_1.d(16): Error: no identifier for declarator `o[()
fail_compilation/e15876_1.d(16): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `)`
fail_compilation/e15876_1.d(17): Error: found `End of File` instead of statement
fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `]`
fail_compilation/e15876_1.d(17): Error: no identifier for declarator `o[()
{
scope(exit) }
scope(exit) __error__
}
]`
---
*/

View file

@ -1,25 +1,27 @@
/*
TEST_OUTPUT:
---
fail_compilation/e15876_3.d(25): Error: unexpected `(` in declarator
fail_compilation/e15876_3.d(25): Error: basic type expected, not `=`
fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `(`
fail_compilation/e15876_3.d(26): Error: found `End of File` instead of statement
fail_compilation/e15876_3.d(26): Error: expression expected, not `End of File`
fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/e15876_3.d(26): Error: expression expected, not `End of File`
fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `)`
fail_compilation/e15876_3.d(26): Error: found `End of File` instead of statement
fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_3.d(26): Error: found `End of File` when expecting `)`
fail_compilation/e15876_3.d(26): Error: no identifier for declarator `d(_error_ = ()
fail_compilation/e15876_3.d(27): Error: unexpected `(` in declarator
fail_compilation/e15876_3.d(27): Error: basic type expected, not `=`
fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `(`
fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
fail_compilation/e15876_3.d(28): Error: no identifier for declarator `d(_error_ = ()
{
for (; 0; 0)
for (__error__
0; 0)
{
__error__
}
}
)`
fail_compilation/e15876_3.d(26): Error: semicolon expected following function declaration
fail_compilation/e15876_3.d(28): Error: semicolon expected following function declaration
---
*/
d(={for

View file

@ -1,20 +1,22 @@
/*
TEST_OUTPUT:
---
fail_compilation/e15876_4.d(23): Error: found `)` when expecting `(`
fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `(`
fail_compilation/e15876_4.d(24): Error: found `End of File` instead of statement
fail_compilation/e15876_4.d(24): Error: expression expected, not `End of File`
fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/e15876_4.d(24): Error: expression expected, not `End of File`
fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `)`
fail_compilation/e15876_4.d(24): Error: found `End of File` instead of statement
fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_4.d(24): Error: found `End of File` when expecting `)`
fail_compilation/e15876_4.d(24): Error: no identifier for declarator `typeof(()
fail_compilation/e15876_4.d(25): Error: found `)` when expecting `(`
fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `(`
fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
fail_compilation/e15876_4.d(26): Error: no identifier for declarator `typeof(()
{
for (; 0; 0)
for (__error__
0; 0)
{
__error__
}
}
)`

View file

@ -1,27 +1,28 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail10968.d(42): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(42): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
fail_compilation/fail10968.d(47): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(47): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arraysetassign!(SA[], SA)._d_arraysetassign`
fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
---
*/
@ -52,12 +53,12 @@ void bar() pure @safe
/*
TEST_OUTPUT:
---
fail_compilation/fail10968.d(75): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(76): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(77): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(80): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(78): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(81): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(82): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
fail_compilation/fail10968.d(83): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit
---
*/

View file

@ -3,8 +3,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail121.d(23): Error: no property `typeinfo` for type `fail121.myobject`
fail_compilation/fail121.d(23): Error: no property `typeinfo` for type `int`
fail_compilation/fail121.d(23): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject`
fail_compilation/fail121.d(23): Error: no property `typeinfo` for `i` of type `int`
---
*/

View file

@ -0,0 +1,21 @@
// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `in` contract may throw but function is marked as `nothrow`
fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `out` contract may throw but function is marked as `nothrow`
---
*/
void test() nothrow
in
{
throw new Exception(null);
}
out
{
throw new Exception(null);
}
do
{
}

View file

@ -4,9 +4,8 @@ EXTRA_FILES: imports/fail17646.d
TEST_OUTPUT:
---
fail_compilation/imports/fail17646.d(10): Error: found `}` instead of statement
fail_compilation/imports/fail17646.d(7): Error: function `imports.fail17646.allTestData!"".allTestData` has no `return` statement, but is expected to return a value of type `const(TestData)[]`
fail_compilation/fail17646.d(16): Error: template instance `imports.fail17646.allTestData!""` error instantiating
fail_compilation/fail17646.d(19): instantiated from here: `runTests!""`
fail_compilation/fail17646.d(11): Error: function `fail17646.runTests!"".runTests` has no `return` statement, but is expected to return a value of type `int`
fail_compilation/fail17646.d(18): Error: template instance `fail17646.runTests!""` error instantiating
---
*/
int runTests(Modules...)()

View file

@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18892.d(20): Error: no property `foo` for type `fail18892.MT`
fail_compilation/fail18892.d(21): Error: no property `foo` for type `fail18892.MT`
fail_compilation/fail18892.d(20): Error: no property `foo` for `a` of type `fail18892.MT`
fail_compilation/fail18892.d(21): Error: no property `foo` for `MT` of type `fail18892.MT`
---
*/

View file

@ -1,9 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18970.d(24): Error: no property `y` for type `fail18970.S`
fail_compilation/fail18970.d(24): Error: no property `y` for `S()` of type `fail18970.S`
fail_compilation/fail18970.d(24): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
fail_compilation/fail18970.d(31): Error: no property `yyy` for type `fail18970.S2`
fail_compilation/fail18970.d(31): Error: no property `yyy` for `this` of type `fail18970.S2`
fail_compilation/fail18970.d(31): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/

View file

@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18979.d(13): Error: no property `__ctor` for type `imports.imp18979.Foo`
fail_compilation/fail18979.d(13): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo`
----
*/

View file

@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail19103.d(12): Error: no property `puts` for type `fail19103.C`
fail_compilation/fail19103.d(14): Error: no property `puts` for type `fail19103.S1`
fail_compilation/fail19103.d(12): Error: no property `puts` for `new C` of type `fail19103.C`
fail_compilation/fail19103.d(14): Error: no property `puts` for `s1` of type `fail19103.S1`
fail_compilation/fail19103.d(16): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`?
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail19687.d(17): Error: no property `nonexisting` for type `string`
fail_compilation/fail19687.d(17): Error: no property `nonexisting` for `""` of type `string`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail19913.d(11): Error: no property `b` for type `int`
fail_compilation/fail19913.d(11): Error: no property `b` for `a` of type `int`
fail_compilation/fail19913.d(11): Error: mixin `fail19913.S.b!()` is not defined
---
*/

View file

@ -0,0 +1,19 @@
/+ TEST_OUTPUT:
---
fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto`
fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int`
fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)`
fail_compilation/fail21243.d(16): Error: declaration expected, not `)`
fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values
fail_compilation/fail21243.d(18): Error: basic type expected, not `(`
fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases
fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration
fail_compilation/fail21243.d(18): Error: declaration expected, not `=>`
fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values
---
+/
auto a = auto (int x) => x;
auto b = function auto (int x) { return x; };
alias c = auto (int x) => x;
alias d = function auto (int x) { return x; };

View file

@ -4,8 +4,8 @@ EXTRA_FILES: imports/test23109a.d imports/test23109b.d imports/test23109c.d
EXTRA_SOURCES: extra-files/test23109/object.d
TEST_OUTPUT:
---
Error: no property `getHash` for type `object.TypeInfo_Const`
Error: no property `getHash` for type `object.TypeInfo_Const`
Error: no property `getHash` for `typeid(const(Ensure[]))` of type `object.TypeInfo_Const`
Error: no property `getHash` for `typeid(const(Ensure[1]))` of type `object.TypeInfo_Const`
fail_compilation/imports/test23109a.d(10): Error: template instance `imports.test23109a.Array!(Ensure)` error instantiating
---
*/

View file

@ -0,0 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/imports/fail7372.d(7): Error: undefined identifier `X`
fail_compilation/fail7372.d(4): parent scope from here: `mixin Issue7372!()`
---
*/
#line 1
import imports.fail7372;
interface I {}
class C : I {
mixin Issue7372!();
}

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for type `int`
fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for `0` of type `int`
fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for type `object.Object`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/failoffset.d(12): Error: no property `offset` for type `int`
fail_compilation/failoffset.d(12): Error: no property `offset` for `b` of type `int`
fail_compilation/failoffset.d(12): while evaluating: `static assert(b.offset == 4)`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice10938.d(13): Error: no property `opts` for type `ice10938.C`
fail_compilation/ice10938.d(13): Error: no property `opts` for `this` of type `ice10938.C`
fail_compilation/ice10938.d(13): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice12174.d(12): Error: no property `sum` for type `int[]`
fail_compilation/ice12174.d(12): Error: no property `sum` for `[1, 2, 3]` of type `int[]`
fail_compilation/ice12174.d(20): Error: CTFE failed because of previous errors in `this`
fail_compilation/ice12174.d(13): called from here: `filter([1, 2, 3])`
---

View file

@ -2,19 +2,21 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `(`
fail_compilation/ice15855.d(25): Error: found `End of File` instead of statement
fail_compilation/ice15855.d(25): Error: expression expected, not `End of File`
fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/ice15855.d(25): Error: expression expected, not `End of File`
fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `)`
fail_compilation/ice15855.d(25): Error: found `End of File` instead of statement
fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/ice15855.d(25): Error: found `End of File` when expecting `]`
fail_compilation/ice15855.d(25): Error: no identifier for declarator `a[()
fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `(`
fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `;` following `for` condition
fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `)`
fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `}` following compound statement
fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `]`
fail_compilation/ice15855.d(27): Error: no identifier for declarator `a[()
{
for (; 0; 0)
for (__error__
0; 0)
{
__error__
}
}
]`

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice18469.d(10): Error: no property `opCall` for type `void`
fail_compilation/ice18469.d(10): Error: no property `opCall` for `this.~this()` of type `void`
---
*/
class Bar

View file

@ -1,6 +1,6 @@
/* TEST_OUTPUT:
---
fail_compilation/ice19755.d(11): Error: no property `x` for type `ice19755.Thunk!int*`
fail_compilation/ice19755.d(11): Error: no property `x` for `self` of type `ice19755.Thunk!int*`
fail_compilation/ice19755.d(16): Error: template instance `ice19755.Thunk!int` error instantiating
---
*/

View file

@ -0,0 +1,9 @@
module imports.fail7372;
import imports.imp1;
mixin template Issue7372()
{
public void f()
{
int foo = X;
}
}

View file

@ -22,7 +22,6 @@ fail_compilation/misc_parser_err_cov1.d(39): Error: expression expected, not `;`
fail_compilation/misc_parser_err_cov1.d(40): Error: semicolon expected following auto declaration, not `auto`
fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected following `.`, not `+`
fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`.
fail_compilation/misc_parser_err_cov1.d(41): Error: found `.` when expecting `;` following statement
fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;`
fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement
fail_compilation/misc_parser_err_cov1.d(43): Error: found `End of File` when expecting `}` following compound statement

View file

@ -0,0 +1,13 @@
/* TEST_OUTPUT:
---
fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F;
` of type `void`
---
*/
mixin template Foo() { }
void main()
{
mixin Foo F;
F.x;
}

View file

@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/test15785.d(16): Error: no property `foo` for type `imports.test15785.Base`
fail_compilation/test15785.d(16): Error: no property `foo` for `super` of type `imports.test15785.Base`
fail_compilation/test15785.d(17): Error: undefined identifier `bar`
---
*/

View file

@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/test15897.d(19): Error: no property `create` for type `imports.test15897.Cat`
fail_compilation/test15897.d(19): Error: no property `create` for `cat` of type `imports.test15897.Cat`
---
*/
module test15897;

View file

@ -1,7 +1,7 @@
/* REQUIRED_ARGS: -preview=bitfields
* TEST_OUTPUT:
---
fail_compilation/test16188.d(101): Error: no property `name` for type `test16188.Where`
fail_compilation/test16188.d(101): Error: no property `name` for `Where()` of type `test16188.Where`
fail_compilation/test16188.d(101): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
(spec:1) fail_compilation/test17380spec.d(14): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for type `test17380spec.Uint128`
(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128`
fail_compilation/test17380spec.d(14): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
---
*/

View file

@ -3,10 +3,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/test21096.d(13): Error: identifier or new keyword expected following `(...)`.
fail_compilation/test21096.d(13): Error: found `.` when expecting `]`
fail_compilation/test21096.d(13): Error: no identifier for declarator `char`
fail_compilation/test21096.d(13): Error: declaration expected, not `]`
fail_compilation/test21096.d(11): Error: identifier or new keyword expected following `(...)`.
fail_compilation/test21096.d(11): Error: no identifier for declarator `char[(__error)]`
---
*/

Some files were not shown because too many files have changed in this diff Show more