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:
parent
be4a6551ed
commit
c8dfa79c99
171 changed files with 3175 additions and 5197 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, ...);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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_)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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*) ));
|
||||
|
|
4
gcc/testsuite/gdc.test/compilable/imports/cimports2a.i
Normal file
4
gcc/testsuite/gdc.test/compilable/imports/cimports2a.i
Normal file
|
@ -0,0 +1,4 @@
|
|||
extern int xx;
|
||||
|
||||
typedef struct Foo *FooRef;
|
||||
FooRef make_foo(void);
|
4
gcc/testsuite/gdc.test/compilable/imports/cimports2b.i
Normal file
4
gcc/testsuite/gdc.test/compilable/imports/cimports2b.i
Normal file
|
@ -0,0 +1,4 @@
|
|||
extern int xx;
|
||||
|
||||
typedef struct Foo *FooRef;
|
||||
void free_foo(FooRef foo);
|
7
gcc/testsuite/gdc.test/compilable/imports/format23327.d
Normal file
7
gcc/testsuite/gdc.test/compilable/imports/format23327.d
Normal file
|
@ -0,0 +1,7 @@
|
|||
module imports.format23327;
|
||||
|
||||
import imports.format23327.write;
|
||||
|
||||
immutable(string) format23327() { }
|
||||
|
||||
import imports.format23327.internal.write;
|
50
gcc/testsuite/gdc.test/compilable/segfaultgolf.d
Normal file
50
gcc/testsuite/gdc.test/compilable/segfaultgolf.d
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
45
gcc/testsuite/gdc.test/compilable/statictemplatethis.d
Normal file
45
gcc/testsuite/gdc.test/compilable/statictemplatethis.d
Normal 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)));
|
||||
}
|
38
gcc/testsuite/gdc.test/compilable/test13123.d
Normal file
38
gcc/testsuite/gdc.test/compilable/test13123.d
Normal 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)));
|
21
gcc/testsuite/gdc.test/compilable/test21243.d
Normal file
21
gcc/testsuite/gdc.test/compilable/test21243.d
Normal 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
|
||||
}
|
16
gcc/testsuite/gdc.test/compilable/test21956.d
Normal file
16
gcc/testsuite/gdc.test/compilable/test21956.d
Normal 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;
|
||||
}
|
10
gcc/testsuite/gdc.test/compilable/test22674.d
Normal file
10
gcc/testsuite/gdc.test/compilable/test22674.d
Normal 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)
|
||||
}
|
6
gcc/testsuite/gdc.test/compilable/test23173.d
Normal file
6
gcc/testsuite/gdc.test/compilable/test23173.d
Normal 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));
|
21
gcc/testsuite/gdc.test/compilable/test23258.d
Normal file
21
gcc/testsuite/gdc.test/compilable/test23258.d
Normal 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
|
||||
{
|
||||
}
|
7
gcc/testsuite/gdc.test/compilable/test23306.d
Normal file
7
gcc/testsuite/gdc.test/compilable/test23306.d
Normal file
|
@ -0,0 +1,7 @@
|
|||
class A {
|
||||
@disable new();
|
||||
}
|
||||
|
||||
void main() {
|
||||
scope A a = new A();
|
||||
}
|
3
gcc/testsuite/gdc.test/compilable/test23327.d
Normal file
3
gcc/testsuite/gdc.test/compilable/test23327.d
Normal 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;
|
20
gcc/testsuite/gdc.test/compilable/vararg.d
Normal file
20
gcc/testsuite/gdc.test/compilable/vararg.d
Normal 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...) {}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!()`
|
||||
|
|
16
gcc/testsuite/gdc.test/fail_compilation/diag23355.d
Normal file
16
gcc/testsuite/gdc.test/fail_compilation/diag23355.d
Normal 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); }
|
|
@ -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) { } }
|
||||
|
|
|
@ -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) { } }
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__
|
||||
}
|
||||
]`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
}
|
||||
}
|
||||
)`
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
21
gcc/testsuite/gdc.test/fail_compilation/fail13123.d
Normal file
21
gcc/testsuite/gdc.test/fail_compilation/fail13123.d
Normal 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
|
||||
{
|
||||
}
|
|
@ -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...)()
|
||||
|
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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`
|
||||
----
|
||||
*/
|
||||
|
||||
|
|
|
@ -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`?
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
19
gcc/testsuite/gdc.test/fail_compilation/fail21243.d
Normal file
19
gcc/testsuite/gdc.test/fail_compilation/fail21243.d
Normal 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; };
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
13
gcc/testsuite/gdc.test/fail_compilation/fail7372.d
Normal file
13
gcc/testsuite/gdc.test/fail_compilation/fail7372.d
Normal 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!();
|
||||
}
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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)`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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])`
|
||||
---
|
||||
|
|
|
@ -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__
|
||||
}
|
||||
}
|
||||
]`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
module imports.fail7372;
|
||||
import imports.imp1;
|
||||
mixin template Issue7372()
|
||||
{
|
||||
public void f()
|
||||
{
|
||||
int foo = X;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
13
gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
Normal file
13
gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
Normal 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;
|
||||
}
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue