aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 03:07:41 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 03:13:00 +0200
commit0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3 (patch)
tree8c549ddd4b93c78f44959d47a4956837022a5cf1 /gcc/d
parentd41a57c46df6f8f7dae0c0a8b349e734806a837b (diff)
downloadgcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.zip
gcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.tar.gz
gcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.tar.bz2
d: Merge upstream dmd, druntime 17ccd12af3, phobos 8d3800bee.
D front-end changes: - Import dmd v2.104.0. - Assignment-style syntax is now allowed for `alias this'. - Overloading `extern(C)' functions is now an error. D runtime changes: - Import druntime v2.104.0. Phobos changes: - Import phobos v2.104.0. - Better static assert messages when instantiating `std.algorithm.iteration.permutations' with wrong inputs. - Added `std.system.instructionSetArchitecture' and `std.system.ISA'. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 17ccd12af3. * dmd/VERSION: Bump version to v2.104.0. * Make-lang.in (D_FRONTEND_OBJS): Rename d/apply.o to d/postordervisitor.o. * d-codegen.cc (make_location_t): Update for new front-end interface. (build_filename_from_loc): Likewise. (build_assert_call): Likewise. (build_array_bounds_call): Likewise. (build_bounds_index_condition): Likewise. (build_bounds_slice_condition): Likewise. (build_frame_type): Likewise. (get_frameinfo): Likewise. * d-diagnostic.cc (d_diagnostic_report_diagnostic): Likewise. * decl.cc (build_decl_tree): Likewise. (start_function): Likewise. * expr.cc (ExprVisitor::visit (NewExp *)): Replace code generation of `new pointer' with front-end lowering. * runtime.def (NEWITEMT): Remove. (NEWITEMIT): Remove. * toir.cc (IRVisitor::visit (LabelStatement *)): Update for new front-end interface. * typeinfo.cc (check_typeinfo_type): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 17ccd12af3. * src/MERGE: Merge upstream phobos 8d3800bee. gcc/testsuite/ChangeLog: * gdc.dg/asm4.d: Update test.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/Make-lang.in2
-rw-r--r--gcc/d/d-codegen.cc37
-rw-r--r--gcc/d/d-diagnostic.cc2
-rw-r--r--gcc/d/decl.cc4
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/README.md2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/aggregate.d49
-rw-r--r--gcc/d/dmd/canthrow.d11
-rw-r--r--gcc/d/dmd/chkformat.d2
-rw-r--r--gcc/d/dmd/clone.d18
-rw-r--r--gcc/d/dmd/cond.d2
-rw-r--r--gcc/d/dmd/cparse.d117
-rw-r--r--gcc/d/dmd/cppmangle.d10
-rw-r--r--gcc/d/dmd/dcast.d4
-rw-r--r--gcc/d/dmd/dclass.d9
-rw-r--r--gcc/d/dmd/declaration.d8
-rw-r--r--gcc/d/dmd/declaration.h29
-rw-r--r--gcc/d/dmd/delegatize.d2
-rw-r--r--gcc/d/dmd/denum.d7
-rw-r--r--gcc/d/dmd/dimport.d16
-rw-r--r--gcc/d/dmd/dinterpret.d1
-rw-r--r--gcc/d/dmd/doc.d10
-rw-r--r--gcc/d/dmd/dsymbolsem.d26
-rw-r--r--gcc/d/dmd/dtemplate.d318
-rw-r--r--gcc/d/dmd/escape.d36
-rw-r--r--gcc/d/dmd/expression.d63
-rw-r--r--gcc/d/dmd/expression.h3
-rw-r--r--gcc/d/dmd/expressionsem.d85
-rw-r--r--gcc/d/dmd/foreachvar.d2
-rw-r--r--gcc/d/dmd/func.d76
-rw-r--r--gcc/d/dmd/globals.d4
-rw-r--r--gcc/d/dmd/globals.h28
-rw-r--r--gcc/d/dmd/gluelayer.d29
-rw-r--r--gcc/d/dmd/iasm.d9
-rw-r--r--gcc/d/dmd/id.d3
-rw-r--r--gcc/d/dmd/identifier.d21
-rw-r--r--gcc/d/dmd/importc.d13
-rw-r--r--gcc/d/dmd/initsem.d3
-rw-r--r--gcc/d/dmd/lexer.d12
-rw-r--r--gcc/d/dmd/location.d78
-rw-r--r--gcc/d/dmd/mtype.d6
-rw-r--r--gcc/d/dmd/nogc.d2
-rw-r--r--gcc/d/dmd/ob.d1
-rw-r--r--gcc/d/dmd/opover.d52
-rw-r--r--gcc/d/dmd/optimize.d5
-rw-r--r--gcc/d/dmd/parse.d87
-rw-r--r--gcc/d/dmd/postordervisitor.d (renamed from gcc/d/dmd/apply.d)37
-rw-r--r--gcc/d/dmd/semantic2.d4
-rw-r--r--gcc/d/dmd/sideeffect.d8
-rw-r--r--gcc/d/dmd/statementsem.d18
-rw-r--r--gcc/d/dmd/tokens.d2
-rw-r--r--gcc/d/dmd/traits.d4
-rw-r--r--gcc/d/dmd/transitivevisitor.d10
-rw-r--r--gcc/d/dmd/typesem.d2
-rw-r--r--gcc/d/expr.cc18
-rw-r--r--gcc/d/runtime.def5
-rw-r--r--gcc/d/toir.cc4
-rw-r--r--gcc/d/typeinfo.cc2
59 files changed, 898 insertions, 524 deletions
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 4fbf209..264ae03 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -81,7 +81,6 @@ D_FRONTEND_OBJS = \
d/access.o \
d/aggregate.o \
d/aliasthis.o \
- d/apply.o \
d/arrayop.o \
d/arraytypes.o \
d/attrib.o \
@@ -160,6 +159,7 @@ D_FRONTEND_OBJS = \
d/parse.o \
d/parsetimevisitor.o \
d/permissivevisitor.o \
+ d/postordervisitor.o \
d/printast.o \
d/root-aav.o \
d/root-array.o \
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 689d1c5..2738958 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -50,11 +50,11 @@ make_location_t (const Loc &loc)
{
location_t gcc_location = input_location;
- if (loc.filename)
+ if (const char *filename = loc.filename ())
{
- linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum);
- linemap_line_start (line_table, loc.linnum, 0);
- gcc_location = linemap_position_for_column (line_table, loc.charnum);
+ linemap_add (line_table, LC_ENTER, 0, filename, loc.linnum ());
+ linemap_line_start (line_table, loc.linnum (), 0);
+ gcc_location = linemap_position_for_column (line_table, loc.charnum ());
linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
}
@@ -1872,8 +1872,10 @@ void_okay_p (tree t)
static tree
build_filename_from_loc (const Loc &loc)
{
- const char *filename = loc.filename
- ? loc.filename : d_function_chain->module->srcfile.toChars ();
+ const char *filename = loc.filename ();
+
+ if (filename == NULL)
+ filename = d_function_chain->module->srcfile.toChars ();
unsigned length = strlen (filename);
tree str = build_string (length, filename);
@@ -1890,17 +1892,17 @@ tree
build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
{
tree file;
- tree line = size_int (loc.linnum);
+ tree line = size_int (loc.linnum ());
switch (libcall)
{
case LIBCALL_ASSERT_MSG:
case LIBCALL_UNITTEST_MSG:
/* File location is passed as a D string. */
- if (loc.filename)
+ if (const char *filename = loc.filename ())
{
- unsigned len = strlen (loc.filename);
- tree str = build_string (len, loc.filename);
+ unsigned len = strlen (filename);
+ tree str = build_string (len, filename);
TREE_TYPE (str) = make_array_type (Type::tchar, len);
file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
@@ -1939,7 +1941,7 @@ build_array_bounds_call (const Loc &loc)
{
return build_libcall (LIBCALL_ARRAYBOUNDSP, Type::tvoid, 2,
build_filename_from_loc (loc),
- size_int (loc.linnum));
+ size_int (loc.linnum ()));
}
}
@@ -1968,7 +1970,8 @@ build_bounds_index_condition (IndexExp *ie, tree index, tree length)
{
boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_INDEXP, Type::tvoid, 4,
build_filename_from_loc (ie->e2->loc),
- size_int (ie->e2->loc.linnum), index, length);
+ size_int (ie->e2->loc.linnum ()),
+ index, length);
}
return build_condition (TREE_TYPE (index), condition, boundserr, index);
@@ -2017,7 +2020,7 @@ build_bounds_slice_condition (SliceExp *se, tree lower, tree upper, tree length)
boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_SLICEP,
Type::tvoid, 5,
build_filename_from_loc (se->loc),
- size_int (se->loc.linnum),
+ size_int (se->loc.linnum ()),
lower, upper, length);
}
@@ -2659,8 +2662,8 @@ build_frame_type (tree ffi, FuncDeclaration *fd)
of the calling function non-locally. So we add all parameters with nested
refs to the function frame, this should also mean overriding methods will
have the same frame layout when inheriting a contract. */
- if ((global.params.useIn == CHECKENABLEon && fd->frequire)
- || (global.params.useOut == CHECKENABLEon && fd->fensure))
+ if ((global.params.useIn == CHECKENABLEon && fd->frequire ())
+ || (global.params.useOut == CHECKENABLEon && fd->fensure ()))
{
if (fd->parameters)
{
@@ -2870,8 +2873,8 @@ get_frameinfo (FuncDeclaration *fd)
/* In checkNestedReference, references from contracts are not added to the
closureVars array, so assume all parameters referenced. */
- if ((global.params.useIn == CHECKENABLEon && fd->frequire)
- || (global.params.useOut == CHECKENABLEon && fd->fensure))
+ if ((global.params.useIn == CHECKENABLEon && fd->frequire ())
+ || (global.params.useOut == CHECKENABLEon && fd->fensure ()))
FRAMEINFO_CREATES_FRAME (ffi) = 1;
/* If however `fd` is nested (deeply) in a function that creates a
diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc
index c3bde46..7e5b17c 100644
--- a/gcc/d/d-diagnostic.cc
+++ b/gcc/d/d-diagnostic.cc
@@ -189,7 +189,7 @@ d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format,
va_list argp;
va_copy (argp, ap);
- if (loc.filename || !verbatim)
+ if (loc.filename () || !verbatim)
{
rich_location rich_loc (line_table, make_location_t (loc));
diagnostic_info diagnostic;
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 0375ede..b866593 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1083,7 +1083,7 @@ build_decl_tree (Dsymbol *d)
location_t saved_location = input_location;
/* Set input location, empty DECL_SOURCE_FILE can crash debug generator. */
- if (d->loc.filename)
+ if (d->loc.filename ())
input_location = make_location_t (d->loc);
else
input_location = make_location_t (Loc ("<no_file>", 1, 0));
@@ -2064,7 +2064,7 @@ start_function (FuncDeclaration *fd)
allocate_struct_function (fndecl, false);
/* Store the end of the function. */
- if (fd->endloc.filename)
+ if (fd->endloc.filename ())
cfun->function_end_locus = make_location_t (fd->endloc);
else
cfun->function_end_locus = DECL_SOURCE_LOCATION (fndecl);
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 95ea67d..1cff48a 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-28a3b24c2e45de39cd3df528142fd06b6456e8fd
+17ccd12af386543c0b9935bf7e0a8e701b903105
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/README.md b/gcc/d/dmd/README.md
index 57f56f3..79215b7 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -99,7 +99,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| [strictvisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/strictvisitor.d) | Visitor that forces derived classes to implement `visit` for every possible node |
| [visitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor.d) | A visitor implementing `visit` for all nodes present in the compiler |
| [transitivevisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/transitivevisitor.d) | Provide a mixin template with visit methods for the parse time AST |
-| [apply.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/apply.d) | Depth-first expression visitor |
+| [postordervisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/postordervisitor.d) | Depth-first expression visitor |
| [sapply.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/sapply.d) | Depth-first statement visitor |
| [statement_rewrite_walker.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statement_rewrite_walker.d) | Statement visitor that allows replacing the currently visited node |
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 7cf9127..d5aee89 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.104.0-beta.1
+v2.104.0
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 1306a10..42b926b 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -18,7 +18,6 @@ import core.stdc.stdio;
import core.checkedint;
import dmd.aliasthis;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
import dmd.attrib;
@@ -764,21 +763,18 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
if (s)
{
// Finish all constructors semantics to determine this.noDefaultCtor.
- struct SearchCtor
+ static int searchCtor(Dsymbol s, void*)
{
- extern (C++) static int fp(Dsymbol s, void* ctxt)
- {
- auto f = s.isCtorDeclaration();
- if (f && f.semanticRun == PASS.initial)
- f.dsymbolSemantic(null);
- return 0;
- }
+ auto f = s.isCtorDeclaration();
+ if (f && f.semanticRun == PASS.initial)
+ f.dsymbolSemantic(null);
+ return 0;
}
for (size_t i = 0; i < members.length; i++)
{
auto sm = (*members)[i];
- sm.apply(&SearchCtor.fp, null);
+ sm.apply(&searchCtor, null);
}
}
return s;
@@ -814,3 +810,36 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
v.visit(this);
}
}
+
+/*********************************
+ * Iterate this dsymbol or members of this scoped dsymbol, then
+ * call `fp` with the found symbol and `params`.
+ * Params:
+ * symbol = the dsymbol or parent of members to call fp on
+ * fp = function pointer to process the iterated symbol.
+ * If it returns nonzero, the iteration will be aborted.
+ * ctx = context parameter passed to fp.
+ * Returns:
+ * nonzero if the iteration is aborted by the return value of fp,
+ * or 0 if it's completed.
+ */
+int apply(Dsymbol symbol, int function(Dsymbol, void*) fp, void* ctx)
+{
+ if (auto nd = symbol.isNspace())
+ {
+ return nd.members.foreachDsymbol( (s) { return s && s.apply(fp, ctx); } );
+ }
+ if (auto ad = symbol.isAttribDeclaration())
+ {
+ return ad.include(ad._scope).foreachDsymbol( (s) { return s && s.apply(fp, ctx); } );
+ }
+ if (auto tm = symbol.isTemplateMixin())
+ {
+ if (tm._scope) // if fwd reference
+ dsymbolSemantic(tm, null); // try to resolve it
+
+ return tm.members.foreachDsymbol( (s) { return s && s.apply(fp, ctx); } );
+ }
+
+ return fp(symbol, ctx);
+}
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 7dfec8a..09d39ca 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -14,7 +14,6 @@
module dmd.canthrow;
import dmd.aggregate;
-import dmd.apply;
import dmd.arraytypes;
import dmd.attrib;
import dmd.astenums;
@@ -26,6 +25,7 @@ import dmd.func;
import dmd.globals;
import dmd.init;
import dmd.mtype;
+import dmd.postordervisitor;
import dmd.root.rootobject;
import dmd.tokens;
import dmd.visitor;
@@ -133,16 +133,9 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
*/
if (ce.f && ce.f == func)
return;
- Type t = ce.e1.type.toBasetype();
- auto tf = t.isTypeFunction();
+ const tf = ce.calledFunctionType();
if (tf && tf.isnothrow)
return;
- else
- {
- auto td = t.isTypeDelegate();
- if (td && td.nextOf().isTypeFunction().isnothrow)
- return;
- }
if (ce.f)
checkFuncThrows(ce, ce.f);
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index 21a1b5e..feaa3c7 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -177,6 +177,8 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
errorMsg(null, e, (c_longsize == 4 ? "uint" : "ulong"), t);
else
errorMsg(null, e, (c_longsize == 4 ? "int" : "long"), t);
+ if (t.isintegral() && t.size() != c_longsize)
+ errorSupplemental(e.loc, "C `long` is %d bytes on your system", c_longsize);
}
break;
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 60e373c..3586f20 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -106,18 +106,18 @@ 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;
- auto a = Expressions(1);
+ auto a = new Expressions(1);
const errors = global.startGagging(); // Do not report errors, even if the template opAssign fbody makes it.
sc = sc.push();
sc.tinst = null;
sc.minst = null;
- a[0] = er;
- auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(&a), FuncResolveFlag.quiet);
+ (*a)[0] = er;
+ auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(a), FuncResolveFlag.quiet);
if (!f)
{
- a[0] = el;
- f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(&a), FuncResolveFlag.quiet);
+ (*a)[0] = el;
+ f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(a), FuncResolveFlag.quiet);
}
sc = sc.pop();
@@ -465,7 +465,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
- auto a = Expressions(1);
+ auto a = new Expressions(1);
bool hasIt(Type tthis)
{
@@ -476,9 +476,9 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc)
FuncDeclaration rfc(Expression e)
{
- a[0] = e;
- a[0].type = tthis;
- return resolveFuncCall(ad.loc, sc, eq, null, tthis, ArgumentList(&a), FuncResolveFlag.quiet);
+ (*a)[0] = e;
+ (*a)[0].type = tthis;
+ return resolveFuncCall(ad.loc, sc, eq, null, tthis, ArgumentList(a), FuncResolveFlag.quiet);
}
f = rfc(er);
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index c40936c..fcb50e0 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -259,7 +259,7 @@ extern (C++) final class StaticForeach : RootObject
auto sdecl = new StructDeclaration(loc, sid, false);
sdecl.storage_class |= STC.static_;
sdecl.members = new Dsymbols();
- auto fid = Identifier.idPool(tupleFieldName.ptr, tupleFieldName.length);
+ auto fid = Identifier.idPool(tupleFieldName);
auto ty = new TypeTypeof(loc, new TupleExp(loc, e));
sdecl.members.push(new VarDeclaration(loc, ty, fid, null, 0));
auto r = cast(TypeStruct)sdecl.type;
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 9b7db1f..33669e3 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -324,6 +324,8 @@ final class CParser(AST) : Parser!AST
// atomic-type-specifier or type_qualifier
case TOK._Atomic:
+ case TOK.__attribute__:
+
Ldeclaration:
{
cparseDeclaration(LVL.local);
@@ -2356,6 +2358,8 @@ final class CParser(AST) : Parser!AST
cparseGnuAttributes(tagSpecifier);
else if (token.value == TOK.__declspec)
cparseDeclspec(tagSpecifier);
+ else if (token.value == TOK.__pragma)
+ uupragmaDirective(sloc);
else
break;
}
@@ -2710,7 +2714,7 @@ final class CParser(AST) : Parser!AST
*
* Params:
* declarator = declarator kind
- * t = base type to start with
+ * tbase = base type to start with
* pident = set to Identifier if there is one, null if not
* specifier = specifiers in and out
* Returns:
@@ -2718,12 +2722,26 @@ final class CParser(AST) : Parser!AST
* symbol table for the parameter-type-list, which will contain any
* declared struct, union or enum tags.
*/
- private AST.Type cparseDeclarator(DTR declarator, AST.Type t,
+ private AST.Type cparseDeclarator(DTR declarator, AST.Type tbase,
out Identifier pident, ref Specifier specifier)
{
//printf("cparseDeclarator(%d, %p)\n", declarator, t);
AST.Types constTypes; // all the Types that will need `const` applied to them
+ /* Insert tx -> t into
+ * ts -> ... -> t
+ * so that
+ * ts -> ... -> tx -> t
+ */
+ static void insertTx(ref AST.Type ts, AST.Type tx, AST.Type t)
+ {
+ AST.Type* pt;
+ for (pt = &ts; *pt != t; pt = &(cast(AST.TypeNext)*pt).next)
+ {
+ }
+ *pt = tx;
+ }
+
AST.Type parseDecl(AST.Type t)
{
AST.Type ts;
@@ -2789,20 +2807,6 @@ final class CParser(AST) : Parser!AST
// parse DeclaratorSuffixes
while (1)
{
- /* Insert tx -> t into
- * ts -> ... -> t
- * so that
- * ts -> ... -> tx -> t
- */
- static void insertTx(ref AST.Type ts, AST.Type tx, AST.Type t)
- {
- AST.Type* pt;
- for (pt = &ts; *pt != t; pt = &(cast(AST.TypeNext)*pt).next)
- {
- }
- *pt = tx;
- }
-
switch (token.value)
{
case TOK.leftBracket:
@@ -2915,7 +2919,17 @@ final class CParser(AST) : Parser!AST
return ts;
}
- t = parseDecl(t);
+ auto t = parseDecl(tbase);
+
+ if (specifier.vector_size)
+ {
+ auto length = new AST.IntegerExp(token.loc, specifier.vector_size / tbase.size(), AST.Type.tuns32);
+ auto tsa = new AST.TypeSArray(tbase, length);
+ AST.Type tv = new AST.TypeVector(tsa);
+ specifier.vector_size = 0; // used it up
+
+ insertTx(t, tv, tbase); // replace tbase with tv
+ }
/* Because const is transitive, cannot assemble types from
* fragments. Instead, types to be annotated with const are put
@@ -3553,7 +3567,19 @@ final class CParser(AST) : Parser!AST
{
nextToken();
check(TOK.leftParenthesis);
- cparseConstantExp(); // TODO implement
+ if (token.value == TOK.int32Literal)
+ {
+ const n = token.unsvalue;
+ if (n < 1 || n & (n - 1) || ushort.max < n)
+ error("__attribute__((vector_size(%lld))) must be an integer positive power of 2 and be <= 32,768", cast(ulong)n);
+ specifier.vector_size = cast(uint) n;
+ nextToken();
+ }
+ else
+ {
+ error("value for vector_size expected, not `%s`", token.toChars());
+ nextToken();
+ }
check(TOK.rightParenthesis);
}
else
@@ -3852,6 +3878,10 @@ final class CParser(AST) : Parser!AST
else if (!tag)
error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
+ // many ways and places to declare alignment
+ if (packalign.isUnknown() && !this.packalign.isUnknown())
+ packalign.set(this.packalign.get());
+
/* Need semantic information to determine if this is a declaration,
* redeclaration, or reference to existing declaration.
* Defer to the semantic() pass with a TypeTag.
@@ -4694,6 +4724,7 @@ final class CParser(AST) : Parser!AST
// atomic-type-specifier
case TOK._Atomic:
case TOK.typeof_:
+ case TOK.__attribute__:
t = peek(t);
if (t.value != TOK.leftParenthesis ||
!skipParens(t, &t))
@@ -4959,6 +4990,7 @@ final class CParser(AST) : Parser!AST
bool dllexport; /// dllexport attribute
bool _deprecated; /// deprecated attribute
AST.Expression depMsg; /// deprecated message
+ uint vector_size; /// positive power of 2 multipe of base type size
SCW scw; /// storage-class specifiers
MOD mod; /// type qualifiers
@@ -5400,6 +5432,24 @@ final class CParser(AST) : Parser!AST
pragmaDirective(scanloc);
return true;
}
+ else if (n.ident == Id.ident) // #ident "string"
+ {
+ scan(&n);
+ if (n.value == TOK.string_ && n.ptr[0] == '"' && n.postfix == 0)
+ {
+ /* gcc inserts string into the .comment section in the object file.
+ * Just ignore it for now, but can support it later by writing
+ * the string to obj_exestr()
+ */
+ //auto comment = n.ustring;
+
+ scan(&n);
+ if (n.value == TOK.endOfFile || n.value == TOK.endOfLine)
+ return true;
+ }
+ error("\"string\" expected after `#ident`");
+ return false;
+ }
}
if (n.ident != Id.undef)
error("C preprocessor directive `#%s` is not supported", n.toChars());
@@ -5416,20 +5466,39 @@ final class CParser(AST) : Parser!AST
private void uupragmaDirective(const ref Loc startloc)
{
const loc = startloc;
- nextToken();
+ nextToken(); // move past __pragma
if (token.value != TOK.leftParenthesis)
{
- error(loc, "left parenthesis expected to follow `__pragma`");
+ error(loc, "left parenthesis expected to follow `__pragma` instead of `%s`", token.toChars());
+ nextToken();
return;
}
nextToken();
- if (token.value == TOK.identifier && token.ident == Id.pack)
- pragmaPack(startloc, false);
+
+ if (token.value == TOK.identifier)
+ {
+ if (token.ident == Id.pack)
+ pragmaPack(startloc, false);
+ else
+ {
+ nextToken();
+ if (token.value == TOK.leftParenthesis)
+ cparseParens();
+ }
+
+ }
+ else if (token.value == TOK.endOfFile)
+ {
+ }
+ else if (token.value == TOK.rightParenthesis)
+ {
+ }
else
- error(loc, "unrecognized __pragma");
+ error(loc, "unrecognized `__pragma(%s)`", token.toChars());
+
if (token.value != TOK.rightParenthesis)
{
- error(loc, "right parenthesis expected to close `__pragma(...)`");
+ error(loc, "right parenthesis expected to close `__pragma(...)` instead of `%s`", token.toChars());
return;
}
nextToken();
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 40092c3..ee1340d 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -446,7 +446,15 @@ private final class CppMangleVisitor : Visitor
if (this.context.res.dyncast() == DYNCAST.dsymbol)
parentti = this.context.res.asFuncDecl().parent.isTemplateInstance();
else
- parentti = this.context.res.asType().toDsymbol(null).parent.isTemplateInstance();
+ {
+ auto parent = this.context.res.asType().toDsymbol(null).parent;
+ parentti = parent.isTemplateInstance();
+ // https://issues.dlang.org/show_bug.cgi?id=22760
+ // The template instance may sometimes have the form
+ // S1!int.S1, therefore the above instruction might yield null
+ if (parentti is null && parent.parent)
+ parentti = parent.parent.isTemplateInstance();
+ }
return (*parentti.tiargs)[arg];
}());
scope (exit) this.context.pop(prev);
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 8ffbef3c..6fcc280 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -71,6 +71,8 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
{
+ // no need for an extra cast when matching is exact
+
if (match == MATCH.convert && e.type.isTypeNoreturn())
{
return specialNoreturnCast(e, t);
@@ -88,6 +90,8 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
auto ad = isAggregate(e.type);
if (ad && ad.aliasthis)
{
+ if (!ad.type || ad.type.isTypeError())
+ return e;
auto ts = ad.type.isTypeStruct();
const adMatch = ts
? ts.implicitConvToWithoutAliasThis(t)
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index e458593..1b8e8ef 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -17,7 +17,6 @@ import core.stdc.stdio;
import core.stdc.string;
import dmd.aggregate;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
import dmd.attrib;
@@ -867,7 +866,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
* Resolve forward references to all class member functions,
* and determine whether this class is abstract.
*/
- static int func(Dsymbol s)
+ static int func(Dsymbol s, void*)
{
auto fd = s.isFuncDeclaration();
if (!fd)
@@ -883,7 +882,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
for (size_t i = 0; i < members.length; i++)
{
auto s = (*members)[i];
- if (s.apply(&func))
+ if (s.apply(&func, null))
{
return yes();
}
@@ -910,7 +909,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
* each of the virtual functions,
* which will fill in the vtbl[] overrides.
*/
- static int virtualSemantic(Dsymbol s)
+ static int virtualSemantic(Dsymbol s, void*)
{
auto fd = s.isFuncDeclaration();
if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration())
@@ -921,7 +920,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
for (size_t i = 0; i < members.length; i++)
{
auto s = (*members)[i];
- s.apply(&virtualSemantic);
+ s.apply(&virtualSemantic,null);
}
}
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 0e5df5e..cfa6988 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -44,6 +44,10 @@ import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
/************************************
* Check to see the aggregate type is nested and its context pointer is
* accessible from the current scope.
@@ -633,9 +637,7 @@ extern (C++) final class TupleDeclaration : Declaration
version (none)
{
buf.printf("_%s_%d", ident.toChars(), i);
- const len = buf.offset;
- const name = buf.extractSlice().ptr;
- auto id = Identifier.idPool(name, len);
+ auto id = Identifier.idPool(buf.extractSlice());
auto arg = new Parameter(STC.in_, t, id, null);
}
else
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 7a69382..197091e 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -534,22 +534,19 @@ enum class BUILTIN : unsigned char
Expression *eval_builtin(const Loc &loc, FuncDeclaration *fd, Expressions *arguments);
BUILTIN isBuiltin(FuncDeclaration *fd);
+struct ContractInfo;
+
class FuncDeclaration : public Declaration
{
public:
- Statements *frequires; // in contracts
- Ensures *fensures; // out contracts
- Statement *frequire; // lowered in contract
- Statement *fensure; // lowered out contract
Statement *fbody;
FuncDeclarations foverrides; // functions this function overrides
- FuncDeclaration *fdrequire; // function that does the in contract
- FuncDeclaration *fdensure; // function that does the out contract
- Expressions *fdrequireParams; // argument list for __require
- Expressions *fdensureParams; // argument list for __ensure
+private:
+ ContractInfo *contracts; // contract information
+public:
const char *mangleString; // mangled symbol created from mangleExact()
VarDeclaration *vresult; // result variable for out contracts
@@ -686,6 +683,22 @@ public:
static FuncDeclaration *create(const Loc &loc, const Loc &endloc, Identifier *id, StorageClass storage_class, Type *type, bool noreturn = false);
FuncDeclaration *syntaxCopy(Dsymbol *) override;
+ Statements *frequires();
+ Ensures *fensures();
+ Statement *frequire();
+ Statement *fensure();
+ FuncDeclaration *fdrequire();
+ FuncDeclaration *fdensure();
+ Expressions *fdrequireParams();
+ Expressions *fdensureParams();
+ Statements *frequires(Statements *frs);
+ Ensures *fensures(Statements *fes);
+ Statement *frequire(Statement *fr);
+ Statement *fensure(Statement *fe);
+ FuncDeclaration *fdrequire(FuncDeclaration *fdr);
+ FuncDeclaration *fdensure(FuncDeclaration *fde);
+ Expressions *fdrequireParams(Expressions *fdrp);
+ Expressions *fdensureParams(Expressions *fdep);
bool functionSemantic();
bool functionSemantic3();
bool equals(const RootObject * const o) const override final;
diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d
index fd95691..b135bfa 100644
--- a/gcc/d/dmd/delegatize.d
+++ b/gcc/d/dmd/delegatize.d
@@ -14,7 +14,6 @@
module dmd.delegatize;
import core.stdc.stdio;
-import dmd.apply;
import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
@@ -27,6 +26,7 @@ import dmd.init;
import dmd.initsem;
import dmd.location;
import dmd.mtype;
+import dmd.postordervisitor;
import dmd.statement;
import dmd.tokens;
import dmd.visitor;
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 221250b..87b40b8 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -169,7 +169,12 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return defaultval;
}
//printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
- if (defaultval)
+ // https://issues.dlang.org/show_bug.cgi?id=23904
+ // Return defaultval only if it is not ErrorExp.
+ // A speculative context may set defaultval to ErrorExp;
+ // subsequent non-speculative contexts need to be able
+ // to print the error.
+ if (defaultval && !defaultval.isErrorExp())
return defaultval;
if (isCsymbol())
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index b653d9b..c4d5ddb 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -26,6 +26,7 @@ import dmd.location;
import dmd.mtype;
import dmd.visitor;
+import core.stdc.stdio;
/***********************************************************
*/
extern (C++) final class Import : Dsymbol
@@ -232,7 +233,20 @@ extern (C++) final class Import : Dsymbol
* most likely because of parsing errors.
* Therefore we cannot trust the resulting AST.
*/
- if (load(sc)) return;
+ if (load(sc))
+ {
+ // https://issues.dlang.org/show_bug.cgi?id=23873
+ // For imports that are not at module or function level,
+ // e.g. aggregate level, the import symbol is added to the
+ // symbol table and later semantic is performed on it.
+ // This leads to semantic analysis on an malformed AST
+ // which causes all kinds of segfaults.
+ // The fix is to note that the module has errors and avoid
+ // semantic analysis on it.
+ if(mod)
+ mod.errors = true;
+ return;
+ }
if (!mod) return; // Failed
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 4ef6a39..5b27a07 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -16,7 +16,6 @@ module dmd.dinterpret;
import core.stdc.stdio;
import core.stdc.stdlib;
import core.stdc.string;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
import dmd.attrib;
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 7674f77..3e60dc4 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -429,9 +429,9 @@ extern(C++) void gendocfile(Module m)
if (m.filetype == FileType.ddoc)
{
const ploc = m.md ? &m.md.loc : &m.loc;
- const loc = Loc(ploc.filename ? ploc.filename : srcfilename.ptr,
- ploc.linnum,
- ploc.charnum);
+ Loc loc = *ploc;
+ if (!loc.filename)
+ loc.filename = srcfilename.ptr;
size_t commentlen = strlen(cast(char*)m.comment);
Dsymbols a;
@@ -4151,7 +4151,7 @@ private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, con
private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset)
{
const incrementLoc = loc.linnum == 0 ? 1 : 0;
- loc.linnum += incrementLoc;
+ loc.linnum = loc.linnum + incrementLoc;
loc.charnum = 0;
//printf("highlightText()\n");
bool leadingBlank = true;
@@ -4256,7 +4256,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
lineQuoted = false;
tableRowDetected = false;
iLineStart = i + 1;
- loc.linnum += incrementLoc;
+ loc.linnum = loc.linnum + incrementLoc;
// update the paragraph start if we just entered a macro
if (previousMacroLevel < macroLevel && iParagraphStart < iLineStart)
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 506946f..a5cd63b 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -17,7 +17,6 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.aliasthis;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
@@ -78,6 +77,10 @@ import dmd.templateparamsem;
import dmd.typesem;
import dmd.visitor;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
enum LOG = false;
private uint setMangleOverride(Dsymbol s, const(char)[] sym)
@@ -484,7 +487,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Infering the type requires running semantic,
// so mark the scope as ctfe if required
- bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0;
+ bool needctfe = (dsym.storage_class & (STC.manifest | STC.static_)) != 0 || !sc.func;
if (needctfe)
{
sc.flags |= SCOPE.condition;
@@ -1366,9 +1369,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
static if (LOG)
{
- printf("Import::semantic('%s') %s\n", toPrettyChars(), id.toChars());
+ printf("Import::semantic('%s') %s\n", imp.toPrettyChars(), imp.id.toChars());
scope(exit)
- printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
+ printf("-Import::semantic('%s'), pkg = %p\n", imp.toChars(), imp.pkg);
}
if (imp.semanticRun > PASS.initial)
return;
@@ -1434,7 +1437,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
imp.addPackageAccess(scopesym);
}
- imp.mod.dsymbolSemantic(null);
+ // if a module has errors it means that parsing has failed.
+ if (!imp.mod.errors)
+ imp.mod.dsymbolSemantic(null);
if (imp.mod.needmoduleinfo)
{
@@ -1463,7 +1468,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
else
{
Dsymbol s = imp.mod.search_correct(imp.names[i]);
- if (s)
+ // https://issues.dlang.org/show_bug.cgi?id=23908
+ // Don't suggest symbols from the importer's module
+ if (s && s.parent != importer)
imp.mod.error(imp.loc, "import `%s` not found, did you mean %s `%s`?", imp.names[i].toChars(), s.kind(), s.toPrettyChars());
else
imp.mod.error(imp.loc, "import `%s` not found", imp.names[i].toChars());
@@ -7124,8 +7131,9 @@ bool determineFields(AggregateDeclaration ad)
// determineFields can be called recursively from one of the fields's v.semantic
ad.fields.setDim(0);
- static int func(Dsymbol s, AggregateDeclaration ad)
+ static int func(Dsymbol s, void* ctx)
{
+ auto ad = cast(AggregateDeclaration)ctx;
auto v = s.isVarDeclaration();
if (!v)
return 0;
@@ -7141,7 +7149,7 @@ bool determineFields(AggregateDeclaration ad)
if (v.aliasTuple)
{
// If this variable was really a tuple, process each element.
- return v.aliasTuple.foreachVar(tv => tv.apply(&func, ad));
+ return v.aliasTuple.foreachVar(tv => tv.apply(&func, cast(void*) ad));
}
if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
@@ -7173,7 +7181,7 @@ bool determineFields(AggregateDeclaration ad)
for (size_t i = 0; i < ad.members.length; i++)
{
auto s = (*ad.members)[i];
- if (s.apply(&func, ad))
+ if (s.apply(&func, cast(void *)ad))
{
if (ad.sizeok != Sizeok.none)
{
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index ef743d6..5b98d2f 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -4141,185 +4141,207 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
goto Lnomatch;
L2:
- for (size_t i = 0; 1; i++)
+ if (!resolveTemplateInstantiation(t.tempinst.tiargs, &t.tempinst.tdtypes, tempdecl, tp, dedtypes))
+ goto Lnomatch;
+ }
+ visit(cast(Type)t);
+ return;
+
+ Lnomatch:
+ //printf("no match\n");
+ result = MATCH.nomatch;
+ }
+
+ /********************
+ * Match template `parameters` to the target template instance.
+ * Example:
+ * struct Temp(U, int Z) {}
+ * void foo(T)(Temp!(T, 3));
+ * foo(Temp!(int, 3)());
+ * Input:
+ * this.parameters = template params of foo -> [T]
+ * tiargs = <Temp!(int, 3)>.tiargs -> [int, 3]
+ * tdtypes = <Temp!(int, 3)>.tdtypes -> [int, 3]
+ * tempdecl = <struct Temp!(T, int Z)> -> [T, Z]
+ * tp = <Temp!(T, 3)>
+ * Output:
+ * dedtypes = deduced params of `foo(Temp!(int, 3)())` -> [int]
+ */
+ private bool resolveTemplateInstantiation(Objects* tiargs, Objects* tdtypes, TemplateDeclaration tempdecl, TypeInstance tp, Objects* dedtypes)
+ {
+ for (size_t i = 0; 1; i++)
+ {
+ //printf("\ttest: tempinst.tiargs[%zu]\n", i);
+ RootObject o1 = null;
+ if (i < tiargs.length)
+ o1 = (*tiargs)[i];
+ else if (i < tdtypes.length && i < tp.tempinst.tiargs.length)
{
- //printf("\ttest: tempinst.tiargs[%zu]\n", i);
- RootObject o1 = null;
- if (i < t.tempinst.tiargs.length)
- o1 = (*t.tempinst.tiargs)[i];
- else if (i < t.tempinst.tdtypes.length && i < tp.tempinst.tiargs.length)
- {
- // Pick up default arg
- o1 = t.tempinst.tdtypes[i];
- }
- else if (i >= tp.tempinst.tiargs.length)
- break;
- //printf("\ttest: o1 = %s\n", o1.toChars());
- if (i >= tp.tempinst.tiargs.length)
+ // Pick up default arg
+ o1 = (*tdtypes)[i];
+ }
+ else if (i >= tp.tempinst.tiargs.length)
+ break;
+ //printf("\ttest: o1 = %s\n", o1.toChars());
+ if (i >= tp.tempinst.tiargs.length)
+ {
+ size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
+ while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
{
- size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
- while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
- {
- i++;
- }
- if (i >= dim)
- break; // match if all remained parameters are dependent
- goto Lnomatch;
+ i++;
}
+ if (i >= dim)
+ break; // match if all remained parameters are dependent
+ return false;
+ }
- RootObject o2 = (*tp.tempinst.tiargs)[i];
- Type t2 = isType(o2);
- //printf("\ttest: o2 = %s\n", o2.toChars());
- size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
- ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
- if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
- (*parameters)[j].isTemplateTupleParameter())
- {
- /* Given:
+ RootObject o2 = (*tp.tempinst.tiargs)[i];
+ Type t2 = isType(o2);
+ //printf("\ttest: o2 = %s\n", o2.toChars());
+ size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
+ ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
+ if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
+ (*parameters)[j].isTemplateTupleParameter())
+ {
+ /* Given:
* struct A(B...) {}
* alias A!(int, float) X;
* static if (is(X Y == A!(Z), Z...)) {}
* deduce that Z is a tuple(int, float)
*/
- /* Create tuple from remaining args
+ /* Create tuple from remaining args
*/
- size_t vtdim = (tempdecl.isVariadic() ? t.tempinst.tiargs.length : t.tempinst.tdtypes.length) - i;
- auto vt = new Tuple(vtdim);
- for (size_t k = 0; k < vtdim; k++)
- {
- RootObject o;
- if (k < t.tempinst.tiargs.length)
- o = (*t.tempinst.tiargs)[i + k];
- else // Pick up default arg
- o = t.tempinst.tdtypes[i + k];
- vt.objects[k] = o;
- }
-
- Tuple v = cast(Tuple)(*dedtypes)[j];
- if (v)
- {
- if (!match(v, vt))
- goto Lnomatch;
- }
- else
- (*dedtypes)[j] = vt;
- break;
- }
- else if (!o1)
- break;
-
- Type t1 = isType(o1);
- Dsymbol s1 = isDsymbol(o1);
- Dsymbol s2 = isDsymbol(o2);
- Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
- Expression e2 = isExpression(o2);
- version (none)
+ size_t vtdim = (tempdecl.isVariadic() ? tiargs.length : tdtypes.length) - i;
+ auto vt = new Tuple(vtdim);
+ for (size_t k = 0; k < vtdim; k++)
{
- Tuple v1 = isTuple(o1);
- Tuple v2 = isTuple(o2);
- if (t1)
- printf("t1 = %s\n", t1.toChars());
- if (t2)
- printf("t2 = %s\n", t2.toChars());
- if (e1)
- printf("e1 = %s\n", e1.toChars());
- if (e2)
- printf("e2 = %s\n", e2.toChars());
- if (s1)
- printf("s1 = %s\n", s1.toChars());
- if (s2)
- printf("s2 = %s\n", s2.toChars());
- if (v1)
- printf("v1 = %s\n", v1.toChars());
- if (v2)
- printf("v2 = %s\n", v2.toChars());
+ RootObject o;
+ if (k < tiargs.length)
+ o = (*tiargs)[i + k];
+ else // Pick up default arg
+ o = (*tdtypes)[i + k];
+ vt.objects[k] = o;
}
- if (t1 && t2)
+ Tuple v = cast(Tuple)(*dedtypes)[j];
+ if (v)
{
- if (!deduceType(t1, sc, t2, parameters, dedtypes))
- goto Lnomatch;
+ if (!match(v, vt))
+ return false;
}
- else if (e1 && e2)
- {
- Le:
- e1 = e1.ctfeInterpret();
+ else
+ (*dedtypes)[j] = vt;
+ break;
+ }
+ else if (!o1)
+ break;
- /* If it is one of the template parameters for this template,
+ Type t1 = isType(o1);
+ Dsymbol s1 = isDsymbol(o1);
+ Dsymbol s2 = isDsymbol(o2);
+ Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
+ Expression e2 = isExpression(o2);
+ version (none)
+ {
+ Tuple v1 = isTuple(o1);
+ Tuple v2 = isTuple(o2);
+ if (t1)
+ printf("t1 = %s\n", t1.toChars());
+ if (t2)
+ printf("t2 = %s\n", t2.toChars());
+ if (e1)
+ printf("e1 = %s\n", e1.toChars());
+ if (e2)
+ printf("e2 = %s\n", e2.toChars());
+ if (s1)
+ printf("s1 = %s\n", s1.toChars());
+ if (s2)
+ printf("s2 = %s\n", s2.toChars());
+ if (v1)
+ printf("v1 = %s\n", v1.toChars());
+ if (v2)
+ printf("v2 = %s\n", v2.toChars());
+ }
+
+ if (t1 && t2)
+ {
+ if (!deduceType(t1, sc, t2, parameters, dedtypes))
+ return false;
+ }
+ else if (e1 && e2)
+ {
+ Le:
+ e1 = e1.ctfeInterpret();
+
+ /* If it is one of the template parameters for this template,
* we should not attempt to interpret it. It already has a value.
*/
- if (e2.op == EXP.variable && (e2.isVarExp().var.storage_class & STC.templateparameter))
- {
- /*
+ if (e2.op == EXP.variable && (e2.isVarExp().var.storage_class & STC.templateparameter))
+ {
+ /*
* (T:Number!(e2), int e2)
*/
- j = templateIdentifierLookup(e2.isVarExp().var.ident, parameters);
- if (j != IDX_NOTFOUND)
- goto L1;
- // The template parameter was not from this template
- // (it may be from a parent template, for example)
- }
-
- e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
- e2 = e2.ctfeInterpret();
+ j = templateIdentifierLookup(e2.isVarExp().var.ident, parameters);
+ if (j != IDX_NOTFOUND)
+ goto L1;
+ // The template parameter was not from this template
+ // (it may be from a parent template, for example)
+ }
- //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
- //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
- if (!e1.equals(e2))
- {
- if (!e2.implicitConvTo(e1.type))
- goto Lnomatch;
+ e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
+ e2 = e2.ctfeInterpret();
- e2 = e2.implicitCastTo(sc, e1.type);
- e2 = e2.ctfeInterpret();
- if (!e1.equals(e2))
- goto Lnomatch;
- }
- }
- else if (e1 && t2 && t2.ty == Tident)
+ //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
+ //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
+ if (!e1.equals(e2))
{
- j = templateParameterLookup(t2, parameters);
- L1:
- if (j == IDX_NOTFOUND)
- {
- t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
- if (e2)
- goto Le;
- goto Lnomatch;
- }
- if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
- goto Lnomatch;
+ if (!e2.implicitConvTo(e1.type))
+ return false;
+
+ e2 = e2.implicitCastTo(sc, e1.type);
+ e2 = e2.ctfeInterpret();
+ if (!e1.equals(e2))
+ return false;
}
- else if (s1 && s2)
+ }
+ else if (e1 && t2 && t2.ty == Tident)
+ {
+ j = templateParameterLookup(t2, parameters);
+ L1:
+ if (j == IDX_NOTFOUND)
{
- Ls:
- if (!s1.equals(s2))
- goto Lnomatch;
+ t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
+ if (e2)
+ goto Le;
+ return false;
}
- else if (s1 && t2 && t2.ty == Tident)
+ if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
+ return false;
+ }
+ else if (s1 && s2)
+ {
+ Ls:
+ if (!s1.equals(s2))
+ return false;
+ }
+ else if (s1 && t2 && t2.ty == Tident)
+ {
+ j = templateParameterLookup(t2, parameters);
+ if (j == IDX_NOTFOUND)
{
- j = templateParameterLookup(t2, parameters);
- if (j == IDX_NOTFOUND)
- {
- t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
- if (s2)
- goto Ls;
- goto Lnomatch;
- }
- if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
- goto Lnomatch;
+ t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
+ if (s2)
+ goto Ls;
+ return false;
}
- else
- goto Lnomatch;
+ if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
+ return false;
}
+ else
+ return false;
}
- visit(cast(Type)t);
- return;
-
- Lnomatch:
- //printf("no match\n");
- result = MATCH.nomatch;
+ return true;
}
override void visit(TypeStruct t)
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 4f1edaa..c0dd17f 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -377,13 +377,18 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
desc ~ " `%s` assigned to non-scope parameter calling `assert()`", v);
return;
}
+
+ bool isThis = fdc && fdc.needThis() && fdc.vthis == vPar; // implicit `this` parameter to member function
+
const(char)* msg =
+ (isThis) ? (desc ~ " `%s` calling non-scope member function `%s.%s()`") :
(fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`") :
(fdc && !parId) ? (desc ~ " `%s` assigned to non-scope anonymous parameter calling `%s`") :
(!fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s`") :
(desc ~ " `%s` assigned to non-scope anonymous parameter");
- if (sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc))
+ auto param = isThis ? v : (parId ? parId : fdc);
+ if (sc.setUnsafeDIP1000(gag, arg.loc, msg, v, param, fdc))
{
result = true;
printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10);
@@ -1746,20 +1751,8 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
/* Check each argument that is
* passed as 'return scope'.
*/
- Type t1 = e.e1.type.toBasetype();
- TypeFunction tf;
- TypeDelegate dg;
- if (t1.ty == Tdelegate)
- {
- dg = t1.isTypeDelegate();
- tf = dg.next.isTypeFunction();
- }
- else if (t1.ty == Tfunction)
- tf = t1.isTypeFunction();
- else
- return;
-
- if (!e.type.hasPointers())
+ TypeFunction tf = e.calledFunctionType();
+ if (!tf || !e.type.hasPointers())
return;
if (e.arguments && e.arguments.length)
@@ -1815,6 +1808,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
}
}
// If 'this' is returned, check it too
+ Type t1 = e.e1.type.toBasetype();
if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
{
DotVarExp dve = e.e1.isDotVarExp();
@@ -1880,7 +1874,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
/* If returning the result of a delegate call, the .ptr
* field of the delegate must be checked.
*/
- if (dg)
+ if (t1.isTypeDelegate())
{
if (tf.isreturn)
escapeByValue(e.e1, er, live, retRefTransition);
@@ -2066,13 +2060,8 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
/* If the function returns by ref, check each argument that is
* passed as 'return ref'.
*/
- Type t1 = e.e1.type.toBasetype();
- TypeFunction tf;
- if (t1.ty == Tdelegate)
- tf = t1.isTypeDelegate().next.isTypeFunction();
- else if (t1.ty == Tfunction)
- tf = t1.isTypeFunction();
- else
+ TypeFunction tf = e.calledFunctionType();
+ if (!tf)
return;
if (tf.isref)
{
@@ -2107,6 +2096,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
}
}
// If 'this' is returned by ref, check it too
+ Type t1 = e.e1.type.toBasetype();
if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
{
DotVarExp dve = e.e1.isDotVarExp();
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 067d22f..473efb8 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -19,7 +19,6 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.aliasthis;
-import dmd.apply;
import dmd.arrayop;
import dmd.arraytypes;
import dmd.astenums;
@@ -56,6 +55,7 @@ import dmd.nspace;
import dmd.objc;
import dmd.opover;
import dmd.optimize;
+import dmd.postordervisitor;
import dmd.root.complex;
import dmd.root.ctfloat;
import dmd.root.filename;
@@ -699,6 +699,20 @@ VarDeclaration expToVariable(Expression e)
case EXP.super_:
return (cast(ThisExp)e).var.isVarDeclaration();
+ // Temporaries for rvalues that need destruction
+ // are of form: (T s = rvalue, s). For these cases
+ // we can just return var declaration of `s`. However,
+ // this is intentionally not calling `Expression.extractLast`
+ // because at this point we cannot infer the var declaration
+ // of more complex generated comma expressions such as the
+ // one for the array append hook.
+ case EXP.comma:
+ {
+ if (auto ve = e.isCommaExp().e2.isVarExp())
+ return ve.var.isVarDeclaration();
+
+ return null;
+ }
default:
return null;
}
@@ -723,7 +737,6 @@ extern (C++) abstract class Expression : ASTNode
Type type; // !=null means that semantic() has been run
Loc loc; // file location
const EXP op; // to minimize use of dynamic_cast
- bool parens; // if this is a parenthesized expression
extern (D) this(const ref Loc loc, EXP op) scope
{
@@ -1530,6 +1543,11 @@ extern (C++) abstract class Expression : ASTNode
return false;
if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
return false;
+ /* The original expression (`new S(...)`) will be verified instead. This
+ * is to keep errors related to the original code and not the lowering.
+ */
+ if (f.ident == Id._d_newitemT)
+ return false;
if (!f.isNogc())
{
@@ -2338,6 +2356,7 @@ extern (C++) final class ComplexExp : Expression
extern (C++) class IdentifierExp : Expression
{
Identifier ident;
+ bool parens; // if it appears as (identifier)
extern (D) this(const ref Loc loc, Identifier ident) scope
{
@@ -3520,6 +3539,8 @@ extern (C++) final class CompoundLiteralExp : Expression
*/
extern (C++) final class TypeExp : Expression
{
+ bool parens; // if this is a parenthesized expression
+
extern (D) this(const ref Loc loc, Type type)
{
super(loc, EXP.type);
@@ -3672,7 +3693,7 @@ extern (C++) final class NewExp : Expression
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
- Expression lowering; // lowered druntime hook: `_d_newclass`
+ Expression lowering; // lowered druntime hook: `_d_new{class,itemT}`
/// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around.
/// The fields are still separate for backwards compatibility
@@ -5188,6 +5209,7 @@ extern (C++) final class CallExp : UnaExp
bool directcall; // true if a virtual call is devirtualized
bool inDebugStatement; /// true if this was in a debug statement
bool ignoreAttributes; /// don't enforce attributes (e.g. call @gc function in @nogc code)
+ bool isUfcsRewrite; /// the first argument was pushed in here by a UFCS rewrite
VarDeclaration vthis2; // container for multi-context
/// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around.
@@ -5329,6 +5351,26 @@ extern (C++) final class CallExp : UnaExp
}
}
+/**
+ * Get the called function type from a call expression
+ * Params:
+ * ce = function call expression. Must have had semantic analysis done.
+ * Returns: called function type, or `null` if error / no semantic analysis done
+ */
+TypeFunction calledFunctionType(CallExp ce)
+{
+ Type t = ce.e1.type;
+ if (!t)
+ return null;
+ t = t.toBasetype();
+ if (auto tf = t.isTypeFunction())
+ return tf;
+ else if (auto td = t.isTypeDelegate())
+ return td.nextOf().isTypeFunction();
+ else
+ return null;
+}
+
FuncDeclaration isFuncAddress(Expression e, bool* hasOverloads = null)
{
if (auto ae = e.isAddrExp())
@@ -7058,9 +7100,7 @@ extern (C++) final class FileInitExp : DefaultInitExp
s = loc.isValid() ? loc.filename : sc._module.ident.toChars();
Expression e = new StringExp(loc, s.toDString());
- e = e.expressionSemantic(sc);
- e = e.castTo(sc, type);
- return e;
+ return e.expressionSemantic(sc);
}
override void accept(Visitor v)
@@ -7082,8 +7122,7 @@ extern (C++) final class LineInitExp : DefaultInitExp
override Expression resolveLoc(const ref Loc loc, Scope* sc)
{
Expression e = new IntegerExp(loc, loc.linnum, Type.tint32);
- e = e.castTo(sc, type);
- return e;
+ return e.expressionSemantic(sc);
}
override void accept(Visitor v)
@@ -7106,9 +7145,7 @@ extern (C++) final class ModuleInitExp : DefaultInitExp
{
const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString();
Expression e = new StringExp(loc, s);
- e = e.expressionSemantic(sc);
- e = e.castTo(sc, type);
- return e;
+ return e.expressionSemantic(sc);
}
override void accept(Visitor v)
@@ -7137,9 +7174,7 @@ extern (C++) final class FuncInitExp : DefaultInitExp
else
s = "";
Expression e = new StringExp(loc, s.toDString());
- e = e.expressionSemantic(sc);
- e.type = Type.tstring;
- return e;
+ return e.expressionSemantic(sc);
}
override void accept(Visitor v)
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index a4b18b9..770c3e7 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -83,7 +83,6 @@ public:
Type *type; // !=NULL means that semantic() has been run
Loc loc; // file location
EXP op; // to minimize use of dynamic_cast
- d_bool parens; // if this is a parenthesized expression
size_t size() const;
static void _init();
@@ -316,6 +315,7 @@ class IdentifierExp : public Expression
{
public:
Identifier *ident;
+ d_bool parens;
static IdentifierExp *create(const Loc &loc, Identifier *ident);
bool isLvalue() override final;
@@ -839,6 +839,7 @@ public:
d_bool directcall; // true if a virtual call is devirtualized
d_bool inDebugStatement; // true if this was in a debug statement
d_bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code)
+ d_bool isUfcsRewrite; // the first argument was pushed in here by a UFCS rewrite
VarDeclaration *vthis2; // container for multi-context
static CallExp *create(const Loc &loc, Expression *e, Expressions *exps);
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index cf4aac4..8ac8866 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -653,7 +653,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
if (!ce.names)
ce.names = new Identifiers();
ce.names.shift(null);
-
+ ce.isUfcsRewrite = true;
return null;
}
@@ -1254,12 +1254,12 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
return ErrorExp.get();
e2 = resolveProperties(sc, e2);
- Expressions a;
+ Expressions* a = new Expressions();
a.push(e2);
for (size_t i = 0; i < os.a.length; i++)
{
- if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, ArgumentList(&a), FuncResolveFlag.quiet))
+ if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, ArgumentList(a), FuncResolveFlag.quiet))
{
if (f.errors)
return ErrorExp.get();
@@ -1378,10 +1378,10 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
return ErrorExp.get();
e2 = resolveProperties(sc, e2);
- Expressions a;
+ Expressions* a = new Expressions();
a.push(e2);
- FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, ArgumentList(&a), FuncResolveFlag.quiet);
+ FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, ArgumentList(a), FuncResolveFlag.quiet);
if (fd && fd.type)
{
if (fd.errors)
@@ -3574,6 +3574,51 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp;
}
+ /**
+ * Sets the `lowering` field of a `NewExp` to a call to `_d_newitemT` unless
+ * compiling with `-betterC` or within `__traits(compiles)`.
+ *
+ * Params:
+ * ne = the `NewExp` to lower
+ */
+ private void tryLowerToNewItem(NewExp ne)
+ {
+ if (global.params.betterC || !sc.needsCodegen())
+ return;
+
+ auto hook = global.params.tracegc ? Id._d_newitemTTrace : Id._d_newitemT;
+ if (!verifyHookExist(ne.loc, *sc, hook, "new struct"))
+ return;
+
+ /* Lower the memory allocation and initialization of `new T()` to
+ * `_d_newitemT!T()`.
+ */
+ Expression id = new IdentifierExp(ne.loc, Id.empty);
+ id = new DotIdExp(ne.loc, id, Id.object);
+ auto tiargs = new Objects();
+ /*
+ * Remove `inout`, `const`, `immutable` and `shared` to reduce the
+ * number of generated `_d_newitemT` instances.
+ */
+ auto t = ne.type.nextOf.unqualify(MODFlags.wild | MODFlags.const_ |
+ MODFlags.immutable_ | MODFlags.shared_);
+ tiargs.push(t);
+ id = new DotTemplateInstanceExp(ne.loc, id, hook, tiargs);
+
+ auto arguments = new Expressions();
+ if (global.params.tracegc)
+ {
+ auto funcname = (sc.callsc && sc.callsc.func) ?
+ sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
+ arguments.push(new StringExp(ne.loc, ne.loc.filename.toDString()));
+ arguments.push(new IntegerExp(ne.loc, ne.loc.linnum, Type.tint32));
+ arguments.push(new StringExp(ne.loc, funcname.toDString()));
+ }
+ id = new CallExp(ne.loc, id, arguments);
+
+ ne.lowering = id.expressionSemantic(sc);
+ }
+
override void visit(NewExp exp)
{
static if (LOGSEMANTIC)
@@ -4007,6 +4052,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.type = exp.type.pointerTo();
+ tryLowerToNewItem(exp);
}
else if (tb.ty == Tarray)
{
@@ -4078,6 +4124,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.type = exp.type.pointerTo();
+ tryLowerToNewItem(exp);
}
else if (tb.ty == Taarray)
{
@@ -5192,7 +5239,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
s = (cast(TemplateExp)exp.e1).td;
L2:
- exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.argumentList, FuncResolveFlag.standard);
+ exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.argumentList,
+ exp.isUfcsRewrite ? FuncResolveFlag.ufcs : FuncResolveFlag.standard);
if (!exp.f || exp.f.errors)
return setError();
if (exp.f.needThis())
@@ -5301,6 +5349,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
buf.writeByte(')');
//printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
+ if (exp.isUfcsRewrite)
+ {
+ const arg = (*exp.argumentList.arguments)[0];
+ .error(exp.loc, "no property `%s` for `%s` of type `%s`", exp.f.ident.toChars(), arg.toChars(), arg.type.toChars());
+ .errorSupplemental(exp.loc, "the following error occured while looking for a UFCS match");
+ }
+
.error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
if (failMessage)
@@ -6733,7 +6788,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.ident != Id.__sizeof)
{
- result = fieldLookup(exp.e1, sc, exp.ident);
+ result = fieldLookup(exp.e1, sc, exp.ident, exp.arrow);
return;
}
}
@@ -9068,7 +9123,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
{
auto die = e1x.isDotIdExp();
- e1x = fieldLookup(die.e1, sc, die.ident);
+ e1x = fieldLookup(die.e1, sc, die.ident, die.arrow);
}
else if (auto die = e1x.isDotIdExp())
{
@@ -11023,7 +11078,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* `_d_arraycatnTX` canot be used with `-betterC`, but `CatExp`s may be
* used with `-betterC`, but only during CTFE.
*/
- if (global.params.betterC)
+ if (global.params.betterC || !sc.needsCodegen())
return;
if (auto ce = exp.isCatExp())
@@ -13175,10 +13230,20 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
Expression se = new ScopeExp(exp.loc, imp.pkg);
return se.expressionSemantic(sc);
}
+
+ if (auto attr = s.isAttribDeclaration())
+ {
+ if (auto sm = ie.sds.search(exp.loc, exp.ident, flags))
+ {
+ auto es = new DsymbolExp(exp.loc, sm);
+ return es;
+ }
+ }
+
// BUG: handle other cases like in IdentifierExp::semantic()
debug
{
- printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
+ printf("s = %p '%s', kind = '%s'\n", s, s.toChars(), s.kind());
}
assert(0);
}
diff --git a/gcc/d/dmd/foreachvar.d b/gcc/d/dmd/foreachvar.d
index 7a96469..1293057 100644
--- a/gcc/d/dmd/foreachvar.d
+++ b/gcc/d/dmd/foreachvar.d
@@ -15,7 +15,6 @@ import core.stdc.stdio;
import core.stdc.stdlib;
import core.stdc.string;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
import dmd.attrib;
@@ -33,6 +32,7 @@ import dmd.identifier;
import dmd.init;
import dmd.initsem;
import dmd.mtype;
+import dmd.postordervisitor;
import dmd.printast;
import dmd.root.array;
import dmd.root.rootobject;
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 8e11ab1..a714d2d 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -59,6 +59,10 @@ import dmd.statementsem;
import dmd.tokens;
import dmd.visitor;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
/// Inline Status
enum ILS : ubyte
{
@@ -259,21 +263,30 @@ extern (C++) struct Ensure
}
/***********************************************************
+ * Most functions don't have contracts, so save memory by grouping
+ * this information into a separate struct
*/
-extern (C++) class FuncDeclaration : Declaration
+private struct ContractInfo
{
Statements* frequires; /// in contracts
Ensures* fensures; /// out contracts
Statement frequire; /// lowered in contract
Statement fensure; /// lowered out contract
- Statement fbody; /// function body
-
- FuncDeclarations foverrides; /// functions this function overrides
FuncDeclaration fdrequire; /// function that does the in contract
FuncDeclaration fdensure; /// function that does the out contract
-
Expressions* fdrequireParams; /// argument list for __require
Expressions* fdensureParams; /// argument list for __ensure
+}
+
+/***********************************************************
+ */
+extern (C++) class FuncDeclaration : Declaration
+{
+ Statement fbody; /// function body
+
+ FuncDeclarations foverrides; /// functions this function overrides
+
+ private ContractInfo* contracts; /// contract information
const(char)* mangleString; /// mangled symbol created from mangleExact()
@@ -403,6 +416,44 @@ extern (C++) class FuncDeclaration : Declaration
return new FuncDeclaration(loc, endloc, id, storage_class, type, noreturn);
}
+ final nothrow pure @safe
+ {
+ private ref ContractInfo getContracts()
+ {
+ if (!contracts)
+ contracts = new ContractInfo();
+ return *contracts;
+ }
+
+ // getters
+ inout(Statements*) frequires() inout { return contracts ? contracts.frequires : null; }
+ inout(Ensures*) fensures() inout { return contracts ? contracts.fensures : null; }
+ inout(Statement) frequire() inout { return contracts ? contracts.frequire: null; }
+ inout(Statement) fensure() inout { return contracts ? contracts.fensure : null; }
+ inout(FuncDeclaration) fdrequire() inout { return contracts ? contracts.fdrequire : null; }
+ inout(FuncDeclaration) fdensure() inout { return contracts ? contracts.fdensure: null; }
+ inout(Expressions*) fdrequireParams() inout { return contracts ? contracts.fdrequireParams: null; }
+ inout(Expressions*) fdensureParams() inout { return contracts ? contracts.fdensureParams: null; }
+
+ extern (D) private static string generateContractSetter(string field, string type)
+ {
+ return type ~ " " ~ field ~ "(" ~ type ~ " param)" ~
+ "{
+ if (!param && !contracts) return null;
+ return getContracts()." ~ field ~ " = param;
+ }";
+ }
+
+ mixin(generateContractSetter("frequires", "Statements*"));
+ mixin(generateContractSetter("fensures", "Ensures*"));
+ mixin(generateContractSetter("frequire", "Statement"));
+ mixin(generateContractSetter("fensure", "Statement"));
+ mixin(generateContractSetter("fdrequire", "FuncDeclaration"));
+ mixin(generateContractSetter("fdensure", "FuncDeclaration"));
+ mixin(generateContractSetter("fdrequireParams", "Expressions*"));
+ mixin(generateContractSetter("fdensureParams", "Expressions*"));
+ }
+
override FuncDeclaration syntaxCopy(Dsymbol s)
{
//printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
@@ -2717,7 +2768,7 @@ extern (C++) class FuncDeclaration : Declaration
*/
static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, StorageClass stc = 0)
{
- return genCfunc(fparams, treturn, Identifier.idPool(name, cast(uint)strlen(name)), stc);
+ return genCfunc(fparams, treturn, Identifier.idPool(name[0 .. strlen(name)]), stc);
}
static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, StorageClass stc = 0)
@@ -3199,6 +3250,7 @@ enum FuncResolveFlag : ubyte
quiet = 1, /// do not issue error message on no match, just return `null`.
overloadOnly = 2, /// only resolve overloads, i.e. do not issue error on ambiguous
/// matches and need explicit this.
+ ufcs = 4, /// trying to resolve UFCS call
}
/*******************************************
@@ -3316,12 +3368,22 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
}
// no match, generate an error messages
+ if (flags & FuncResolveFlag.ufcs)
+ {
+ auto arg = (*fargs)[0];
+ .error(loc, "no property `%s` for `%s` of type `%s`", s.ident.toChars(), arg.toChars(), arg.type.toChars());
+ .errorSupplemental(loc, "the following error occured while looking for a UFCS match");
+ }
+
if (!fd)
{
// all of overloads are templates
if (td)
{
- .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
+ const(char)* msg = "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`";
+ if (!od && !td.overnext)
+ msg = "%s `%s.%s` is not callable using argument types `!(%s)%s`";
+ .error(loc, msg,
td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
tiargsBuf.peekChars(), fargsBuf.peekChars());
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 45b4528..0ac6042 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -26,6 +26,10 @@ import dmd.location;
import dmd.lexer : CompileEnv;
import dmd.utils;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
/// Defines a setting for how compiler warnings and deprecations are handled
enum DiagnosticReporting : ubyte
{
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 902cf83..66345ac 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -353,10 +353,11 @@ typedef unsigned long long uinteger_t;
// file location
struct Loc
{
- const char *filename; // either absolute or relative to cwd
- unsigned linnum;
- unsigned charnum;
-
+private:
+ unsigned _linnum;
+ unsigned short _charnum;
+ unsigned short fileIndex;
+public:
static void set(bool showColumns, MessageStyle messageStyle);
static bool showColumns;
@@ -364,18 +365,25 @@ struct Loc
Loc()
{
- linnum = 0;
- charnum = 0;
- filename = NULL;
+ _linnum = 0;
+ _charnum = 0;
+ fileIndex = 0;
}
Loc(const char *filename, unsigned linnum, unsigned charnum)
{
- this->linnum = linnum;
- this->charnum = charnum;
- this->filename = filename;
+ this->linnum(linnum);
+ this->charnum(charnum);
+ this->filename(filename);
}
+ uint32_t charnum() const;
+ uint32_t charnum(uint32_t num);
+ uint32_t linnum() const;
+ uint32_t linnum(uint32_t num);
+ const char *filename() const;
+ void filename(const char *name);
+
const char *toChars(
bool showColumns = Loc::showColumns,
MessageStyle messageStyle = Loc::messageStyle) const;
diff --git a/gcc/d/dmd/gluelayer.d b/gcc/d/dmd/gluelayer.d
index 7b52eff..1793700 100644
--- a/gcc/d/dmd/gluelayer.d
+++ b/gcc/d/dmd/gluelayer.d
@@ -48,25 +48,6 @@ version (NoBackend)
}
}
}
-else version (MARS)
-{
- public import dmd.backend.cc : block, Blockx, Symbol;
- public import dmd.backend.type : type;
- public import dmd.backend.el : elem;
- public import dmd.backend.code_x86 : code;
-
- extern (C++)
- {
- Statement asmSemantic(AsmStatement s, Scope* sc);
-
- void toObjFile(Dsymbol ds, bool multiobj);
-
- extern(C++) abstract class ObjcGlue
- {
- static void initialize();
- }
- }
-}
else version (IN_GCC)
{
extern (C++) union tree_node;
@@ -88,4 +69,12 @@ else version (IN_GCC)
}
}
else
- static assert(false, "Unsupported compiler backend");
+{
+ public import dmd.backend.cc : block, Blockx, Symbol;
+ public import dmd.backend.type : type;
+ public import dmd.backend.el : elem;
+ public import dmd.backend.code_x86 : code;
+ public import dmd.iasm : asmSemantic;
+ public import dmd.objc_glue : ObjcGlue;
+ public import dmd.toobj : toObjFile;
+}
diff --git a/gcc/d/dmd/iasm.d b/gcc/d/dmd/iasm.d
index 66829da..1fdfe40 100644
--- a/gcc/d/dmd/iasm.d
+++ b/gcc/d/dmd/iasm.d
@@ -23,13 +23,14 @@ import dmd.tokens;
import dmd.statement;
import dmd.statementsem;
-version (MARS)
+version (IN_GCC)
{
- import dmd.iasmdmd;
+ import dmd.iasmgcc;
}
-else version (IN_GCC)
+else
{
- import dmd.iasmgcc;
+ import dmd.iasmdmd;
+ version = MARS;
}
/************************ AsmStatement ***************************************/
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index a2271d5..a2daf60 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -315,6 +315,8 @@ immutable Msgtable[] msgtable =
{ "_d_newThrowable" },
{ "_d_newclassT" },
{ "_d_newclassTTrace" },
+ { "_d_newitemT" },
+ { "_d_newitemTTrace" },
{ "_d_assert_fail" },
{ "dup" },
{ "_aaApply" },
@@ -549,6 +551,7 @@ immutable Msgtable[] msgtable =
{ "_pure", "pure" },
{ "define" },
{ "undef" },
+ { "ident" },
];
diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d
index 2233d77..b1c421c 100644
--- a/gcc/d/dmd/identifier.d
+++ b/gcc/d/dmd/identifier.d
@@ -274,12 +274,7 @@ nothrow:
return idPool(s[0 .. len]);
}
- extern (D) static Identifier idPool(const(char)[] s)
- {
- return idPool(s, false);
- }
-
- extern (D) private static Identifier idPool(const(char)[] s, bool isAnonymous)
+ extern (D) static Identifier idPool(const(char)[] s, bool isAnonymous = false)
{
auto sv = stringtable.update(s);
auto id = sv.value;
@@ -291,18 +286,18 @@ nothrow:
return id;
}
- extern (D) static Identifier idPool(const(char)* s, size_t len, int value)
- {
- return idPool(s[0 .. len], value);
- }
-
- extern (D) static Identifier idPool(const(char)[] s, int value)
+ /******************************************
+ * Used for inserting keywords into the string table.
+ * Params:
+ * s = string for keyword
+ * value = TOK.xxxx for the keyword
+ */
+ extern (D) static void idPool(const(char)[] s, TOK value)
{
auto sv = stringtable.insert(s, null);
assert(sv);
auto id = new Identifier(sv.toString(), value);
sv.value = id;
- return id;
}
/**********************************
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 97710b8..fe0aa17 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -108,11 +108,12 @@ Expression arrayFuncConv(Expression e, Scope* sc)
* e = evaluates to an instance of a struct
* sc = context
* id = identifier of a field in that struct
+ * arrow = -> was used
* Returns:
* if successful `e.ident`
* if not then `ErrorExp` and message is printed
*/
-Expression fieldLookup(Expression e, Scope* sc, Identifier id)
+Expression fieldLookup(Expression e, Scope* sc, Identifier id, bool arrow)
{
e = e.expressionSemantic(sc);
if (e.isErrorExp())
@@ -123,6 +124,9 @@ Expression fieldLookup(Expression e, Scope* sc, Identifier id)
if (t.isTypePointer())
{
t = t.isTypePointer().next;
+ auto pe = e.toChars();
+ if (!arrow)
+ e.error("since `%s` is a pointer, use `%s->%s` instead of `%s.%s`", pe, pe, id.toChars(), pe, id.toChars());
e = new PtrExp(e.loc, e);
}
if (auto ts = t.isTypeStruct())
@@ -237,15 +241,16 @@ Expression castCallAmbiguity(Expression e, Scope* sc)
case EXP.call:
auto ce = (*pe).isCallExp();
- if (ce.e1.parens)
+ auto ie = ce.e1.isIdentifierExp();
+ if (ie && ie.parens)
{
- ce.e1 = expressionSemantic(ce.e1, sc);
+ ce.e1 = expressionSemantic(ie, sc);
if (ce.e1.op == EXP.type)
{
const numArgs = ce.arguments ? ce.arguments.length : 0;
if (numArgs >= 1)
{
- ce.e1.parens = false;
+ ie.parens = false;
Expression arg;
foreach (a; (*ce.arguments)[])
{
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 893d2a6..ca770bd 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -587,6 +587,9 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
*/
t = t.toBasetype();
+ if (auto tv = t.isTypeVector())
+ t = tv.basetype;
+
/* If `{ expression }` return the expression initializer
*/
ExpInitializer isBraceExpression()
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index 0ec468b..a878cc9 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -119,7 +119,7 @@ class Lexer
this(const(char)* filename, const(char)* base, size_t begoffset,
size_t endoffset, bool doDocComment, bool commentToken,
ErrorSink errorSink,
- const CompileEnv* compileEnv) pure scope
+ const CompileEnv* compileEnv) scope
{
scanloc = Loc(filename, 1, 1);
// debug printf("Lexer::Lexer(%p)\n", base);
@@ -573,7 +573,7 @@ class Lexer
}
break;
}
- Identifier id = Identifier.idPool(cast(char*)t.ptr, cast(uint)(p - t.ptr));
+ Identifier id = Identifier.idPool((cast(char*)t.ptr)[0 .. p - t.ptr], false);
t.ident = id;
t.value = cast(TOK)id.getValue();
@@ -2672,9 +2672,9 @@ class Lexer
return result;
}
- final Loc loc() pure @nogc
+ final Loc loc() @nogc
{
- scanloc.charnum = cast(uint)(1 + p - line);
+ scanloc.charnum = cast(ushort)(1 + p - line);
version (LocOffset)
scanloc.fileOffset = cast(uint)(p - base);
return scanloc;
@@ -3098,9 +3098,9 @@ class Lexer
/**************************
* `p` should be at start of next line
*/
- private void endOfLine() pure @nogc @safe
+ private void endOfLine() @nogc @safe
{
- scanloc.linnum++;
+ scanloc.linnum = scanloc.linnum + 1;
line = p;
}
}
diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d
index 020d297..b2b3661 100644
--- a/gcc/d/dmd/location.d
+++ b/gcc/d/dmd/location.d
@@ -11,7 +11,10 @@
module dmd.location;
+import core.stdc.stdio;
+
import dmd.common.outbuffer;
+import dmd.root.array;
import dmd.root.filename;
version (DMDLIB)
@@ -34,10 +37,9 @@ debug info etc.
*/
struct Loc
{
- /// zero-terminated filename string, either absolute or relative to cwd
- const(char)* filename;
- uint linnum; /// line number, starting from 1
- uint charnum; /// utf8 code unit index relative to start of line, starting from 1
+ private uint _linnum;
+ private ushort _charnum;
+ private ushort fileIndex; // index into filenames[], starting from 1 (0 means no filename)
version (LocOffset)
uint fileOffset; /// utf8 code unit index relative to start of file, starting from 0
@@ -46,6 +48,8 @@ struct Loc
extern (C++) __gshared bool showColumns;
extern (C++) __gshared MessageStyle messageStyle;
+ __gshared Array!(const(char)*) filenames;
+
nothrow:
/*******************************
@@ -60,19 +64,69 @@ nothrow:
this.messageStyle = messageStyle;
}
- extern (D) this(const(char)* filename, uint linnum, uint charnum) pure
+ extern (D) this(const(char)* filename, uint linnum, uint charnum)
{
- this.linnum = linnum;
- this.charnum = charnum;
+ this._linnum = linnum;
+ this._charnum = cast(ushort) charnum;
this.filename = filename;
}
+ /// utf8 code unit index relative to start of line, starting from 1
+ extern (C++) uint charnum() const @nogc @safe
+ {
+ return _charnum;
+ }
+
+ /// ditto
+ extern (C++) uint charnum(uint num) @nogc @safe
+ {
+ return _charnum = cast(ushort) num;
+ }
+
+ /// line number, starting from 1
+ extern (C++) uint linnum() const @nogc @safe
+ {
+ return _linnum;
+ }
+
+ /// ditto
+ extern (C++) uint linnum(uint num) @nogc @safe
+ {
+ return _linnum = num;
+ }
+
+ /***
+ * Returns: filename for this location, null if none
+ */
+ extern (C++) const(char)* filename() const @nogc
+ {
+ return fileIndex ? filenames[fileIndex - 1] : null;
+ }
+
+ /***
+ * Set file name for this location
+ * Params:
+ * name = file name for location, null for no file name
+ */
+ extern (C++) void filename(const(char)* name)
+ {
+ if (name)
+ {
+ //printf("setting %s\n", name);
+ filenames.push(name);
+ fileIndex = cast(ushort)filenames.length;
+ assert(fileIndex); // no overflow
+ }
+ else
+ fileIndex = 0;
+ }
+
extern (C++) const(char)* toChars(
bool showColumns = Loc.showColumns,
- MessageStyle messageStyle = Loc.messageStyle) const pure nothrow
+ MessageStyle messageStyle = Loc.messageStyle) const nothrow
{
OutBuffer buf;
- if (filename)
+ if (fileIndex)
{
buf.writestring(filename);
}
@@ -126,7 +180,7 @@ nothrow:
* may lead to multiple equivalent filenames (`foo.d-mixin-<line>`),
* e.g., for test/runnable/test18880.d.
*/
- extern (D) bool opEquals(ref const(Loc) loc) const @trusted pure nothrow @nogc
+ extern (D) bool opEquals(ref const(Loc) loc) const @trusted nothrow @nogc
{
import core.stdc.string : strcmp;
@@ -137,7 +191,7 @@ nothrow:
}
/// ditto
- extern (D) size_t toHash() const @trusted pure nothrow
+ extern (D) size_t toHash() const @trusted nothrow
{
import dmd.root.string : toDString;
@@ -153,6 +207,6 @@ nothrow:
*/
bool isValid() const pure
{
- return filename !is null;
+ return fileIndex != 0;
}
}
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index badc579..cb3e6cd 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -2448,7 +2448,7 @@ extern (C++) abstract class Type : ASTNode
//printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name);
assert(0 < length && length < namelen); // don't overflow the buffer
- auto id = Identifier.idPool(name, length);
+ auto id = Identifier.idPool(name[0 .. length]);
if (name != namebuf.ptr)
free(name);
@@ -7119,9 +7119,9 @@ bool isCopyable(Type t)
assert(ctor);
scope el = new IdentifierExp(Loc.initial, Id.p); // dummy lvalue
el.type = cast() ts;
- Expressions args;
+ Expressions* args = new Expressions();
args.push(el);
- FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(&args), FuncResolveFlag.quiet);
+ FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(args), FuncResolveFlag.quiet);
if (!f || f.storage_class & STC.disable)
return false;
}
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index a0f3e60..9a8f242 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -16,7 +16,6 @@ module dmd.nogc;
import core.stdc.stdio;
import dmd.aggregate;
-import dmd.apply;
import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
@@ -26,6 +25,7 @@ import dmd.func;
import dmd.globals;
import dmd.init;
import dmd.mtype;
+import dmd.postordervisitor;
import dmd.tokens;
import dmd.visitor;
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 89728b6..56243a0 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -20,7 +20,6 @@ import dmd.root.rootobject;
import dmd.root.rmem;
import dmd.aggregate;
-import dmd.apply;
import dmd.arraytypes;
import dmd.astenums;
import dmd.declaration;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index d7b90d7..0e64d9c 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -607,8 +607,6 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
//printf("BinExp::op_overload() (%s)\n", e.toChars());
Identifier id = opId(e);
Identifier id_r = opId_r(e);
- Expressions args1;
- Expressions args2;
int argsset = 0;
AggregateDeclaration ad1 = isAggregate(e.e1.type);
AggregateDeclaration ad2 = isAggregate(e.e2.type);
@@ -701,6 +699,8 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
}
}
}
+ Expressions* args1 = new Expressions();
+ Expressions* args2 = new Expressions();
if (s || s_r)
{
/* Try:
@@ -709,16 +709,16 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
* and see which is better.
*/
args1.setDim(1);
- args1[0] = e.e1;
- expandTuples(&args1);
+ (*args1)[0] = e.e1;
+ expandTuples(args1);
args2.setDim(1);
- args2[0] = e.e2;
- expandTuples(&args2);
+ (*args2)[0] = e.e2;
+ expandTuples(args2);
argsset = 1;
MatchAccumulator m;
if (s)
{
- functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2));
+ functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
@@ -727,7 +727,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
FuncDeclaration lastf = m.lastf;
if (s_r)
{
- functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1));
+ functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
@@ -791,16 +791,16 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (!argsset)
{
args1.setDim(1);
- args1[0] = e.e1;
- expandTuples(&args1);
+ (*args1)[0] = e.e1;
+ expandTuples(args1);
args2.setDim(1);
- args2[0] = e.e2;
- expandTuples(&args2);
+ (*args2)[0] = e.e2;
+ expandTuples(args2);
}
MatchAccumulator m;
if (s_r)
{
- functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2));
+ functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
@@ -809,7 +809,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
FuncDeclaration lastf = m.lastf;
if (s)
{
- functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1));
+ functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
@@ -1197,7 +1197,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
return ErrorExp.get();
}
Identifier id = opId(e);
- Expressions args2;
+ Expressions* args2 = new Expressions();
AggregateDeclaration ad1 = isAggregate(e.e1.type);
Dsymbol s = null;
Objects* tiargs = null;
@@ -1240,10 +1240,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
* a.opOpAssign(b)
*/
args2.setDim(1);
- args2[0] = e.e2;
- expandTuples(&args2);
+ (*args2)[0] = e.e2;
+ expandTuples(args2);
MatchAccumulator m;
- functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2));
+ functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
@@ -1322,12 +1322,12 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
* b.opEquals(a)
* and see which is better.
*/
- Expressions args1 = Expressions(1);
- args1[0] = e.e1;
- expandTuples(&args1);
- Expressions args2 = Expressions(1);
- args2[0] = e.e2;
- expandTuples(&args2);
+ Expressions* args1 = new Expressions(1);
+ (*args1)[0] = e.e1;
+ expandTuples(args1);
+ Expressions* args2 = new Expressions(1);
+ (*args2)[0] = e.e2;
+ expandTuples(args2);
MatchAccumulator m;
if (0 && s && s_r)
{
@@ -1336,7 +1336,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
}
if (s)
{
- functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2));
+ functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
@@ -1344,7 +1344,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
int count = m.count;
if (s_r)
{
- functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1));
+ functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 61c385f..335310d 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -769,11 +769,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
if (e.arguments)
{
- Type t1 = e.e1.type.toBasetype();
- if (auto td = t1.isTypeDelegate())
- t1 = td.next;
// t1 can apparently be void for __ArrayDtor(T) calls
- if (auto tf = t1.isTypeFunction())
+ if (auto tf = e.calledFunctionType())
{
foreach (i, ref arg; (*e.arguments)[])
{
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 68a2506..b7e0791 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -4515,10 +4515,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
if (_init)
{
- if (isThis)
- error(token.loc, "cannot use syntax `alias this = %s`, use `alias %s this` instead", _init.toChars(), _init.toChars());
- else
- error("alias cannot have initializer");
+ error("alias cannot have initializer");
}
v = new AST.AliasDeclaration(aliasLoc, ident, t);
@@ -4780,23 +4777,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
addComment(s, comment);
return a;
}
- version (none)
+ /* Look for:
+ * alias this = identifier;
+ */
+ if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
{
- /* Look for:
- * alias this = identifier;
- */
- if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
- {
- check(TOK.this_);
- check(TOK.assign);
- auto s = new AliasThis(loc, token.ident);
- nextToken();
- check(TOK.semicolon, "`alias this = Identifier`");
- auto a = new Dsymbols();
- a.push(s);
- addComment(s, comment);
- return a;
- }
+ check(TOK.this_);
+ check(TOK.assign);
+ auto s = new AST.AliasThis(loc, token.ident);
+ nextToken();
+ check(TOK.semicolon, "`alias this = Identifier`");
+ auto a = new AST.Dsymbols();
+ a.push(s);
+ addComment(s, comment);
+ return a;
}
/* Look for:
* alias identifier = type;
@@ -5032,7 +5026,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
stc = STC.ref_;
nextToken();
}
- if (token.value != TOK.leftParenthesis && token.value != TOK.leftCurly)
+ if (token.value != TOK.leftParenthesis && token.value != TOK.leftCurly &&
+ token.value != TOK.goesTo)
{
// function type (parameters) { statements... }
// delegate type (parameters) { statements... }
@@ -5331,7 +5326,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
error("cannot use function constraints for non-template functions. Use `static if` instead");
}
else
- error("semicolon expected following function declaration");
+ error("semicolon expected following function declaration, not `%s`", token.toChars());
}
break;
}
@@ -7081,7 +7076,7 @@ LagainStc:
private void checkParens(TOK value, AST.Expression e)
{
- if (precedence[e.op] == PREC.rel && !e.parens)
+ if (precedence[e.op] == PREC.rel)
error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`", e.toChars(), Token.toChars(value));
}
@@ -8485,7 +8480,6 @@ LagainStc:
// ( expression )
nextToken();
e = parseExpression();
- e.parens = true;
check(loc, TOK.rightParenthesis);
break;
}
@@ -8806,9 +8800,9 @@ LagainStc:
nextToken();
return AST.ErrorExp.get();
}
- e = new AST.TypeExp(loc, t);
- e.parens = true;
- e = parsePostExp(e);
+ auto te = new AST.TypeExp(loc, t);
+ te.parens = true;
+ e = parsePostExp(te);
}
else
{
@@ -9115,14 +9109,18 @@ LagainStc:
private AST.Expression parseAndExp()
{
Loc loc = token.loc;
+ bool parens = token.value == TOK.leftParenthesis;
auto e = parseCmpExp();
while (token.value == TOK.and)
{
- checkParens(TOK.and, e);
- nextToken();
+ if (!parens)
+ checkParens(TOK.and, e);
+ parens = nextToken() == TOK.leftParenthesis;
auto e2 = parseCmpExp();
- checkParens(TOK.and, e2);
+ if (!parens)
+ checkParens(TOK.and, e2);
e = new AST.AndExp(loc, e, e2);
+ parens = true; // don't call checkParens() for And
loc = token.loc;
}
return e;
@@ -9130,32 +9128,42 @@ LagainStc:
private AST.Expression parseXorExp()
{
- const loc = token.loc;
+ Loc loc = token.loc;
+ bool parens = token.value == TOK.leftParenthesis;
auto e = parseAndExp();
while (token.value == TOK.xor)
{
- checkParens(TOK.xor, e);
- nextToken();
+ if (!parens)
+ checkParens(TOK.xor, e);
+ parens = nextToken() == TOK.leftParenthesis;
auto e2 = parseAndExp();
- checkParens(TOK.xor, e2);
+ if (!parens)
+ checkParens(TOK.xor, e2);
e = new AST.XorExp(loc, e, e2);
+ parens = true;
+ loc = token.loc;
}
return e;
}
private AST.Expression parseOrExp()
{
- const loc = token.loc;
+ Loc loc = token.loc;
+ bool parens = token.value == TOK.leftParenthesis;
auto e = parseXorExp();
while (token.value == TOK.or)
{
- checkParens(TOK.or, e);
- nextToken();
+ if (!parens)
+ checkParens(TOK.or, e);
+ parens = nextToken() == TOK.leftParenthesis;
auto e2 = parseXorExp();
- checkParens(TOK.or, e2);
+ if (!parens)
+ checkParens(TOK.or, e2);
e = new AST.OrExp(loc, e, e2);
+ parens = true;
+ loc = token.loc;
}
return e;
}
@@ -9206,6 +9214,7 @@ LagainStc:
AST.Expression parseAssignExp()
{
+ bool parens = token.value == TOK.leftParenthesis;
AST.Expression e;
e = parseCondExp();
if (e is null)
@@ -9214,7 +9223,7 @@ LagainStc:
// require parens for e.g. `t ? a = 1 : b = 2`
void checkRequiredParens()
{
- if (e.op == EXP.question && !e.parens)
+ if (e.op == EXP.question && !parens)
eSink.error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`",
e.toChars(), Token.toChars(token.value));
}
diff --git a/gcc/d/dmd/apply.d b/gcc/d/dmd/postordervisitor.d
index d18b81f..a0c7115 100644
--- a/gcc/d/dmd/apply.d
+++ b/gcc/d/dmd/postordervisitor.d
@@ -9,11 +9,9 @@
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/apply.d
*/
-module dmd.apply;
+module dmd.postordervisitor;
import dmd.arraytypes;
-import dmd.dsymbol;
-import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.expression;
import dmd.root.array;
@@ -26,39 +24,6 @@ bool walkPostorder(Expression e, StoppableVisitor v)
return v.stop;
}
-/*********************************
- * Iterate this dsymbol or members of this scoped dsymbol, then
- * call `fp` with the found symbol and `params`.
- * Params:
- * symbol = the dsymbol or parent of members to call fp on
- * fp = function pointer to process the iterated symbol.
- * If it returns nonzero, the iteration will be aborted.
- * params = any parameters passed to fp.
- * Returns:
- * nonzero if the iteration is aborted by the return value of fp,
- * or 0 if it's completed.
- */
-int apply(FP, Params...)(Dsymbol symbol, FP fp, Params params)
-{
- if (auto nd = symbol.isNspace())
- {
- return nd.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
- if (auto ad = symbol.isAttribDeclaration())
- {
- return ad.include(ad._scope).foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
- if (auto tm = symbol.isTemplateMixin())
- {
- if (tm._scope) // if fwd reference
- dsymbolSemantic(tm, null); // try to resolve it
-
- return tm.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
- }
-
- return fp(symbol, params);
-}
-
/**************************************
* An Expression tree walker that will visit each Expression e in the tree,
* in depth-first evaluation order, and call fp(e,param) on it.
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index ee268d9..c40e72c 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -447,14 +447,12 @@ private extern(C++) final class Semantic2Visitor : Visitor
const sameParams = tf1.parameterList == tf2.parameterList;
// Allow the hack to declare overloads with different parameters/STC's
- // @@@DEPRECATED_2.104@@@
- // Deprecated in 2020-08, make this an error in 2.104
if (parent1.isModule() &&
linkage1 != LINK.d && linkage1 != LINK.cpp &&
(!sameAttr || !sameParams)
)
{
- f2.deprecation("cannot overload `extern(%s)` function at %s",
+ f2.error("cannot overload `extern(%s)` function at %s",
linkageToChars(f1._linkage),
f1.loc.toChars());
return 0;
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index 3f3e7e6..90b86df 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -11,7 +11,6 @@
module dmd.sideeffect;
-import dmd.apply;
import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
@@ -22,6 +21,7 @@ import dmd.globals;
import dmd.identifier;
import dmd.init;
import dmd.mtype;
+import dmd.postordervisitor;
import dmd.tokens;
import dmd.visitor;
@@ -101,9 +101,11 @@ extern (C++) bool hasSideEffect(Expression e, bool assumeImpureCalls = false)
int callSideEffectLevel(FuncDeclaration f)
{
/* https://issues.dlang.org/show_bug.cgi?id=12760
- * ctor call always has side effects.
+ * https://issues.dlang.org/show_bug.cgi?id=16384
+ *
+ * ctor calls and invariant calls always have side effects
*/
- if (f.isCtorDeclaration())
+ if (f.isCtorDeclaration() || f.isInvariantDeclaration())
return 0;
assert(f.type.ty == Tfunction);
TypeFunction tf = cast(TypeFunction)f.type;
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f849ce1..f0454163 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -1273,8 +1273,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
}
else if (auto td = sfront.isTemplateDeclaration())
{
- Expressions a;
- if (auto f = resolveFuncCall(loc, sc, td, null, tab, ArgumentList(&a), FuncResolveFlag.quiet))
+ if (auto f = resolveFuncCall(loc, sc, td, null, tab, ArgumentList(), FuncResolveFlag.quiet))
tfront = f.type;
}
else if (auto d = sfront.toAlias().isDeclaration())
@@ -2733,7 +2732,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
tbret = tret.toBasetype();
}
- if (inferRef) // deduce 'auto ref'
+ // https://issues.dlang.org/show_bug.cgi?id=23914
+ if (inferRef && !resType.isTypeNoreturn()) // deduce 'auto ref'
tf.isref = false;
if (tbret.ty != Tvoid && !resType.isTypeNoreturn()) // if non-void return
@@ -3593,6 +3593,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
cas.error("`asm` statement is assumed to be impure - mark it with `pure` if it is not");
if (!(cas.stc & STC.nogc) && sc.func.setGC(cas.loc, "`asm` statement in %s `%s` is assumed to use the GC - mark it with `@nogc` if it does not"))
cas.error("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
+ // @@@DEPRECATED_2.114@@@
+ // change deprecation() to error(), add `else` and remove `| STC.safe`
+ // to turn deprecation into an error when deprecation cycle is over
+ if (cas.stc & STC.safe)
+ cas.deprecation("`asm` statement cannot be marked `@safe`, use `@system` or `@trusted` instead");
if (!(cas.stc & (STC.trusted | STC.safe)))
{
sc.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not");
@@ -4045,6 +4050,13 @@ void catchSemantic(Catch c, Scope* sc)
// reference .object.Throwable
c.type = getThrowable();
}
+ else if (!c.type.isNaked() && !c.type.isConst())
+ {
+ // @@@DEPRECATED_2.113@@@
+ // Deprecated in 2.103, change into an error & uncomment in 2.113
+ deprecation(c.loc, "can only catch mutable or const qualified types, not `%s`", c.type.toChars());
+ //c.errors = true;
+ }
c.type = c.type.typeSemantic(c.loc, sc);
if (c.type == Type.terror)
{
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 352c89e..5871762 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -593,7 +593,7 @@ shared static this() nothrow
foreach (kw; keywords)
{
//printf("keyword[%d] = '%s'\n",kw, Token.tochars[kw].ptr);
- Identifier.idPool(Token.tochars[kw].ptr, Token.tochars[kw].length, cast(uint)kw);
+ Identifier.idPool(Token.tochars[kw], kw);
}
}
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 0f36353..53c8fb0 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -1215,7 +1215,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
{
if (fd.overnext)
{
- deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `%s`", fd.toChars());
+ deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not the overload set `%s`", fd.toChars());
deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
}
}
@@ -1225,7 +1225,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
{
if (td.overnext || td.funcroot)
{
- deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `%s`", td.ident.toChars());
+ deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not the overload set `%s`", td.ident.toChars());
deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
}
}
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index c588270..a82a268 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -161,6 +161,16 @@ package mixin template ParseVisitMethods(AST)
s._body.accept(this);
}
+ override void visit(AST.StaticForeachStatement s)
+ {
+ // printf("Visiting StaticForeachStatement\n");
+ if (s.sfe.aggrfe)
+ s.sfe.aggrfe.accept(this);
+
+ if (s.sfe.rangefe)
+ s.sfe.rangefe.accept(this);
+ }
+
override void visit(AST.IfStatement s)
{
//printf("Visiting IfStatement\n");
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index f0decf2..09eef83 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -163,7 +163,7 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
/* Look for what user might have intended
*/
const p = mt.mutableOf().unSharedOf().toChars();
- auto id = Identifier.idPool(p, cast(uint)strlen(p));
+ auto id = Identifier.idPool(p[0 .. strlen(p)]);
if (const n = importHint(id.toString()))
error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr);
else if (auto s2 = sc.search_correct(id))
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 23f2f0b..8fb1eea 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2296,11 +2296,12 @@ public:
return;
}
+ /* This case should have been rewritten to `_d_newitemT' during the
+ semantic phase. */
+ gcc_assert (e->lowering);
+
/* Generate: _d_newitemT() */
- libcall_fn libcall = htype->isZeroInit ()
- ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
- tree arg = build_typeinfo (e, e->newtype);
- new_call = build_libcall (libcall, tb, 1, arg);
+ new_call = build_expr (e->lowering);
if (e->member || !e->arguments)
{
@@ -2423,11 +2424,12 @@ public:
return;
}
- libcall_fn libcall = tpointer->next->isZeroInit (e->loc)
- ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
+ /* This case should have been rewritten to `_d_newitemT' during the
+ semantic phase. */
+ gcc_assert (e->lowering);
- tree arg = build_typeinfo (e, e->newtype);
- result = build_libcall (libcall, tb, 1, arg);
+ /* Generate: _d_newitemT() */
+ result = build_expr (e->lowering);
if (e->arguments && e->arguments->length == 1)
{
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index fd83cc9..4d1ba09 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -70,11 +70,6 @@ DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT),
DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT),
P2(OBJECT, CLASSINFO), 0)
-/* Used when calling new on a pointer. The `i' variant is for when the
- initializer is nonzero. */
-DEF_D_RUNTIME (NEWITEMT, "_d_newitemT", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
-DEF_D_RUNTIME (NEWITEMIT, "_d_newitemiT", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
-
/* Used when calling new on an array. The `i' variant is for when the
initializer is nonzero, and the `m' variant is when initializing a
multi-dimensional array. */
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index 8bd6eb6..db6f71b 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -780,8 +780,8 @@ public:
this->do_label (label);
- if (this->is_return_label (s->ident) && this->func_->fensure != NULL)
- this->build_stmt (this->func_->fensure);
+ if (this->is_return_label (s->ident) && this->func_->fensure () != NULL)
+ this->build_stmt (this->func_->fensure ());
else if (s->statement)
this->build_stmt (s->statement);
}
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index 1c5e50c..bf17438 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -1421,7 +1421,7 @@ check_typeinfo_type (const Loc &loc, Scope *sc, Expression *expr)
/* If TypeInfo has not been declared, warn about each location once. */
static Loc warnloc;
- if (loc.filename && !warnloc.equals (loc))
+ if (loc.filename () && !warnloc.equals (loc))
{
error_at (make_location_t (loc),
"%<object.TypeInfo%> could not be found, "