aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-09-27 10:43:32 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-09-27 10:50:18 +0200
commitc8dfa79c9948ce09a7b4071f8059294b1972aef6 (patch)
treecb93655417a5475c6baac88691fc92621b3fa7ce /gcc/d
parentbe4a6551ed37c1e7dbdfb9400fc2e2b5d40c5be2 (diff)
downloadgcc-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/d')
-rw-r--r--gcc/d/decl.cc2
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/aggregate.d13
-rw-r--r--gcc/d/dmd/aggregate.h2
-rw-r--r--gcc/d/dmd/apply.d25
-rw-r--r--gcc/d/dmd/arrayop.d12
-rw-r--r--gcc/d/dmd/attrib.d4
-rw-r--r--gcc/d/dmd/canthrow.d6
-rw-r--r--gcc/d/dmd/chkformat.d600
-rw-r--r--gcc/d/dmd/clone.d6
-rw-r--r--gcc/d/dmd/cparse.d19
-rw-r--r--gcc/d/dmd/dcast.d4
-rw-r--r--gcc/d/dmd/declaration.h4
-rw-r--r--gcc/d/dmd/dimport.d7
-rw-r--r--gcc/d/dmd/dinterpret.d12
-rw-r--r--gcc/d/dmd/dmangle.d17
-rw-r--r--gcc/d/dmd/doc.d4
-rw-r--r--gcc/d/dmd/dsymbol.d6
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d48
-rw-r--r--gcc/d/dmd/dtemplate.d71
-rw-r--r--gcc/d/dmd/escape.d5
-rw-r--r--gcc/d/dmd/expression.d20
-rw-r--r--gcc/d/dmd/expression.h22
-rw-r--r--gcc/d/dmd/expressionsem.d92
-rw-r--r--gcc/d/dmd/func.d19
-rw-r--r--gcc/d/dmd/iasmgcc.d8
-rw-r--r--gcc/d/dmd/id.d2
-rw-r--r--gcc/d/dmd/init.d1
-rw-r--r--gcc/d/dmd/init.h1
-rw-r--r--gcc/d/dmd/initsem.d553
-rw-r--r--gcc/d/dmd/lexer.d9
-rw-r--r--gcc/d/dmd/module.h2
-rw-r--r--gcc/d/dmd/mtype.d649
-rw-r--r--gcc/d/dmd/mtype.h4
-rw-r--r--gcc/d/dmd/opover.d9
-rw-r--r--gcc/d/dmd/parse.d102
-rw-r--r--gcc/d/dmd/root/object.h2
-rw-r--r--gcc/d/dmd/semantic3.d40
-rw-r--r--gcc/d/dmd/transitivevisitor.d73
-rw-r--r--gcc/d/dmd/typesem.d18
-rw-r--r--gcc/d/expr.cc33
-rw-r--r--gcc/d/runtime.def5
43 files changed, 1284 insertions, 1251 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),