diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-09-27 10:43:32 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-09-27 10:50:18 +0200 |
commit | c8dfa79c9948ce09a7b4071f8059294b1972aef6 (patch) | |
tree | cb93655417a5475c6baac88691fc92621b3fa7ce /gcc | |
parent | be4a6551ed37c1e7dbdfb9400fc2e2b5d40c5be2 (diff) | |
download | gcc-c8dfa79c9948ce09a7b4071f8059294b1972aef6.zip gcc-c8dfa79c9948ce09a7b4071f8059294b1972aef6.tar.gz gcc-c8dfa79c9948ce09a7b4071f8059294b1972aef6.tar.bz2 |
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.
Diffstat (limited to 'gcc')
104 files changed, 1829 insertions, 1375 deletions
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index e91aee3..dcfca64 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -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; diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 85fc49d..a4c46f3 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -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. diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index f4b5e8a..edca17f 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -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; diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index d91e35e..f0909e3 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -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(); diff --git a/gcc/d/dmd/apply.d b/gcc/d/dmd/apply.d index ac2c80e..3b73771 100644 --- a/gcc/d/dmd/apply.d +++ b/gcc/d/dmd/apply.d @@ -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) diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d index 272e751..f07a6f4 100644 --- a/gcc/d/dmd/arrayop.d +++ b/gcc/d/dmd/arrayop.d @@ -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; } /*********************************************** diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index b569a9c..3472d1c 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -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()) diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index 088ca61..09e3833 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -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; diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d index e118d70..8204961 100644 --- a/gcc/d/dmd/chkformat.d +++ b/gcc/d/dmd/chkformat.d @@ -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'); - - idx = 0; - assert(parseGenericFormatSpecifier("hn", idx, genSpecifier) == Format.hn); - assert(genSpecifier == 'n'); - - idx = 0; - assert(parseGenericFormatSpecifier("ji", idx, genSpecifier) == Format.jd); - assert(genSpecifier == 'i'); + void testG(string fmtStr, Format expectedFormat, char expectedGenSpecifier) + { + idx = 0; + assert(parseGenericFormatSpecifier(fmtStr, idx, genSpecifier) == expectedFormat); + assert(genSpecifier == expectedGenSpecifier); + } - 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 - */ - - 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); +@("parsePrintfFormatSpecifier") unittest +{ + bool useGNUExts = false; - 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 - */ + size_t idx = 0; + bool widthStar; + bool precisionStar; - 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); + + 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); - 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); + // Synonyms + 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); + + // width, precision + testP("%*d", Format.d, 3); + assert(widthStar && !precisionStar); + + testP("%.*d", Format.d, 4); + assert(!widthStar && precisionStar); + + testP("%*.*d", Format.d, 5); + assert(widthStar && precisionStar); - idx = 0; - assert(parseScanfFormatSpecifier("%llu", idx, asterisk) == Format.llu); - assert(idx == 4); + // 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("%ju", idx, asterisk) == Format.ju); - assert(idx == 3); + // 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("%g", idx, asterisk) == Format.g); - assert(idx == 2); + testP("%C", Format.lc, 2); + testP("%S", Format.ls, 2); - idx = 0; - assert(parseScanfFormatSpecifier("%lg", idx, asterisk) == Format.lg); - assert(idx == 3); + // 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); + } - idx = 0; - assert(parseScanfFormatSpecifier("%Lg", idx, asterisk) == Format.Lg); - assert(idx == 3); + 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); - idx = 0; - assert(parseScanfFormatSpecifier("%p", idx, asterisk) == Format.p); - assert(idx == 2); + // ISO printf() + useGNUExts = false; + testP(s, Format.error, 2); + } +} - idx = 0; - assert(parseScanfFormatSpecifier("%s", idx, asterisk) == Format.s); - assert(idx == 2); +@("parseScanfFormatSpecifier") unittest +{ + size_t idx; + bool asterisk; - idx = 0; - assert(parseScanfFormatSpecifier("%ls", idx, asterisk,) == Format.ls); - assert(idx == 3); + void testS(string fmtStr, Format expectedFormat, size_t expectedIdx) + { + idx = 0; + assert(parseScanfFormatSpecifier(fmtStr, idx, asterisk) == expectedFormat); + assert(idx == expectedIdx); + } - idx = 0; - assert(parseScanfFormatSpecifier("%%", idx, asterisk) == Format.percent); - assert(idx == 2); + // 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 - idx = 0; - assert(parseScanfFormatSpecifier("%i", idx, asterisk) == Format.d); - assert(idx == 2); + testS("%i", Format.d, 2); + testS("%n", Format.n, 2); - idx = 0; - assert(parseScanfFormatSpecifier("%n", idx, asterisk) == Format.n); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%o", idx, asterisk) == Format.u); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%x", idx, asterisk) == Format.u); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%f", idx, asterisk) == Format.g); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%e", idx, asterisk) == Format.g); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g); - assert(idx == 2); - - idx = 0; - assert(parseScanfFormatSpecifier("%c", idx, asterisk) == Format.c); - assert(idx == 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); - } - idx = 0; - assert(parseScanfFormatSpecifier("%mc", idx, asterisk) == Format.POSIX_ms); - assert(idx == 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); - } + testS(s, Format.error, s.length); } - // 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("%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); + + testS("%C", Format.lc, 2); + testS("%S", Format.ls, 2); } diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index 1a26eaa..ba7d590 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -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) { diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 2679a63..2c5a4f0 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -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) { diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index afd19f3..8ab3873 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -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); diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index bc8db44..5bce6b0 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -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); diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d index 5cc3772..705acd1 100644 --- a/gcc/d/dmd/dimport.d +++ b/gcc/d/dmd/dimport.d @@ -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); diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index a9fd0f5..a95d9de 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -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. diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d index 25794e2..be0cbcc 100644 --- a/gcc/d/dmd/dmangle.d +++ b/gcc/d/dmd/dmangle.d @@ -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); diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d index ba83649..e1d5897 100644 --- a/gcc/d/dmd/doc.d +++ b/gcc/d/dmd/doc.d @@ -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) diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index c940ff0..7e2d02f 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -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; diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index bea4b77..acf0004 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -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, ...); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index c3424dc..701f06a 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -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) diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 34cae1d..13efc1c 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -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); } } diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 4f06bac..7ba0a96 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -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; } } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index f871fade..42b4dd4 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -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() */ diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 9ab1cab..c9e3978 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -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; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 3114100..8a4a13c 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -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()); diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 4c09474..bcae282 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -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); } } diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d index 7d4fbc3..7a840ff 100644 --- a/gcc/d/dmd/iasmgcc.d +++ b/gcc/d/dmd/iasmgcc.d @@ -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) diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 6695faa..48ca766 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -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" }, diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d index 164a5f3..523b5b8 100644 --- a/gcc/d/dmd/init.d +++ b/gcc/d/dmd/init.d @@ -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) { diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h index 296c31d..977157f 100644 --- a/gcc/d/dmd/init.h +++ b/gcc/d/dmd/init.h @@ -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(); diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index a576712..ef39f59 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -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 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)); // 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; + } } + } + //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index); + return si; + } - VarDeclaration vd = sd.fields[fieldi]; + /* 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 + } - // Check for overlapping initializations (can happen with unions) - foreach (k, v2; sd.fields[0 .. nfields]) + 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()) { - if (vd.isOverlappedWith(v2) && elems[k]) + ExpInitializer ei = di.initializer.isExpInitializer(); + if (ei.exp.isStringExp() && tnsa.nextOf().isintegral()) { - continue FieldLoop; // skip it + ai.addInit(null, ei); + ++index; } + else + ai.addInit(null, subArray(tnsa, 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) + else { - errors = true; - continue; + ai.addInit(null, di.initializer); + ++index; } - - elems[fieldi] = ex; } - if (errors) - return err(); - - // 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); + //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()) - { - return ei.initializerSemantic(sc, t, needInterpret); - } - - error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars()); - return err(); - } + size_t fieldi = 0; - /* 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()) + for (size_t index = 0; index < ci.initializerList.length; ) { - if (ei.exp.isStringExp()) - return ei.initializerSemantic(sc, t, needInterpret); + auto di = ci.initializerList[index]; + auto dlist = di.designatorList; + if (dlist) + { + const length = (*dlist).length; + if (length == 0 || !(*dlist)[0].ident) + { + 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) + { + fieldi = k; + si.addInit(id, di.initializer); + ++fieldi; + ++index; + break; + } + } + } + else + { + 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; + } + } } + return initializerSemantic(si, 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) + else if (auto ta = t.isTypeSArray()) { - //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; + auto tn = t.nextOf().toBasetype(); // element type of array - /* Run initializerSemantic on a single element. + /* If it's an array of integral being initialized by `{ string }` + * replace with `string` */ - Initializer elem(Initializer ie) + if (tn.isintegral()) { - ++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; + if (ExpInitializer ei = isBraceExpression()) + { + if (ei.exp.isStringExp()) + return ei.initializerSemantic(sc, t, needInterpret); + } } - foreach (j; 0 .. dim) + 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 = dil[i]; - if (di.designatorList) - { - error(ci.loc, "C designator-list not supported yet"); - errors = true; - break; - } - if (tnsa && di.initializer.isExpInitializer()) + auto di = ci.initializerList[index]; + if (auto dlist = di.designatorList) { - // 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].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()) { - // 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 + */ + if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct { - simple = false; - dil[n].initializer = structs(tns); // the first field + 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 - dil[n].initializer = elem(di.initializer); + 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 { - di.initializer = elem(di.initializer); + ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret)); + ++index; } - ++n; - if (i == dil.length) - break; - } - //printf(" n: %d i: %d\n", cast(int)n, cast(int)i); - return n; - } - - 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 - { - // 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(); - } - - 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) - { - ai.index[j] = null; - ai.value[j] = dil[j].initializer; } - auto ty = tx; - return ai.initializerSemantic(sc, ty, needInterpret); + return initializerSemantic(ai, sc, tx, needInterpret); } - - if (newdim < ci.initializerList.length && tnb.isTypeStruct()) + 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) diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 21bbde8..1de89d4 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -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 { diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 6bfb729..341ce36 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -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; } diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index f2da41b..1240f5a 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -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; + } +} diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 3e614d8..2b9c94c 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -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); } }; diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index 4f6903c..ca99b8b 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -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) { diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index ce2769d..ed85a5d 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -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); - - ai = token.ident; - nextToken(); - } - else goto _else; + 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 { - _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; diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/root/object.h index 0c92a9a..b735dd9 100644 --- a/gcc/d/dmd/root/object.h +++ b/gcc/d/dmd/root/object.h @@ -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. diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index ad4487f..d2f9c0a 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -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_) { diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d index 5791a88..0d7240f 100644 --- a/gcc/d/dmd/transitivevisitor.d +++ b/gcc/d/dmd/transitivevisitor.d @@ -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) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index b21ff79..0ef7705 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -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 diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index b0ce870..fa5ec90 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -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 (); diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index 282f22c..f576bef 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -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), diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d index 076e29b..abe956c 100644 --- a/gcc/testsuite/gdc.test/compilable/commontype.d +++ b/gcc/testsuite/gdc.test/compilable/commontype.d @@ -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*) )); diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i new file mode 100644 index 0000000..c8ff976 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i @@ -0,0 +1,4 @@ +extern int xx; + +typedef struct Foo *FooRef; +FooRef make_foo(void); diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i new file mode 100644 index 0000000..03b22b2 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i @@ -0,0 +1,4 @@ +extern int xx; + +typedef struct Foo *FooRef; +void free_foo(FooRef foo); diff --git a/gcc/testsuite/gdc.test/compilable/imports/format23327.d b/gcc/testsuite/gdc.test/compilable/imports/format23327.d new file mode 100644 index 0000000..de9b957 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/format23327.d @@ -0,0 +1,7 @@ +module imports.format23327; + +import imports.format23327.write; + +immutable(string) format23327() { } + +import imports.format23327.internal.write; diff --git a/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d b/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/format23327/write.d diff --git a/gcc/testsuite/gdc.test/compilable/segfaultgolf.d b/gcc/testsuite/gdc.test/compilable/segfaultgolf.d new file mode 100644 index 0000000..2ea125f --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/segfaultgolf.d @@ -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); + } + } +} diff --git a/gcc/testsuite/gdc.test/compilable/statictemplatethis.d b/gcc/testsuite/gdc.test/compilable/statictemplatethis.d new file mode 100644 index 0000000..0236f2d --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/statictemplatethis.d @@ -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))); +} diff --git a/gcc/testsuite/gdc.test/compilable/test13123.d b/gcc/testsuite/gdc.test/compilable/test13123.d new file mode 100644 index 0000000..881eb1b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test13123.d @@ -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))); diff --git a/gcc/testsuite/gdc.test/compilable/test21243.d b/gcc/testsuite/gdc.test/compilable/test21243.d new file mode 100644 index 0000000..20838dc --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21243.d @@ -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 +} diff --git a/gcc/testsuite/gdc.test/compilable/test21956.d b/gcc/testsuite/gdc.test/compilable/test21956.d new file mode 100644 index 0000000..64ebc55 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21956.d @@ -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; +} diff --git a/gcc/testsuite/gdc.test/compilable/test22674.d b/gcc/testsuite/gdc.test/compilable/test22674.d new file mode 100644 index 0000000..cc6e3bb --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test22674.d @@ -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) +} diff --git a/gcc/testsuite/gdc.test/compilable/test23173.d b/gcc/testsuite/gdc.test/compilable/test23173.d new file mode 100644 index 0000000..6b16132 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23173.d @@ -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)); diff --git a/gcc/testsuite/gdc.test/compilable/test23258.d b/gcc/testsuite/gdc.test/compilable/test23258.d new file mode 100644 index 0000000..1e8e91b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23258.d @@ -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 +{ +} diff --git a/gcc/testsuite/gdc.test/compilable/test23306.d b/gcc/testsuite/gdc.test/compilable/test23306.d new file mode 100644 index 0000000..81b51f6 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23306.d @@ -0,0 +1,7 @@ +class A { + @disable new(); +} + +void main() { + scope A a = new A(); +} diff --git a/gcc/testsuite/gdc.test/compilable/test23327.d b/gcc/testsuite/gdc.test/compilable/test23327.d new file mode 100644 index 0000000..bbb6346 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23327.d @@ -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; diff --git a/gcc/testsuite/gdc.test/compilable/vararg.d b/gcc/testsuite/gdc.test/compilable/vararg.d new file mode 100644 index 0000000..79826a0 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/vararg.d @@ -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...) {} +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d index 72becf2..84d0ad4 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d @@ -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; diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d index f18341f..80c7f5e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13528.d b/gcc/testsuite/gdc.test/fail_compilation/diag13528.d index 5d908f7..9b5761f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag13528.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag13528.d @@ -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() { diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d index 6447f5e..fa7c611 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d index 1c61408..e4cb2a7 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d @@ -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!()` diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23355.d b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d new file mode 100644 index 0000000..586cbb0 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d @@ -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); } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3438.d b/gcc/testsuite/gdc.test/fail_compilation/diag3438.d index 445f6d5d..c4cbc72 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag3438.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag3438.d @@ -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) { } } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d b/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d deleted file mode 100644 index 46a197d..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/diag3438b.d +++ /dev/null @@ -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) { } } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d index 9e0dadd..7cf3023 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d index bf04a51..324d217 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d @@ -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; diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d index 33bee25..92e0734 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d @@ -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__ +} ]` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d index ae5f77a..fe7d546 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d index 6f46633..f4bd407 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d @@ -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__ } } )` diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d index e969b24..cfda8f4 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail121.d b/gcc/testsuite/gdc.test/fail_compilation/fail121.d index 70e9d0c..8d5af74 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail121.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail121.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13123.d b/gcc/testsuite/gdc.test/fail_compilation/fail13123.d new file mode 100644 index 0000000..7784cba --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail13123.d @@ -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 +{ +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17646.d b/gcc/testsuite/gdc.test/fail_compilation/fail17646.d index 3571e38..39e7cb9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17646.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail17646.d @@ -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...)() diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d index 531d1ed..0fb56d3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d index 0973217..a8156fe 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d index 9756570..04e36f6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d @@ -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` ---- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d index 6b740ac..40fafcd 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d @@ -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`? --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19687.d b/gcc/testsuite/gdc.test/fail_compilation/fail19687.d index 7d1c6e5..0076091 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19687.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19687.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19913.d b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d index fe2655e..c880923 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19913.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d new file mode 100644 index 0000000..25df235 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d @@ -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; }; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d index 91b4e79..5c5c11b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7372.d b/gcc/testsuite/gdc.test/fail_compilation/fail7372.d new file mode 100644 index 0000000..2d56e09 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7372.d @@ -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!(); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d index d7853e6..c44b289 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d +++ b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/failoffset.d b/gcc/testsuite/gdc.test/fail_compilation/failoffset.d index bbec698..ff0d26b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/failoffset.d +++ b/gcc/testsuite/gdc.test/fail_compilation/failoffset.d @@ -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)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d index 2084e32..d21ee47 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12174.d b/gcc/testsuite/gdc.test/fail_compilation/ice12174.d index 019722a..dbe386e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice12174.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice12174.d @@ -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])` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d index e800838..b26fe4c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d @@ -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__ } } ]` diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice18469.d b/gcc/testsuite/gdc.test/fail_compilation/ice18469.d index 8803956..796dd3d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice18469.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice18469.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d index f948477..6d60fc4 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d b/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d new file mode 100644 index 0000000..f71c736 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/fail7372.d @@ -0,0 +1,9 @@ +module imports.fail7372; +import imports.imp1; +mixin template Issue7372() +{ + public void f() + { + int foo = X; + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d index b50a616..11fddf0 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d new file mode 100644 index 0000000..db8bf59 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d @@ -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; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15785.d b/gcc/testsuite/gdc.test/fail_compilation/test15785.d index 23a3660..594b5d3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15785.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15785.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15897.d b/gcc/testsuite/gdc.test/fail_compilation/test15897.d index e4ade7d..db554cb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15897.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15897.d @@ -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; diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d index c4a0fa6..bdaae94 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d index 2456a59..f523337 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21096.d b/gcc/testsuite/gdc.test/fail_compilation/test21096.d index e32ad9c..302eb3d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test21096.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test21096.d @@ -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)]` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22680.d b/gcc/testsuite/gdc.test/fail_compilation/test22680.d new file mode 100644 index 0000000..caf0f4a --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test22680.d @@ -0,0 +1,17 @@ +/* REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/test22680.d(104): Error: scope variable `this` assigned to non-scope `c` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=22680 + +#line 100 + +C c; +class C { + ~this() @safe { + c = this; + } +} diff --git a/gcc/testsuite/gdc.test/runnable/newaa.d b/gcc/testsuite/gdc.test/runnable/newaa.d new file mode 100644 index 0000000..94e79d5 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/newaa.d @@ -0,0 +1,23 @@ +void main() +{ + alias AA = int[string]; + // aa is not ref + static void test(AA aa) + { + aa[""] = 0; + } + auto aa = new AA(); + auto ab = new int[string]; + auto ac = new typeof(aa); + test(aa); + test(ab); + test(ac); + assert(aa.length); + assert(ab.length); + assert(ac.length); + + int[string] a = new int[string]; + auto b = a; + a["seven"] = 7; + assert(b["seven"] == 7); +} diff --git a/gcc/testsuite/gdc.test/runnable/test23234.d b/gcc/testsuite/gdc.test/runnable/test23234.d new file mode 100644 index 0000000..7872aa7 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test23234.d @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=23234 + +class Bar +{ +} + +class Foo +{ + Bar get() { return new Bar; } + alias get this; +} + +void main() +{ + auto foo = new Foo; + void test(Bar delegate() dg) + { + assert(dg() !is null); + } + + test(() => foo); +} diff --git a/gcc/testsuite/gdc.test/runnable/testassign.d b/gcc/testsuite/gdc.test/runnable/testassign.d index f47d2b2..586aea8 100644 --- a/gcc/testsuite/gdc.test/runnable/testassign.d +++ b/gcc/testsuite/gdc.test/runnable/testassign.d @@ -230,6 +230,21 @@ void test5() static assert(!__traits(compiles, s.err += 1)); } +void test6() +{ + int dtors; + struct S6 + { + @disable this(this); + ~this() { dtors++; } + } + + S6[2] arr; + arr = S6(); + + assert(dtors == 2); +} + /***************************************************/ // https://issues.dlang.org/show_bug.cgi?id=4424 @@ -1192,6 +1207,7 @@ int main() test3(); test4(); test5(); + test6(); test4424(); test6174a(); test6174b(); |