public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Iain Buclaw <ibuclaw@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-4644] d: Merge upstream dmd, druntime f9efc98fd7, phobos a3f22129d. Date: Sun, 15 Oct 2023 11:12:09 +0000 (GMT) [thread overview] Message-ID: <20231015111209.234FB3858D33@sourceware.org> (raw) https://gcc.gnu.org/g:ac908237bd551fb55f2f82736cb37038e9b91459 commit r14-4644-gac908237bd551fb55f2f82736cb37038e9b91459 Author: Iain Buclaw <ibuclaw@gdcproject.org> Date: Sun Oct 15 12:05:10 2023 +0200 d: Merge upstream dmd, druntime f9efc98fd7, phobos a3f22129d. D front-end changes: - Import dmd v2.105.2. - A function with enum storage class is now deprecated. - Global variables can now be initialized with Associative Arrays. - Improvements for the C++ header generation of static variables used in a default argument context. D runtime changes: - Import druntime v2.105.2. - The `core.memory.GC' functions `GC.enable', `GC.disable', `GC.collect', and `GC.minimize' `have been marked `@safe'. Phobos changes: - Import phobos v2.105.2. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd f9efc98fd7. * dmd/VERSION: Bump version to v2.105.2. * d-builtins.cc (build_frontend_type): Update for new front-end interface. * d-diagnostic.cc (verrorReport): Don't emit tips when error gagging is turned on. * d-lang.cc (d_handle_option): Remove obsolete parameter. (d_post_options): Likewise. (d_read_ddoc_files): New function. (d_generate_ddoc_file): New function. (d_parse_file): Update for new front-end interface. * expr.cc (ExprVisitor::visit (AssocArrayLiteralExp *)): Check for new front-end lowering of static associative arrays. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime f9efc98fd7. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/internal/newaa.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos a3f22129d. * testsuite/libphobos.hash/test_hash.d: Update test. * testsuite/libphobos.phobos/phobos.exp: Add compiler flags -Wno-deprecated. * testsuite/libphobos.phobos_shared/phobos_shared.exp: Likewise. gcc/testsuite/ChangeLog: * lib/gdc-utils.exp (gdc-convert-args): Handle new compiler options. Diff: --- gcc/d/d-builtins.cc | 3 +- gcc/d/d-diagnostic.cc | 5 +- gcc/d/d-lang.cc | 78 ++++- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/VERSION | 2 +- gcc/d/dmd/attrib.d | 2 +- gcc/d/dmd/blockexit.d | 107 +++--- gcc/d/dmd/canthrow.d | 2 +- gcc/d/dmd/chkformat.d | 32 +- gcc/d/dmd/clone.d | 20 +- gcc/d/dmd/cond.d | 2 +- gcc/d/dmd/cparse.d | 11 +- gcc/d/dmd/cppmangle.d | 2 - gcc/d/dmd/ctfeexpr.d | 6 +- gcc/d/dmd/dcast.d | 13 +- gcc/d/dmd/dclass.d | 6 +- gcc/d/dmd/declaration.d | 7 +- gcc/d/dmd/delegatize.d | 1 - gcc/d/dmd/denum.d | 2 - gcc/d/dmd/dinterpret.d | 14 +- gcc/d/dmd/dmacro.d | 56 ++- gcc/d/dmd/dmodule.d | 4 +- gcc/d/dmd/doc.d | 353 +++++++++---------- gcc/d/dmd/doc.h | 3 +- gcc/d/dmd/dscope.d | 1 + gcc/d/dmd/dstruct.d | 1 + gcc/d/dmd/dsymbol.d | 1 + gcc/d/dmd/dsymbolsem.d | 58 +++- gcc/d/dmd/dtemplate.d | 24 +- gcc/d/dmd/dtoh.d | 10 +- gcc/d/dmd/errors.h | 3 +- gcc/d/dmd/errorsink.d | 1 + gcc/d/dmd/escape.d | 40 ++- gcc/d/dmd/expression.d | 47 +-- gcc/d/dmd/expression.h | 3 +- gcc/d/dmd/expressionsem.d | 109 +++--- gcc/d/dmd/func.d | 21 +- gcc/d/dmd/globals.d | 33 +- gcc/d/dmd/globals.h | 35 +- gcc/d/dmd/hdrgen.d | 375 +++++++++++---------- gcc/d/dmd/hdrgen.h | 4 +- gcc/d/dmd/iasmgcc.d | 2 +- gcc/d/dmd/id.d | 2 + gcc/d/dmd/init.d | 2 +- gcc/d/dmd/initsem.d | 31 +- gcc/d/dmd/json.d | 23 +- gcc/d/dmd/json.h | 2 +- gcc/d/dmd/lexer.d | 88 ++++- gcc/d/dmd/location.d | 20 +- gcc/d/dmd/module.h | 2 +- gcc/d/dmd/mtype.d | 55 ++- gcc/d/dmd/mtype.h | 5 +- gcc/d/dmd/opover.d | 8 +- gcc/d/dmd/optimize.d | 28 +- gcc/d/dmd/parse.d | 110 ++++-- gcc/d/dmd/printast.d | 2 +- gcc/d/dmd/safe.d | 23 +- gcc/d/dmd/semantic2.d | 53 +++ gcc/d/dmd/semantic3.d | 14 +- gcc/d/dmd/statement.d | 117 +------ gcc/d/dmd/statement.h | 3 +- gcc/d/dmd/statementsem.d | 293 ++++++++-------- gcc/d/dmd/tokens.d | 22 +- gcc/d/dmd/tokens.h | 1 + gcc/d/dmd/traits.d | 2 +- gcc/d/dmd/typesem.d | 19 +- gcc/d/dmd/utils.d | 24 +- gcc/d/expr.cc | 9 + .../gdc.test/compilable/dtoh_StructDeclaration.d | 15 + gcc/testsuite/gdc.test/compilable/dtoh_functions.d | 4 +- gcc/testsuite/gdc.test/compilable/issue22682.d | 8 + gcc/testsuite/gdc.test/compilable/obsolete_body.d | 5 + .../gdc.test/compilable/shortened_methods.d | 5 + gcc/testsuite/gdc.test/compilable/test23145.d | 13 +- gcc/testsuite/gdc.test/compilable/test24066.d | 11 + gcc/testsuite/gdc.test/compilable/test24107.d | 17 + gcc/testsuite/gdc.test/compilable/test24109.d | 17 + gcc/testsuite/gdc.test/compilable/test24118.d | 15 + gcc/testsuite/gdc.test/fail_compilation/aa_init.d | 16 + gcc/testsuite/gdc.test/fail_compilation/body.d | 11 - .../gdc.test/fail_compilation/chkformat.d | 2 + .../gdc.test/fail_compilation/dephexstrings.d | 9 - .../gdc.test/fail_compilation/diag10169.d | 3 +- .../gdc.test/fail_compilation/diag10783.d | 5 +- .../gdc.test/fail_compilation/diag12063.d | 42 ++- .../gdc.test/fail_compilation/diag12829.d | 13 +- .../gdc.test/fail_compilation/diag13609a.d | 7 +- .../gdc.test/fail_compilation/diag14145.d | 9 +- .../gdc.test/fail_compilation/diag15713.d | 9 +- gcc/testsuite/gdc.test/fail_compilation/diag3913.d | 6 +- gcc/testsuite/gdc.test/fail_compilation/diag5385.d | 24 +- gcc/testsuite/gdc.test/fail_compilation/diag7477.d | 4 +- gcc/testsuite/gdc.test/fail_compilation/diag8697.d | 3 +- gcc/testsuite/gdc.test/fail_compilation/diag8894.d | 12 +- .../fail_compilation/dip1000_deprecation.d | 19 +- gcc/testsuite/gdc.test/fail_compilation/dip22a.d | 12 +- .../gdc.test/fail_compilation/enum_function.d | 9 +- .../gdc.test/fail_compilation/fail10528.d | 20 +- .../gdc.test/fail_compilation/fail10534.d | 32 +- gcc/testsuite/gdc.test/fail_compilation/fail109.d | 2 +- gcc/testsuite/gdc.test/fail_compilation/fail121.d | 5 +- gcc/testsuite/gdc.test/fail_compilation/fail136.d | 2 +- .../gdc.test/fail_compilation/fail17570.d | 7 +- .../gdc.test/fail_compilation/fail17969.d | 3 +- .../gdc.test/fail_compilation/fail18219.d | 9 +- .../gdc.test/fail_compilation/fail18892.d | 6 +- .../gdc.test/fail_compilation/fail18970.d | 10 +- .../gdc.test/fail_compilation/fail18979.d | 3 +- gcc/testsuite/gdc.test/fail_compilation/fail1900.d | 6 +- .../gdc.test/fail_compilation/fail19076.d | 5 +- .../gdc.test/fail_compilation/fail19103.d | 8 +- gcc/testsuite/gdc.test/fail_compilation/fail196.d | 49 +-- .../gdc.test/fail_compilation/fail20637.d | 3 +- .../gdc.test/fail_compilation/fail22054.d | 10 +- .../gdc.test/fail_compilation/fail22529.d | 2 +- .../gdc.test/fail_compilation/fail23109.d | 2 + gcc/testsuite/gdc.test/fail_compilation/fail61.d | 11 +- gcc/testsuite/gdc.test/fail_compilation/fail7861.d | 3 +- gcc/testsuite/gdc.test/fail_compilation/fail9.d | 3 +- .../gdc.test/fail_compilation/fail_scope.d | 30 +- .../gdc.test/fail_compilation/faildottypeinfo.d | 5 +- .../gdc.test/fail_compilation/fnconstraint.d | 11 +- .../gdc.test/fail_compilation/goto_skip.d | 57 ++++ gcc/testsuite/gdc.test/fail_compilation/ice10713.d | 3 +- gcc/testsuite/gdc.test/fail_compilation/ice10938.d | 5 +- gcc/testsuite/gdc.test/fail_compilation/ice11518.d | 6 +- gcc/testsuite/gdc.test/fail_compilation/ice11982.d | 20 +- gcc/testsuite/gdc.test/fail_compilation/ice8100.d | 7 +- .../gdc.test/fail_compilation/issue12652.d | 24 -- .../gdc.test/fail_compilation/issue22682.d | 18 + gcc/testsuite/gdc.test/fail_compilation/lexer1.d | 4 +- gcc/testsuite/gdc.test/fail_compilation/lexer2.d | 8 +- gcc/testsuite/gdc.test/fail_compilation/main.d | 9 + .../gdc.test/fail_compilation/match_func_ptr.d | 17 + .../fail_compilation/misc_parser_err_cov1.d | 3 +- gcc/testsuite/gdc.test/fail_compilation/nogc3.d | 18 +- .../gdc.test/fail_compilation/noreturn_expr.d | 16 + .../gdc.test/fail_compilation/noreturn_expr2.d | 14 + .../gdc.test/fail_compilation/operator_undefined.d | 20 ++ gcc/testsuite/gdc.test/fail_compilation/parseStc.d | 6 +- gcc/testsuite/gdc.test/fail_compilation/retscope.d | 2 +- gcc/testsuite/gdc.test/fail_compilation/skip.d | 6 +- .../gdc.test/fail_compilation/switch_skip.d | 48 +++ gcc/testsuite/gdc.test/fail_compilation/switches.d | 68 +--- .../gdc.test/fail_compilation/test13536.d | 7 +- .../gdc.test/fail_compilation/test15785.d | 5 +- .../gdc.test/fail_compilation/test15897.d | 3 +- .../gdc.test/fail_compilation/test16188.d | 1 + .../gdc.test/fail_compilation/test16193.d | 5 +- .../gdc.test/fail_compilation/test16365.d | 9 +- .../gdc.test/fail_compilation/test17380spec.d | 7 +- .../gdc.test/fail_compilation/test20655.d | 32 ++ .../gdc.test/fail_compilation/test21353.d | 13 +- .../gdc.test/fail_compilation/test21912.d | 20 +- .../gdc.test/fail_compilation/test22329.d | 3 +- .../gdc.test/fail_compilation/test23112.d | 3 +- .../gdc.test/fail_compilation/test24015.d | 20 ++ .../gdc.test/fail_compilation/test24036.d | 21 ++ .../gdc.test/fail_compilation/test24065.d | 18 + .../gdc.test/fail_compilation/test24084.d | 28 ++ .../gdc.test/fail_compilation/test24110.d | 12 + .../gdc.test/fail_compilation/testOpApply.d | 16 +- gcc/testsuite/gdc.test/fail_compilation/testsemi.d | 3 +- gcc/testsuite/gdc.test/runnable/staticaa.d | 126 +++++++ gcc/testsuite/gdc.test/runnable/test24078.d | 6 + gcc/testsuite/gdc.test/runnable/test24139.d | 25 ++ gcc/testsuite/lib/gdc-utils.exp | 3 + libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/Makefile.am | 6 +- libphobos/libdruntime/Makefile.in | 37 +- libphobos/libdruntime/core/internal/newaa.d | 144 ++++++++ libphobos/libdruntime/core/stdc/math.d | 13 +- libphobos/libdruntime/core/stdcpp/string.d | 6 +- libphobos/libdruntime/core/sys/posix/fcntl.d | 21 ++ libphobos/libdruntime/core/sys/posix/signal.d | 22 +- .../libdruntime/core/sys/posix/sys/resource.d | 35 +- libphobos/libdruntime/core/sys/windows/sql.d | 4 + libphobos/libdruntime/core/sys/windows/sqlext.d | 4 + libphobos/libdruntime/core/sys/windows/sqltypes.d | 4 + libphobos/libdruntime/core/sys/windows/sqlucode.d | 4 + libphobos/libdruntime/core/sys/windows/winnt.d | 2 +- libphobos/libdruntime/object.d | 8 + libphobos/libdruntime/rt/aaA.d | 19 ++ libphobos/libdruntime/rt/minfo.d | 14 +- libphobos/src/MERGE | 2 +- libphobos/src/std/int128.d | 46 ++- libphobos/src/std/string.d | 1 + libphobos/testsuite/libphobos.hash/test_hash.d | 4 +- libphobos/testsuite/libphobos.phobos/phobos.exp | 2 +- .../libphobos.phobos_shared/phobos_shared.exp | 2 +- 190 files changed, 2771 insertions(+), 1427 deletions(-) diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index 60f76fc694c..cf998d22721 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -322,7 +322,8 @@ build_frontend_type (tree type) return NULL; } - args->push (Parameter::create (sc, targ, NULL, NULL, NULL)); + args->push (Parameter::create (Loc (), sc, targ, + NULL, NULL, NULL)); } /* GCC generic and placeholder built-ins are marked as variadic, yet diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc index be779d93297..b698d4e49b8 100644 --- a/gcc/d/d-diagnostic.cc +++ b/gcc/d/d-diagnostic.cc @@ -220,7 +220,7 @@ d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format, void D_ATTRIBUTE_FORMAT(2,0) ATTRIBUTE_GCC_DIAG(2,0) verrorReport (const Loc& loc, const char *format, va_list ap, ErrorKind kind, - const char *prefix1 = NULL, const char *prefix2 = NULL) + const char *prefix1, const char *prefix2) { diagnostic_t diag_kind = DK_UNSPECIFIED; int opt = 0; @@ -277,6 +277,9 @@ verrorReport (const Loc& loc, const char *format, va_list ap, ErrorKind kind, } else if (kind == ErrorKind::tip) { + if (global.gag) + return; + diag_kind = DK_DEBUG; verbatim = true; } diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index f290acf494b..6509d766708 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -779,7 +779,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, case OPT_Wall: if (value) global.params.warnings = DIAGNOSTICinform; - global.params.obsolete = value; break; case OPT_Wdeprecated: @@ -941,7 +940,6 @@ d_post_options (const char ** fn) global.compileEnv.previewIn = global.params.previewIn; global.compileEnv.ddocOutput = global.params.ddoc.doOutput; global.compileEnv.shortenedMethods = global.params.shortenedMethods; - global.compileEnv.obsolete = global.params.obsolete; /* Add in versions given on the command line. */ if (global.params.versionids) @@ -1002,6 +1000,66 @@ d_write_file (const char *filename, const char *data) error ("writing output file %s: %m", filename); } +/* Read ddoc macro files named by the DDOCFILES, then write the concatenated + the contents into DDOCBUF. */ + +static void +d_read_ddoc_files (Strings &ddocfiles, OutBuffer &ddocbuf) +{ + if (ddocbuf.length ()) + return; + + for (size_t i = 0; i < ddocfiles.length; i++) + { + int fd = open (ddocfiles[i], O_RDONLY); + bool ok = false; + struct stat buf; + + if (fd == -1 || fstat (fd, &buf)) + { + error ("unable to open %s for reading: %m", ddocfiles[i]); + continue; + } + + /* Check we've not been given a directory, or a file bigger than 4GB. */ + if (S_ISDIR (buf.st_mode)) + errno = ENOENT; + else if (buf.st_size != unsigned (buf.st_size)) + errno = EMFILE; + else + { + unsigned size = unsigned (buf.st_size); + char *buffer = (char *) xmalloc (size); + + if (read (fd, buffer, size) == ssize_t (size)) + { + ddocbuf.write (buffer, size); + ok = true; + } + + free (buffer); + } + + close (fd); + if (!ok) + fatal_error (input_location, "reading ddoc file %s: %m", ddocfiles[i]); + } +} + +static void +d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf) +{ + input_location = make_location_t (m->loc); + + d_read_ddoc_files (global.params.ddoc.files, ddocbuf); + + OutBuffer ddocbuf_out; + gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime, + global.errorSink, ddocbuf_out); + + d_write_file (m->docfile.toChars (), ddocbuf_out.peekChars ()); +} + /* Implements the lang_hooks.parse_file routine for language D. */ static void @@ -1038,6 +1096,9 @@ d_parse_file (void) Modules modules; modules.reserve (num_in_fnames); + /* Buffer for contents of .ddoc files. */ + OutBuffer ddocbuf; + /* In this mode, the first file name is supposed to be a duplicate of one of the input files. */ if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0) @@ -1125,7 +1186,8 @@ d_parse_file (void) if (m->filetype == FileType::ddoc) { - gendocfile (m, global.errorSink); + d_generate_ddoc_file (m, ddocbuf); + /* Remove M from list of modules. */ modules.remove (i); i--; @@ -1168,7 +1230,9 @@ d_parse_file (void) if (global.params.verbose) message ("import %s", m->toChars ()); - genhdrfile (m); + OutBuffer buf; + genhdrfile (m, buf); + d_write_file (m->hdrfile.toChars (), buf.peekChars ()); } dump_headers = true; @@ -1308,7 +1372,7 @@ d_parse_file (void) if (global.params.json.doOutput) { OutBuffer buf; - json_generate (&buf, &modules); + json_generate (modules, buf); d_write_file (global.params.json.name.ptr, buf.peekChars ()); } @@ -1318,7 +1382,7 @@ d_parse_file (void) for (size_t i = 0; i < modules.length; i++) { Module *m = modules[i]; - gendocfile (m, global.errorSink); + d_generate_ddoc_file (m, ddocbuf); } } @@ -1331,7 +1395,7 @@ d_parse_file (void) OutBuffer buf; buf.doindent = 1; - moduleToBuffer (&buf, m); + moduleToBuffer (buf, m); message ("%s", buf.peekChars ()); } } diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index dc267787cab..d5dfe0d0edd 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -4574d1728d1f7e52ff40e6733b8c39889d128349 +f9efc98fd7954741333f72c6a50af273f3863a1a 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/VERSION b/gcc/d/dmd/VERSION index 8012337e422..fd05dcf2136 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.105.0 +v2.105.2 diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index baabe930c68..5a91bc74229 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -679,7 +679,7 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration { assert(visibility.kind > Visibility.Kind.undefined); OutBuffer buf; - visibilityToBuffer(&buf, visibility); + visibilityToBuffer(buf, visibility); return buf.extractChars(); } diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d index bdc81f246cd..a0da77a2898 100644 --- a/gcc/d/dmd/blockexit.d +++ b/gcc/d/dmd/blockexit.d @@ -18,6 +18,7 @@ import dmd.astenums; import dmd.canthrow; import dmd.dclass; import dmd.declaration; +import dmd.errorsink; import dmd.expression; import dmd.func; import dmd.globals; @@ -56,11 +57,11 @@ enum BE : int * Params: * s = statement to check for block exit status * func = function that statement s is in - * mustNotThrow = generate an error if it throws + * eSink = generate an error if it throws * Returns: * BE.xxxx */ -int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) +int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink) { int result = BE.none; @@ -97,7 +98,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn()) result = BE.halt; - result |= canThrow(s.exp, func, mustNotThrow); + result |= canThrow(s.exp, func, eSink !is null); } } @@ -143,23 +144,23 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) // Deprecated in 2.100 // Make an error in 2.110 if (sl && sl.isCaseStatement()) - s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype); + global.errorSink.deprecation(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype); else - s.error("switch case fallthrough - use 'goto %s;' if intended", gototype); + global.errorSink.error(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype); } } } if (!(result & BE.fallthru) && !s.comeFrom()) { - if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() && + if (blockExit(s, func, eSink) != BE.halt && s.hasCode() && s.loc != Loc.initial) // don't emit warning for generated code - s.warning("statement is not reachable"); + global.errorSink.warning(s.loc, "statement is not reachable"); } else { result &= ~BE.fallthru; - result |= blockExit(s, func, mustNotThrow); + result |= blockExit(s, func, eSink); } slast = s; } @@ -173,7 +174,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { if (s) { - int r = blockExit(s, func, mustNotThrow); + int r = blockExit(s, func, eSink); result |= r & ~(BE.break_ | BE.continue_ | BE.fallthru); if ((r & (BE.fallthru | BE.continue_ | BE.break_)) == 0) result &= ~BE.fallthru; @@ -184,7 +185,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) void visitScope(ScopeStatement s) { //printf("ScopeStatement::blockExit(%p)\n", s.statement); - result = blockExit(s.statement, func, mustNotThrow); + result = blockExit(s.statement, func, eSink); } void visitWhile(WhileStatement s) @@ -197,7 +198,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { if (s._body) { - result = blockExit(s._body, func, mustNotThrow); + result = blockExit(s._body, func, eSink); if (result == BE.break_) { result = BE.fallthru; @@ -210,7 +211,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) result = BE.fallthru; if (result & BE.fallthru) { - result |= canThrow(s.condition, func, mustNotThrow); + result |= canThrow(s.condition, func, eSink !is null); if (!(result & BE.break_) && s.condition.toBool().hasValue(true)) result &= ~BE.fallthru; @@ -223,13 +224,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) result = BE.fallthru; if (s._init) { - result = blockExit(s._init, func, mustNotThrow); + result = blockExit(s._init, func, eSink); if (!(result & BE.fallthru)) return; } if (s.condition) { - result |= canThrow(s.condition, func, mustNotThrow); + result |= canThrow(s.condition, func, eSink !is null); const opt = s.condition.toBool(); if (opt.hasValue(true)) @@ -241,22 +242,22 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) result &= ~BE.fallthru; // the body must do the exiting if (s._body) { - int r = blockExit(s._body, func, mustNotThrow); + int r = blockExit(s._body, func, eSink); if (r & (BE.break_ | BE.goto_)) result |= BE.fallthru; result |= r & ~(BE.fallthru | BE.break_ | BE.continue_); } if (s.increment) - result |= canThrow(s.increment, func, mustNotThrow); + result |= canThrow(s.increment, func, eSink !is null); } void visitForeach(ForeachStatement s) { result = BE.fallthru; - result |= canThrow(s.aggr, func, mustNotThrow); + result |= canThrow(s.aggr, func, eSink !is null); if (s._body) - result |= blockExit(s._body, func, mustNotThrow) & ~(BE.break_ | BE.continue_); + result |= blockExit(s._body, func, eSink) & ~(BE.break_ | BE.continue_); } void visitForeachRange(ForeachRangeStatement s) @@ -269,30 +270,30 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { //printf("IfStatement::blockExit(%p)\n", s); result = BE.none; - result |= canThrow(s.condition, func, mustNotThrow); + result |= canThrow(s.condition, func, eSink !is null); const opt = s.condition.toBool(); if (opt.hasValue(true)) { - result |= blockExit(s.ifbody, func, mustNotThrow); + result |= blockExit(s.ifbody, func, eSink); } else if (opt.hasValue(false)) { - result |= blockExit(s.elsebody, func, mustNotThrow); + result |= blockExit(s.elsebody, func, eSink); } else { - result |= blockExit(s.ifbody, func, mustNotThrow); - result |= blockExit(s.elsebody, func, mustNotThrow); + result |= blockExit(s.ifbody, func, eSink); + result |= blockExit(s.elsebody, func, eSink); } //printf("IfStatement::blockExit(%p) = x%x\n", s, result); } void visitConditional(ConditionalStatement s) { - result = blockExit(s.ifbody, func, mustNotThrow); + result = blockExit(s.ifbody, func, eSink); if (s.elsebody) - result |= blockExit(s.elsebody, func, mustNotThrow); + result |= blockExit(s.elsebody, func, eSink); } void visitPragma(PragmaStatement s) @@ -308,11 +309,11 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) void visitSwitch(SwitchStatement s) { result = BE.none; - result |= canThrow(s.condition, func, mustNotThrow); + result |= canThrow(s.condition, func, eSink !is null); if (s._body) { - result |= blockExit(s._body, func, mustNotThrow); + result |= blockExit(s._body, func, eSink); if (result & BE.break_) { result |= BE.fallthru; @@ -325,12 +326,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) void visitCase(CaseStatement s) { - result = blockExit(s.statement, func, mustNotThrow); + result = blockExit(s.statement, func, eSink); } void visitDefault(DefaultStatement s) { - result = blockExit(s.statement, func, mustNotThrow); + result = blockExit(s.statement, func, eSink); } void visitGotoDefault(GotoDefaultStatement s) @@ -353,7 +354,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { result = BE.return_; if (s.exp) - result |= canThrow(s.exp, func, mustNotThrow); + result |= canThrow(s.exp, func, eSink !is null); } void visitBreak(BreakStatement s) @@ -369,20 +370,20 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) void visitSynchronized(SynchronizedStatement s) { - result = blockExit(s._body, func, mustNotThrow); + result = blockExit(s._body, func, eSink); } void visitWith(WithStatement s) { result = BE.none; - result |= canThrow(s.exp, func, mustNotThrow); - result |= blockExit(s._body, func, mustNotThrow); + result |= canThrow(s.exp, func, eSink !is null); + result |= blockExit(s._body, func, eSink); } void visitTryCatch(TryCatchStatement s) { assert(s._body); - result = blockExit(s._body, func, false); + result = blockExit(s._body, func, null); int catchresult = 0; foreach (c; *s.catches) @@ -390,7 +391,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) if (c.type == Type.terror) continue; - int cresult = blockExit(c.handler, func, mustNotThrow); + int cresult = blockExit(c.handler, func, eSink); /* If we're catching Object, then there is no throwing */ @@ -411,10 +412,10 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) } catchresult |= cresult; } - if (mustNotThrow && (result & BE.throw_)) + if (eSink && (result & BE.throw_)) { // now explain why this is nothrow - blockExit(s._body, func, mustNotThrow); + blockExit(s._body, func, eSink); } result |= catchresult; } @@ -423,12 +424,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { result = BE.fallthru; if (s._body) - result = blockExit(s._body, func, false); + result = blockExit(s._body, func, null); // check finally body as well, it may throw (bug #4082) int finalresult = BE.fallthru; if (s.finalbody) - finalresult = blockExit(s.finalbody, func, false); + finalresult = blockExit(s.finalbody, func, null); // If either body or finalbody halts if (result == BE.halt) @@ -436,13 +437,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) if (finalresult == BE.halt) result = BE.none; - if (mustNotThrow) + if (eSink) { // now explain why this is nothrow if (s._body && (result & BE.throw_)) - blockExit(s._body, func, mustNotThrow); + blockExit(s._body, func, eSink); if (s.finalbody && (finalresult & BE.throw_)) - blockExit(s.finalbody, func, mustNotThrow); + blockExit(s.finalbody, func, eSink); } version (none) @@ -452,7 +453,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) // destructor call, exit of synchronized statement, etc. if (result == BE.halt && finalresult != BE.halt && s.finalbody && s.finalbody.hasCode()) { - s.finalbody.warning("statement is not reachable"); + eSink.warning(s.finalbody.loc, "statement is not reachable"); } } @@ -472,12 +473,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) if (s.internalThrow) { // https://issues.dlang.org/show_bug.cgi?id=8675 - // Allow throwing 'Throwable' object even if mustNotThrow. + // Allow throwing 'Throwable' object even if eSink. result = BE.fallthru; return; } - result = checkThrow(s.loc, s.exp, mustNotThrow, func); + result = checkThrow(s.loc, s.exp, func, eSink); } void visitGoto(GotoStatement s) @@ -489,7 +490,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) void visitLabel(LabelStatement s) { //printf("LabelStatement::blockExit(%p)\n", s); - result = blockExit(s.statement, func, mustNotThrow); + result = blockExit(s.statement, func, eSink); if (s.breaks) result |= BE.fallthru; } @@ -502,8 +503,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) { if(func) func.setThrow(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); - if (mustNotThrow) - s.error("`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); // TODO + if (eSink) + eSink.error(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); // TODO else result |= BE.throw_; } @@ -528,15 +529,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) + Params: + loc = location of the `throw` + exp = expression yielding the throwable - + mustNotThrow = inside of a `nothrow` scope? + + eSink = if !null then inside of a `nothrow` scope + func = function containing the `throw` + + Returns: `BE.[err]throw` depending on the type of `exp` +/ -BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow, FuncDeclaration func) +BE checkThrow(ref const Loc loc, Expression exp, FuncDeclaration func, ErrorSink eSink) { - import dmd.errors : error; - Type t = exp.type.toBasetype(); ClassDeclaration cd = t.isClassHandle(); assert(cd); @@ -545,8 +544,8 @@ BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow, FuncDe { return BE.errthrow; } - if (mustNotThrow) - loc.error("`%s` is thrown but not caught", exp.type.toChars()); + if (eSink) + eSink.error(loc, "`%s` is thrown but not caught", exp.type.toChars()); else if (func) func.setThrow(loc, "`%s` is thrown but not caught", exp.type); diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index ba13eb084bd..4cead300f40 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -202,7 +202,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN override void visit(ThrowExp te) { - const res = checkThrow(te.loc, te.e1, mustNotThrow, func); + const res = checkThrow(te.loc, te.e1, func, mustNotThrow ? global.errorSink : null); assert((res & ~(CT.exception | CT.error)) == 0); result |= res; } diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d index feaa3c7ee6b..8cfad5916c7 100644 --- a/gcc/d/dmd/chkformat.d +++ b/gcc/d/dmd/chkformat.d @@ -15,7 +15,7 @@ import core.stdc.ctype : isdigit; import dmd.astenums; import dmd.cond; -import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.globals; import dmd.identifier; @@ -53,6 +53,7 @@ import dmd.target; * format = format string * args = arguments to match with format string * isVa_list = if a "v" function (format check only) + * eSink = where the error messages go * * Returns: * `true` if errors occurred @@ -60,7 +61,8 @@ import dmd.target; * C99 7.19.6.1 * https://www.cplusplus.com/reference/cstdio/printf/ */ -bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list) +public +bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list, ErrorSink eSink) { //printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr); size_t n; // index in args @@ -87,7 +89,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre { // format check only if (fmt == Format.error) - deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); + eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); continue; } @@ -96,7 +98,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre if (n == args.length) { if (args.length < (n + 1)) - deprecation(loc, "more format specifiers than %d arguments", cast(int)n); + eSink.deprecation(loc, "more format specifiers than %d arguments", cast(int)n); else skip = true; return null; @@ -106,7 +108,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual) { - deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`", + eSink.deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`", prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars()); } @@ -178,7 +180,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre 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); + eSink.errorSupplemental(e.loc, "C `long` is %d bytes on your system", c_longsize); } break; @@ -226,7 +228,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre break; case Format.n: // pointer to int - if (!(t.ty == Tpointer && tnext.ty == Tint32)) + if (!(t.ty == Tpointer && tnext.ty == Tint32 && tnext.isMutable())) errorMsg(null, e, "int*", t); break; @@ -286,7 +288,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre break; case Format.error: - deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); + eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); break; case Format.GNU_m: @@ -327,6 +329,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre * format = format string * args = arguments to match with format string * isVa_list = if a "v" function (format check only) + * eSink = where the error messages go * * Returns: * `true` if errors occurred @@ -334,7 +337,8 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre * C99 7.19.6.2 * https://www.cplusplus.com/reference/cstdio/scanf/ */ -bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list) +public +bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list, ErrorSink eSink) { size_t n = 0; for (size_t i = 0; i < format.length;) @@ -357,7 +361,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres { // format check only if (fmt == Format.error) - deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); + eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); continue; } @@ -366,7 +370,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres if (n == args.length) { if (!asterisk) - deprecation(loc, "more format specifiers than %d arguments", cast(int)n); + eSink.deprecation(loc, "more format specifiers than %d arguments", cast(int)n); return null; } return args[n++]; @@ -374,7 +378,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual) { - deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`", + eSink.deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`", prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars()); } @@ -512,7 +516,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres break; case Format.error: - deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); + eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr); break; case Format.GNU_m: @@ -523,6 +527,8 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres return false; } +/*****************************************************************************************************/ + private: /************************************** diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index 4cff1ecf49c..181268ec26c 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -297,7 +297,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc) } auto fparams = new Parameters(); - fparams.push(new Parameter(STC.nodtor, sd.type, Id.p, null, null)); + fparams.push(new Parameter(loc, STC.nodtor, sd.type, Id.p, null, null)); auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_); auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf); fop.storage_class |= STC.inference; @@ -546,10 +546,11 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc) TypeFunction tfeqptr; { Scope scx; + scx.eSink = sc.eSink; /* const bool opEquals(ref const S s); */ auto parameters = new Parameters(); - parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null)); + parameters.push(new Parameter(Loc.initial, STC.ref_ | STC.const_, sd.type, null, null, null)); tfeqptr = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d); tfeqptr.mod = MODFlags.const_; tfeqptr = cast(TypeFunction)tfeqptr.typeSemantic(Loc.initial, &scx); @@ -577,7 +578,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc) Loc declLoc; // loc is unnecessary so __xopEquals is never called directly Loc loc; // loc is unnecessary so errors are gagged auto parameters = new Parameters(); - parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null)); + parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null)); auto tf = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d, STC.const_); tf = tf.addSTC(STC.const_).toTypeFunction(); Identifier id = Id.xopEquals; @@ -620,10 +621,11 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) TypeFunction tfcmpptr; { Scope scx; + scx.eSink = sc.eSink; /* const int opCmp(ref const S s); */ auto parameters = new Parameters(); - parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null)); + parameters.push(new Parameter(Loc.initial, STC.ref_ | STC.const_, sd.type, null, null, null)); tfcmpptr = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d); tfcmpptr.mod = MODFlags.const_; tfcmpptr = cast(TypeFunction)tfcmpptr.typeSemantic(Loc.initial, &scx); @@ -701,7 +703,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) Loc declLoc; // loc is unnecessary so __xopCmp is never called directly Loc loc; // loc is unnecessary so errors are gagged auto parameters = new Parameters(); - parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null)); + parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null)); auto tf = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d, STC.const_); tf = tf.addSTC(STC.const_).toTypeFunction(); Identifier id = Id.xopCmp; @@ -820,7 +822,7 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc) Loc declLoc; // loc is unnecessary so __xtoHash is never called directly Loc loc; // internal code should have no loc to prevent coverage auto parameters = new Parameters(); - parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null)); + parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null)); auto tf = new TypeFunction(ParameterList(parameters), Type.thash_t, LINK.d, STC.nothrow_ | STC.trusted); Identifier id = Id.xtoHash; auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf); @@ -1074,7 +1076,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara // // TODO: if (del) delete (char*)this; // return (void*) this; // } - Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null); + Parameter delparam = new Parameter(Loc.initial, STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null); Parameters* params = new Parameters; params.push(delparam); const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later @@ -1126,7 +1128,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc) return null; // Generate shim only when ABI incompatible on target platform - if (ad.classKind != ClassKind.cpp || !target.cpp.wrapDtorInExternD) + if (dtor._linkage != LINK.cpp || !target.cpp.wrapDtorInExternD) return dtor; // generate member function that adjusts calling convention @@ -1514,7 +1516,7 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const { auto fparams = new Parameters(); auto structType = sd.type; - fparams.push(new Parameter(paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null)); + fparams.push(new Parameter(Loc.initial, paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null)); ParameterList pList = ParameterList(fparams); auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_); auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true); diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d index 360acf590bb..76cef77d8ed 100644 --- a/gcc/d/dmd/cond.d +++ b/gcc/d/dmd/cond.d @@ -322,7 +322,7 @@ extern (C++) final class StaticForeach : RootObject foreach (params; pparams) { auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.prm; - params.push(new Parameter(p.storageClass, p.type, p.ident, null, null)); + params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null)); } } Expression[2] res; diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 03383d13fd5..b05d81d3b14 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -626,7 +626,7 @@ final class CParser(AST) : Parser!AST default: // ImportC extensions: parse as a D asm block. - s = parseAsm(); + s = parseAsm(compileEnv.masm); break; } break; @@ -3114,12 +3114,13 @@ final class CParser(AST) : Parser!AST } Identifier id; + const paramLoc = token.loc; auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier); if (token.value == TOK.__attribute__) cparseGnuAttributes(specifier); if (specifier.mod & MOD.xconst) t = toConst(t); - auto param = new AST.Parameter(specifiersToSTC(LVL.parameter, specifier), + auto param = new AST.Parameter(paramLoc, specifiersToSTC(LVL.parameter, specifier), t, id, null, null); parameters.push(param); if (token.value == TOK.rightParenthesis || token.value == TOK.endOfFile) @@ -3297,8 +3298,10 @@ final class CParser(AST) : Parser!AST nextToken(); else { - error("extended-decl-modifier expected"); - break; + error("extended-decl-modifier expected after `__declspec(`, saw `%s` instead", token.toChars()); + nextToken(); + if (token.value != TOK.rightParenthesis) + break; } } } diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d index 5d74ec4c91a..0c32fad7803 100644 --- a/gcc/d/dmd/cppmangle.d +++ b/gcc/d/dmd/cppmangle.d @@ -23,7 +23,6 @@ module dmd.cppmangle; -import core.stdc.string; import core.stdc.stdio; import dmd.arraytypes; @@ -46,7 +45,6 @@ import dmd.common.outbuffer; import dmd.root.rootobject; import dmd.root.string; import dmd.target; -import dmd.tokens; import dmd.typesem; import dmd.visitor; diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d index d355538e97c..c0a2ca6a2a5 100644 --- a/gcc/d/dmd/ctfeexpr.d +++ b/gcc/d/dmd/ctfeexpr.d @@ -12,7 +12,6 @@ module dmd.ctfeexpr; import core.stdc.stdio; -import core.stdc.stdlib; import core.stdc.string; import dmd.arraytypes; import dmd.astenums; @@ -306,9 +305,10 @@ UnionExp copyLiteral(Expression e) } if (auto aae = e.isAssocArrayLiteralExp()) { - emplaceExp!(AssocArrayLiteralExp)(&ue, e.loc, copyLiteralArray(aae.keys), copyLiteralArray(aae.values)); + emplaceExp!(AssocArrayLiteralExp)(&ue, aae.loc, copyLiteralArray(aae.keys), copyLiteralArray(aae.values)); AssocArrayLiteralExp r = ue.exp().isAssocArrayLiteralExp(); - r.type = e.type; + r.type = aae.type; + r.lowering = aae.lowering; r.ownedByCtfe = OwnedBy.ctfe; return ue; } diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index b2aa6433baf..d7cb2b1f970 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -23,7 +23,6 @@ import dmd.declaration; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; -import dmd.errors; import dmd.escape; import dmd.expression; import dmd.expressionsem; @@ -32,7 +31,6 @@ import dmd.globals; import dmd.hdrgen; import dmd.location; import dmd.impcnvtab; -import dmd.id; import dmd.importc; import dmd.init; import dmd.intrange; @@ -44,7 +42,6 @@ import dmd.root.rmem; import dmd.root.utf; import dmd.tokens; import dmd.typesem; -import dmd.visitor; enum LOG = false; @@ -73,7 +70,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) { // no need for an extra cast when matching is exact - if (match == MATCH.convert && e.type.isTypeNoreturn()) + if (match == MATCH.convert && e.type.isTypeNoreturn() && e.op != EXP.type) { return specialNoreturnCast(e, t); } @@ -174,7 +171,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) { //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars()); FuncExp fe; - if (e.matchType(t, sc, &fe) > MATCH.nomatch) + if (e.matchType(t, sc, &fe, global.errorSink) > MATCH.nomatch) { return fe; } @@ -1075,7 +1072,7 @@ MATCH implicitConvTo(Expression e, Type t) MATCH visitFunc(FuncExp e) { //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars()); - MATCH m = e.matchType(t, null, null, 1); + MATCH m = e.matchType(t, null, null, global.errorSinkNull); if (m > MATCH.nomatch) { return m; @@ -1537,7 +1534,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) { return e; } - if (e.type.isTypeNoreturn()) + if (e.type.isTypeNoreturn() && e.op != EXP.type) { return specialNoreturnCast(e, t); } @@ -2489,7 +2486,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) { //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars()); FuncExp fe; - if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch) + if (e.matchType(t, sc, &fe, global.errorSinkNull) > MATCH.nomatch) { return fe; } diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d index 20cb82e1a36..b446e77b879 100644 --- a/gcc/d/dmd/dclass.d +++ b/gcc/d/dmd/dclass.d @@ -19,14 +19,12 @@ import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; import dmd.astenums; -import dmd.attrib; import dmd.gluelayer; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.func; -import dmd.globals; import dmd.id; import dmd.identifier; import dmd.location; @@ -879,6 +877,10 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return 0; } + // opaque class is not abstract if it is not declared abstract + if (!members) + return no(); + for (size_t i = 0; i < members.length; i++) { auto s = (*members)[i]; diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index 8a91a802dae..b21678ce508 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -16,7 +16,6 @@ import core.stdc.stdio; import dmd.aggregate; import dmd.arraytypes; import dmd.astenums; -import dmd.attrib; import dmd.ctorflow; import dmd.dclass; import dmd.delegatize; @@ -647,11 +646,11 @@ extern (C++) final class TupleDeclaration : Declaration { buf.printf("_%s_%d", ident.toChars(), i); auto id = Identifier.idPool(buf.extractSlice()); - auto arg = new Parameter(STC.in_, t, id, null); + auto arg = new Parameter(Loc.initial, STC.in_, t, id, null); } else { - auto arg = new Parameter(0, t, null, null, null); + auto arg = new Parameter(Loc.initial, 0, t, null, null, null); } (*args)[i] = arg; if (!t.deco) @@ -1602,6 +1601,8 @@ extern (C++) class VarDeclaration : Declaration { inuse++; _init = _init.initializerSemantic(_scope, type, INITinterpret); + import dmd.semantic2 : lowerStaticAAs; + lowerStaticAAs(this, _scope); _scope = null; inuse--; } diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d index 559f103908d..490ef56646f 100644 --- a/gcc/d/dmd/delegatize.d +++ b/gcc/d/dmd/delegatize.d @@ -21,7 +21,6 @@ import dmd.dsymbol; import dmd.expression; import dmd.expressionsem; import dmd.func; -import dmd.globals; import dmd.init; import dmd.initsem; import dmd.location; diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d index 87b40b854b9..955a17dc6e8 100644 --- a/gcc/d/dmd/denum.d +++ b/gcc/d/dmd/denum.d @@ -24,13 +24,11 @@ import dmd.dscope; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.expression; -import dmd.globals; import dmd.id; import dmd.identifier; import dmd.init; import dmd.location; import dmd.mtype; -import dmd.tokens; import dmd.typesem; import dmd.visitor; diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 59483511f6d..7cdafda050c 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -40,7 +40,6 @@ import dmd.init; import dmd.initsem; import dmd.location; import dmd.mtype; -import dmd.printast; import dmd.root.rmem; import dmd.root.array; import dmd.root.ctfloat; @@ -635,8 +634,6 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta { if (ctfeGlobals.callDepth > CTFE_RECURSION_LIMIT) { - // This is a compiler error. It must not be suppressed. - global.gag = 0; fd.error("CTFE recursion limit exceeded"); e = CTFEExp.cantexp; break; @@ -790,7 +787,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate) istate.start = null; } - s.error("statement `%s` cannot be interpreted at compile time", s.toChars()); + error(s.loc, "statement `%s` cannot be interpreted at compile time", s.toChars()); result = CTFEExp.cantexp; } @@ -976,7 +973,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate) { // To support this, we need to copy all the closure vars // into the delegate literal. - s.error("closures are not yet supported in CTFE"); + error(s.loc, "closures are not yet supported in CTFE"); result = CTFEExp.cantexp; return; } @@ -1259,7 +1256,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate) if (!scase) { if (s.hasNoDefault) - s.error("no `default` or `case` for `%s` in `switch` statement", econdition.toChars()); + error(s.loc, "no `default` or `case` for `%s` in `switch` statement", econdition.toChars()); scase = s.sdefault; } @@ -1599,7 +1596,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate) return; istate.start = null; } - s.error("`asm` statements cannot be interpreted at compile time"); + error(s.loc, "`asm` statements cannot be interpreted at compile time"); result = CTFEExp.cantexp; } @@ -6105,7 +6102,8 @@ public: result = interpret(&ue, e.msg, istate); if (exceptionOrCant(result)) return; - if (StringExp se = result.isStringExp()) + result = scrubReturnValue(e.loc, result); + if (StringExp se = result.toStringExp()) e.error("%s", se.toStringz().ptr); else e.error("%s", result.toChars()); diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d index 6fc23e99e86..6e6c4b17e99 100644 --- a/gcc/d/dmd/dmacro.d +++ b/gcc/d/dmd/dmacro.d @@ -13,11 +13,12 @@ module dmd.dmacro; import core.stdc.ctype; import core.stdc.string; -import dmd.doc; import dmd.common.outbuffer; import dmd.root.rmem; -extern (C++) struct MacroTable +@trusted: + +struct MacroTable { /********************************** * Define name=text macro. @@ -26,7 +27,7 @@ extern (C++) struct MacroTable * name = name of macro * text = text of macro */ - extern (D) void define(const(char)[] name, const(char)[] text) nothrow pure @safe + void define(const(char)[] name, const(char)[] text) nothrow pure @safe { //printf("MacroTable::define('%.*s' = '%.*s')\n", cast(int)name.length, name.ptr, text.length, text.ptr); if (auto table = name in mactab) @@ -37,13 +38,16 @@ extern (C++) struct MacroTable mactab[name] = new Macro(name, text); } + alias fp_t = bool function(const(char)* p) @nogc nothrow pure; + /***************************************************** * Look for macros in buf and expand them in place. * Only look at the text in buf from start to pend. * * Returns: `true` on success, `false` when the recursion limit was reached */ - extern (D) bool expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg, int recursionLimit) nothrow pure + bool expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg, int recursionLimit, + fp_t isIdStart, fp_t isIdTail) nothrow pure { version (none) { @@ -101,7 +105,7 @@ extern (C++) struct MacroTable end += marg.length - 2; // Scan replaced text for further expansion size_t mend = u + marg.length; - const success = expand(buf, u, mend, null, recursionLimit); + const success = expand(buf, u, mend, null, recursionLimit, isIdStart, isIdTail); if (!success) return false; end += mend - (u + marg.length); @@ -119,7 +123,7 @@ extern (C++) struct MacroTable end += -2 + 2 + marg.length + 2; // Scan replaced text for further expansion size_t mend = u + 2 + marg.length; - const success = expand(buf, u + 2, mend, null, recursionLimit); + const success = expand(buf, u + 2, mend, null, recursionLimit, isIdStart, isIdTail); if (!success) return false; end += mend - (u + 2 + marg.length); @@ -149,7 +153,7 @@ extern (C++) struct MacroTable /* Scan forward to find end of macro name and * beginning of macro argument (marg). */ - for (v = u + 2; v < end; v += utfStride(p + v)) + for (v = u + 2; v < end; v += utfStride(p[v])) { if (!isIdTail(p + v)) { @@ -228,7 +232,7 @@ extern (C++) struct MacroTable // Scan replaced text for further expansion m.inuse++; size_t mend = v + 1 + 2 + m.text.length + 2; - const success = expand(buf, v + 1, mend, marg, recursionLimit); + const success = expand(buf, v + 1, mend, marg, recursionLimit, isIdStart, isIdTail); if (!success) return false; end += mend - (v + 1 + 2 + m.text.length + 2); @@ -260,7 +264,7 @@ extern (C++) struct MacroTable private: - extern (D) Macro* search(const(char)[] name) @nogc nothrow pure @safe + Macro* search(const(char)[] name) @nogc nothrow pure @safe { //printf("Macro::search(%.*s)\n", cast(int)name.length, name.ptr); if (auto table = name in mactab) @@ -299,7 +303,7 @@ struct Macro * copy allocated with mem.xmalloc() */ -char[] memdup(const(char)[] p) nothrow pure @trusted +char[] memdup(const(char)[] p) nothrow pure { size_t len = p.length; return (cast(char*)memcpy(mem.xmalloc(len), p.ptr, len))[0 .. len]; @@ -424,3 +428,35 @@ Largstart: //printf("extractArg%d('%.*s') = '%.*s'\n", n, cast(int)end, p, cast(int)marg.length, marg.ptr); return v; } + +/***************************************** + * Get number of UTF-8 code units in code point that starts with `c` + * Params: + * c = starting code unit + * Returns: number of UTF-8 code units (i.e. bytes), else 1 on invalid UTF start + */ +@safe +int utfStride(char c) @nogc nothrow pure +{ + return + c < 0x80 ? 1 : + c < 0xC0 ? 1 : // invalid UTF start + c < 0xE0 ? 2 : + c < 0xF0 ? 3 : + c < 0xF8 ? 4 : + c < 0xFC ? 5 : + c < 0xFE ? 6 : + 1; // invalid UTF start +} + +unittest +{ + assert(utfStride(0) == 1); + assert(utfStride(0x80) == 1); + assert(utfStride(0xC0) == 2); + assert(utfStride(0xE0) == 3); + assert(utfStride(0xF0) == 4); + assert(utfStride(0xF8) == 5); + assert(utfStride(0xFC) == 6); + assert(utfStride(0xFE) == 1); +} diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 4a2e15c981b..eb68b31edeb 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -780,7 +780,9 @@ extern (C++) final class Module : Package { filetype = FileType.c; + global.compileEnv.masm = target.os == Target.OS.Windows && !target.omfobj; // Microsoft inline assembler format scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines, &global.compileEnv); + global.compileEnv.masm = false; p.nextToken(); checkCompiledImport(); members = p.parseModule(); @@ -1253,7 +1255,7 @@ extern (C++) final class Module : Package // Back end int doppelganger; // sub-module Symbol* cov; // private uint[] __coverage; - uint* covb; // bit array of valid code line numbers + uint[] covb; // bit array of valid code line numbers Symbol* sictor; // module order independent constructor Symbol* sctor; // module constructor Symbol* sdtor; // module destructor diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d index 887fd6c696c..5488d5a0008 100644 --- a/gcc/d/dmd/doc.d +++ b/gcc/d/dmd/doc.d @@ -52,9 +52,11 @@ import dmd.root.rmem; import dmd.root.string; import dmd.root.utf; import dmd.tokens; -import dmd.utils; import dmd.visitor; +private: + +public struct Escape { const(char)[][char.max] strings; @@ -94,7 +96,7 @@ struct Escape /*********************************************************** */ -private class Section +class Section { const(char)[] name; const(char)[] body_; @@ -105,7 +107,7 @@ private class Section assert(0); } - void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf) + void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf) { assert(a.length); if (name.length) @@ -151,16 +153,16 @@ private class Section size_t o = buf.length; buf.write(body_); escapeStrayParenthesis(loc, buf, o, true, sc.eSink); - highlightText(sc, a, loc, *buf, o); + highlightText(sc, a, loc, buf, o); buf.writestring(")"); } } /*********************************************************** */ -private final class ParamSection : Section +final class ParamSection : Section { - override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf) + override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf) { assert(a.length); Dsymbol s = (*a)[0]; // test @@ -241,7 +243,7 @@ private final class ParamSection : Section } else if (fparam && fparam.type && fparam.ident) { - .toCBuffer(fparam.type, buf, fparam.ident, &hgs); + toCBuffer(fparam.type, buf, fparam.ident, hgs); } else { @@ -257,7 +259,7 @@ private final class ParamSection : Section buf.write(namestart[0 .. namelen]); } escapeStrayParenthesis(loc, buf, o, true, sc.eSink); - highlightCode(sc, a, *buf, o); + highlightCode(sc, a, buf, o); } buf.writestring(")"); buf.writestring("$(DDOC_PARAM_DESC "); @@ -265,7 +267,7 @@ private final class ParamSection : Section size_t o = buf.length; buf.write(textstart[0 .. textlen]); escapeStrayParenthesis(loc, buf, o, true, sc.eSink); - highlightText(sc, a, loc, *buf, o); + highlightText(sc, a, loc, buf, o); } buf.writestring(")"); } @@ -317,19 +319,19 @@ private final class ParamSection : Section /*********************************************************** */ -private final class MacroSection : Section +final class MacroSection : Section { - override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf) + override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf) { //printf("MacroSection::write()\n"); DocComment.parseMacros(dc.escapetable, *dc.pmacrotable, body_); } } -private alias Sections = Array!(Section); +alias Sections = Array!(Section); // Workaround for missing Parameter instance for variadic params. (it's unnecessary to instantiate one). -private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe +bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe { foreach (member; *a) { @@ -340,7 +342,7 @@ private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe return false; } -private Dsymbol getEponymousMember(TemplateDeclaration td) @safe +Dsymbol getEponymousMember(TemplateDeclaration td) @safe { if (!td.onemember) return null; @@ -355,7 +357,7 @@ private Dsymbol getEponymousMember(TemplateDeclaration td) @safe return null; } -private TemplateDeclaration getEponymousParent(Dsymbol s) @safe +TemplateDeclaration getEponymousParent(Dsymbol s) @safe { if (!s.parent) return null; @@ -363,40 +365,46 @@ private TemplateDeclaration getEponymousParent(Dsymbol s) @safe return (td && getEponymousMember(td)) ? td : null; } -private immutable ddoc_default = import("default_ddoc_theme." ~ ddoc_ext); -private immutable ddoc_decl_s = "$(DDOC_DECL "; -private immutable ddoc_decl_e = ")\n"; -private immutable ddoc_decl_dd_s = "$(DDOC_DECL_DD "; -private immutable ddoc_decl_dd_e = ")\n"; +immutable ddoc_default = import("default_ddoc_theme." ~ ddoc_ext); +immutable ddoc_decl_s = "$(DDOC_DECL "; +immutable ddoc_decl_e = ")\n"; +immutable ddoc_decl_dd_s = "$(DDOC_DECL_DD "; +immutable ddoc_decl_dd_e = ")\n"; /**************************************************** + * Generate Ddoc file for Module m. + * Params: + * m = Module + * ddoctext_ptr = combined text of .ddoc files for macro definitions + * ddoctext_length = extant of ddoctext_ptr + * datetime = charz returned by ctime() + * eSink = send error messages to eSink + * outbuf = append the Ddoc text to this */ -extern(C++) void gendocfile(Module m, ErrorSink eSink) +public +extern(C++) void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf) { - __gshared OutBuffer mbuf; - __gshared int mbuf_done; - OutBuffer buf; - //printf("Module::gendocfile()\n"); - if (!mbuf_done) // if not already read the ddoc files - { - mbuf_done = 1; - // Use our internal default - mbuf.writestring(ddoc_default); - // Override with DDOCFILE specified in the sc.ini file - char* p = getenv("DDOCFILE"); - if (p) - global.params.ddoc.files.shift(p); - // Override with the ddoc macro files from the command line - for (size_t i = 0; i < global.params.ddoc.files.length; i++) - { - auto buffer = readFile(m.loc, global.params.ddoc.files[i]); - // BUG: convert file contents to UTF-8 before use - const data = buffer.data; - //printf("file: '%.*s'\n", cast(int)data.length, data.ptr); - mbuf.write(data); - } - } - DocComment.parseMacros(m.escapetable, m.macrotable, mbuf[]); + gendocfile(m, ddoctext_ptr[0 .. ddoctext_length], datetime, eSink, outbuf); +} + +/**************************************************** + * Generate Ddoc text for Module `m` and append it to `outbuf`. + * Params: + * m = Module + * ddoctext = combined text of .ddoc files for macro definitions + * datetime = charz returned by ctime() + * eSink = send error messages to eSink + * outbuf = append the Ddoc text to this + */ +public +void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf) +{ + // Load internal default macros first + DocComment.parseMacros(m.escapetable, m.macrotable, ddoc_default[]); + + // Ddoc files override default macros + DocComment.parseMacros(m.escapetable, m.macrotable, ddoctext); + Scope* sc = Scope.createGlobal(m, eSink); // create root scope DocComment* dc = DocComment.parse(m, m.comment); dc.pmacrotable = &m.macrotable; @@ -409,14 +417,9 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink) m.macrotable.define("TITLE", p); } // Set time macros - { - time_t t; - time(&t); - char* p = ctime(&t); - p = mem.xstrdup(p); - m.macrotable.define("DATETIME", p.toDString()); - m.macrotable.define("YEAR", p[20 .. 20 + 4]); - } + m.macrotable.define("DATETIME", datetime[0 .. 26]); + m.macrotable.define("YEAR", datetime[20 .. 20 + 4]); + const srcfilename = m.srcfile.toString(); m.macrotable.define("SRCFILENAME", srcfilename); const docfilename = m.docfile.toString(); @@ -426,6 +429,8 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink) dc.copyright.nooutput = 1; m.macrotable.define("COPYRIGHT", dc.copyright.body_); } + + OutBuffer buf; if (m.filetype == FileType.ddoc) { const ploc = m.md ? &m.md.loc : &m.loc; @@ -433,14 +438,14 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink) if (!loc.filename) loc.filename = srcfilename.ptr; - size_t commentlen = strlen(cast(char*)m.comment); + size_t commentlen = m.comment ? strlen(cast(char*)m.comment) : 0; Dsymbols a; // https://issues.dlang.org/show_bug.cgi?id=9764 // Don't push m in a, to prevent emphasize ddoc file name. if (dc.macros) { commentlen = dc.macros.name.ptr - m.comment; - dc.macros.write(loc, dc, sc, &a, &buf); + dc.macros.write(loc, dc, sc, &a, buf); } buf.write(m.comment[0 .. commentlen]); highlightText(sc, &a, loc, buf, 0); @@ -449,73 +454,47 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink) { Dsymbols a; a.push(m); - dc.writeSections(sc, &a, &buf); + dc.writeSections(sc, &a, buf); emitMemberComments(m, buf, sc); } //printf("BODY= '%.*s'\n", cast(int)buf.length, buf.data); m.macrotable.define("BODY", buf[]); + OutBuffer buf2; buf2.writestring("$(DDOC)"); size_t end = buf2.length; - const success = m.macrotable.expand(buf2, 0, end, null, global.recursionLimit); + // Expand buf in place with macro expansions + const success = m.macrotable.expand(buf2, 0, end, null, global.recursionLimit, &isIdStart, &isIdTail); if (!success) eSink.error(Loc.initial, "DDoc macro expansion limit exceeded; more than %d expansions.", global.recursionLimit); - version (all) + /* Remove all the escape sequences from buf, + * and make CR-LF the newline. + */ + const slice = buf2[]; + outbuf.reserve(slice.length); + auto p = slice.ptr; + for (size_t j = 0; j < slice.length; j++) { - /* Remove all the escape sequences from buf2, - * and make CR-LF the newline. - */ + char c = p[j]; + if (c == 0xFF && j + 1 < slice.length) { - const slice = buf2[]; - buf.setsize(0); - buf.reserve(slice.length); - auto p = slice.ptr; - for (size_t j = 0; j < slice.length; j++) - { - char c = p[j]; - if (c == 0xFF && j + 1 < slice.length) - { - j++; - continue; - } - if (c == '\n') - buf.writeByte('\r'); - else if (c == '\r') - { - buf.writestring("\r\n"); - if (j + 1 < slice.length && p[j + 1] == '\n') - { - j++; - } - continue; - } - buf.writeByte(c); - } + j++; + continue; } - writeFile(m.loc, m.docfile.toString(), buf[]); - } - else - { - /* Remove all the escape sequences from buf2 - */ + if (c == '\n') + outbuf.writeByte('\r'); + else if (c == '\r') { - size_t i = 0; - char* p = buf2.data; - for (size_t j = 0; j < buf2.length; j++) + outbuf.writestring("\r\n"); + if (j + 1 < slice.length && p[j + 1] == '\n') { - if (p[j] == 0xFF && j + 1 < buf2.length) - { - j++; - continue; - } - p[i] = p[j]; - i++; + j++; } - buf2.setsize(i); + continue; } - writeFile(m.loc, m.docfile.toString(), buf2[]); + outbuf.writeByte(c); } } @@ -526,11 +505,12 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink) * to preserve text literally. This also means macros in the * text won't be expanded. */ -void escapeDdocString(OutBuffer* buf, size_t start) +public +void escapeDdocString(ref OutBuffer buf, size_t start) { for (size_t u = start; u < buf.length; u++) { - char c = (*buf)[u]; + char c = buf[u]; switch (c) { case '$': @@ -568,14 +548,14 @@ void escapeDdocString(OutBuffer* buf, size_t start) * directly preceeded by a backslash with $(LPAREN) or $(RPAREN) instead of * counting them as stray parentheses */ -private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool respectBackslashEscapes, ErrorSink eSink) +private void escapeStrayParenthesis(Loc loc, ref OutBuffer buf, size_t start, bool respectBackslashEscapes, ErrorSink eSink) { uint par_open = 0; char inCode = 0; bool atLineStart = true; for (size_t u = start; u < buf.length; u++) { - char c = (*buf)[u]; + char c = buf[u]; switch (c) { case '(': @@ -619,7 +599,7 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool // Issue 15465: don't try to escape unbalanced parens inside code // blocks. int numdash = 1; - for (++u; u < buf.length && (*buf)[u] == c; ++u) + for (++u; u < buf.length && buf[u] == c; ++u) ++numdash; --u; if (c == '`' || (atLineStart && numdash >= 3)) @@ -635,14 +615,14 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool // replace backslash-escaped parens with their macros if (!inCode && respectBackslashEscapes && u+1 < buf.length) { - if ((*buf)[u+1] == '(' || (*buf)[u+1] == ')') + if (buf[u+1] == '(' || buf[u+1] == ')') { - const paren = (*buf)[u+1] == '(' ? "$(LPAREN)" : "$(RPAREN)"; + const paren = buf[u+1] == '(' ? "$(LPAREN)" : "$(RPAREN)"; buf.remove(u, 2); //remove the \) buf.insert(u, paren); //insert this instead u += 8; //skip over newly inserted macro } - else if ((*buf)[u+1] == '\\') + else if (buf[u+1] == '\\') ++u; } break; @@ -657,7 +637,7 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool for (size_t u = buf.length; u > start;) { u--; - char c = (*buf)[u]; + char c = buf[u]; switch (c) { case ')': @@ -683,14 +663,14 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool // Basically, this is to skip over things like private{} blocks in a struct or // class definition that don't add any components to the qualified name. -private Scope* skipNonQualScopes(Scope* sc) @safe +Scope* skipNonQualScopes(Scope* sc) @safe { while (sc && !sc.scopesym) sc = sc.enclosing; return sc; } -private bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent) +bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent) { if (!s || s.isPackage() || s.isModule()) return false; @@ -721,7 +701,7 @@ private bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includ return true; } -private void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false) +void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false) { Identifier ident; { @@ -846,7 +826,7 @@ private void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader /******************************* emitComment **********************************/ /** Get leading indentation from 'src' which represents lines of code. */ -private size_t getCodeIndent(const(char)* src) +size_t getCodeIndent(const(char)* src) { while (src && (*src == '\r' || *src == '\n')) ++src; // skip until we find the first non-empty line @@ -860,7 +840,7 @@ private size_t getCodeIndent(const(char)* src) } /** Recursively expand template mixin member docs into the scope. */ -private void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Scope* sc) +void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Scope* sc) { if (!tm.semanticRun) tm.dsymbolSemantic(sc); @@ -879,7 +859,7 @@ private void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Sc } } -private void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc) +void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc) { if (!sds.members) return; @@ -920,14 +900,14 @@ private void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc) buf.writestring(")"); } -private void emitVisibility(ref OutBuffer buf, Import i) +void emitVisibility(ref OutBuffer buf, Import i) { // imports are private by default, which is different from other declarations // so they should explicitly show their visibility emitVisibility(buf, i.visibility); } -private void emitVisibility(ref OutBuffer buf, Declaration d) +void emitVisibility(ref OutBuffer buf, Declaration d) { auto vis = d.visibility; if (vis.kind != Visibility.Kind.undefined && vis.kind != Visibility.Kind.public_) @@ -936,13 +916,13 @@ private void emitVisibility(ref OutBuffer buf, Declaration d) } } -private void emitVisibility(ref OutBuffer buf, Visibility vis) +void emitVisibility(ref OutBuffer buf, Visibility vis) { - visibilityToBuffer(&buf, vis); + visibilityToBuffer(buf, vis); buf.writeByte(' '); } -private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc) +void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc) { extern (C++) final class EmitComment : Visitor { @@ -1037,7 +1017,7 @@ private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc) // Put the ddoc comment as the document 'description' buf.writestring(ddoc_decl_dd_s); { - dc.writeSections(sc, &dc.a, buf); + dc.writeSections(sc, &dc.a, *buf); if (ScopeDsymbol sds = dc.a[0].isScopeDsymbol()) emitMemberComments(sds, *buf, sc); } @@ -1226,7 +1206,7 @@ private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc) s.accept(v); } -private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) +void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) { extern (C++) final class ToDocBuffer : Visitor { @@ -1246,7 +1226,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) //printf("Dsymbol::toDocbuffer() %s\n", s.toChars()); HdrGenState hgs; hgs.ddoc = true; - .toCBuffer(s, buf, &hgs); + toCBuffer(s, *buf, hgs); } void prefix(Dsymbol s) @@ -1296,7 +1276,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) HdrGenState hgs; hgs.ddoc = true; emitVisibility(*buf, i); - .toCBuffer(i, buf, &hgs); + toCBuffer(i, *buf, hgs); } override void visit(Declaration d) @@ -1315,10 +1295,10 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) Type origType = d.originalType ? d.originalType : d.type; if (origType.ty == Tfunction) { - functionToBufferFull(cast(TypeFunction)origType, buf, d.ident, &hgs, td); + functionToBufferFull(cast(TypeFunction)origType, *buf, d.ident, &hgs, td); } else - .toCBuffer(origType, buf, d.ident, &hgs); + toCBuffer(origType, *buf, d.ident, hgs); } else buf.writestring(d.ident.toString()); @@ -1331,7 +1311,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) { if (i) buf.writestring(", "); - toCBuffer((*td.origParameters)[i], buf, &hgs); + toCBuffer((*td.origParameters)[i], *buf, hgs); } } buf.writeByte(')'); @@ -1345,7 +1325,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) buf.writestring("$(DDOC_CONSTRAINT "); } - .toCBuffer(td.constraint, buf, &hgs); + toCBuffer(td.constraint, *buf, hgs); if (noFuncDecl) { @@ -1505,7 +1485,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) else { HdrGenState hgs; - .toCBuffer(bc.type, buf, null, &hgs); + toCBuffer(bc.type, *buf, null, hgs); } } buf.writestring(";\n"); @@ -1520,7 +1500,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) { buf.writestring(": $(DDOC_ENUM_BASETYPE "); HdrGenState hgs; - .toCBuffer(ed.memtype, buf, null, &hgs); + toCBuffer(ed.memtype, *buf, null, hgs); buf.writestring(")"); } buf.writestring(";\n"); @@ -1540,6 +1520,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) /*********************************************************** */ +public struct DocComment { Sections sections; // Section*[] @@ -1872,7 +1853,7 @@ struct DocComment } } - void writeSections(Scope* sc, Dsymbols* a, OutBuffer* buf) + void writeSections(Scope* sc, Dsymbols* a, ref OutBuffer buf) { assert(a.length); //printf("DocComment::writeSections()\n"); @@ -1897,7 +1878,7 @@ struct DocComment size_t o = buf.length; buf.write(sec.body_); escapeStrayParenthesis(loc, buf, o, true, sc.eSink); - highlightText(sc, a, loc, *buf, o); + highlightText(sc, a, loc, buf, o); buf.writestring(")"); } else @@ -1928,7 +1909,7 @@ struct DocComment buf.writestring("----\n"); buf.writestring(codedoc); buf.writestring("----\n"); - highlightText(sc, a, loc, *buf, o); + highlightText(sc, a, loc, buf, o); } buf.writestring(")"); } @@ -1948,7 +1929,7 @@ struct DocComment /***************************************** * Return true if comment consists entirely of "ditto". */ -private bool isDitto(const(char)* comment) +bool isDitto(const(char)* comment) { if (comment) { @@ -1962,13 +1943,13 @@ private bool isDitto(const(char)* comment) /********************************************** * Skip white space. */ -private const(char)* skipwhitespace(const(char)* p) +const(char)* skipwhitespace(const(char)* p) { return skipwhitespace(p.toDString).ptr; } /// Ditto -private const(char)[] skipwhitespace(const(char)[] p) @safe +const(char)[] skipwhitespace(const(char)[] p) @safe { foreach (idx, char c; p) { @@ -1993,7 +1974,7 @@ private const(char)[] skipwhitespace(const(char)[] p) @safe * chars = the characters to skip; order is unimportant * Returns: the index after skipping characters. */ -private size_t skipChars(ref OutBuffer buf, size_t i, string chars) @safe +size_t skipChars(ref OutBuffer buf, size_t i, string chars) @safe { Outer: foreach (j, c; buf[][i..$]) @@ -2028,7 +2009,7 @@ unittest { * r = the string to replace `c` with * Returns: `s` with `c` replaced with `r` */ -private inout(char)[] replaceChar(inout(char)[] s, char c, string r) pure @safe +inout(char)[] replaceChar(inout(char)[] s, char c, string r) pure @safe { int count = 0; foreach (char sc; s) @@ -2070,7 +2051,7 @@ unittest * s = the string to lowercase * Returns: the lowercase version of the string or the original if already lowercase */ -private string toLowercase(string s) pure @safe +string toLowercase(string s) pure @safe { string lower; foreach (size_t i; 0..s.length) @@ -2112,7 +2093,7 @@ unittest * to = the index within `buf` to stop counting at, exclusive * Returns: the indent */ -private int getMarkdownIndent(ref OutBuffer buf, size_t from, size_t to) @safe +int getMarkdownIndent(ref OutBuffer buf, size_t from, size_t to) @safe { const slice = buf[]; if (to > slice.length) @@ -2158,7 +2139,7 @@ size_t skiptoident(ref OutBuffer buf, size_t i) @safe /************************************************ * Scan forward past end of identifier. */ -private size_t skippastident(ref OutBuffer buf, size_t i) @safe +size_t skippastident(ref OutBuffer buf, size_t i) @safe { const slice = buf[]; while (i < slice.length) @@ -2188,7 +2169,7 @@ private size_t skippastident(ref OutBuffer buf, size_t i) @safe * Scan forward past end of an identifier that might * contain dots (e.g. `abc.def`) */ -private size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe +size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe { const slice = buf[]; bool lastCharWasDot; @@ -2250,7 +2231,7 @@ private size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe * i if not a URL * index just past it if it is a URL */ -private size_t skippastURL(ref OutBuffer buf, size_t i) +size_t skippastURL(ref OutBuffer buf, size_t i) { const slice = buf[][i .. $]; size_t j; @@ -2295,7 +2276,7 @@ Lno: * i = an index within `buf`. If `i` is after `iAt` then it gets * reduced by the length of the removed macro. */ -private void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t i) +void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t i) { if (!iAt) return; @@ -2320,7 +2301,7 @@ private void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t * loc = the current location within the file * Returns: whether a thematic break was replaced */ -private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_t iLineStart, const ref Loc loc) +bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_t iLineStart, const ref Loc loc) { const slice = buf[]; @@ -2356,7 +2337,7 @@ private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_ * the detected heading level from 1 to 6, or * 0 if not at an ATX heading */ -private int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe +int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe { const iHeadingStart = i; const iAfterHashes = skipChars(buf, i, "#"); @@ -2380,7 +2361,7 @@ private int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe * buf = an OutBuffer containing the DDoc * i = the index within `buf` to start looking for a suffix at */ -private void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i) +void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i) { size_t j = i; size_t iSuffixStart = 0; @@ -2425,7 +2406,7 @@ private void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i) * headingLevel = the level (1-6) of heading to end. Is set to `0` when this * function ends. */ -private void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEnd, const ref Loc loc, ref int headingLevel) +void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEnd, const ref Loc loc, ref int headingLevel) { char[5] heading = "$(H0 "; heading[3] = cast(char) ('0' + headingLevel); @@ -2446,7 +2427,7 @@ private void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEn * quoteLevel = the current quote level. Is set to `0` when this function ends. * Returns: the amount that `i` was moved */ -private size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLevel) +size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLevel) { const length = quoteLevel; for (; quoteLevel > 0; --quoteLevel) @@ -2468,7 +2449,7 @@ private size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLe * `0` when this function ends. * Returns: the amount that `i` was moved */ -private size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref MarkdownList[] nestedLists, ref int quoteLevel, out int quoteMacroLevel) +size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref MarkdownList[] nestedLists, ref int quoteLevel, out int quoteMacroLevel) { quoteMacroLevel = 0; const i0 = i; @@ -2487,7 +2468,7 @@ private size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref Markdow * downToLevel = the length within `inlineDelimiters`` to reduce emphasis to * Returns: the number of characters added to the buffer by the replacements */ -private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, int downToLevel = 0) +size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, int downToLevel = 0) { size_t replaceEmphasisPair(ref MarkdownDelimiter start, ref MarkdownDelimiter end) { @@ -2566,7 +2547,7 @@ private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref /**************************************************** */ -private bool isIdentifier(Dsymbols* a, const(char)[] s) @safe +bool isIdentifier(Dsymbols* a, const(char)[] s) @safe { foreach (member; *a) { @@ -2608,7 +2589,7 @@ private bool isIdentifier(Dsymbols* a, const(char)[] s) @safe /**************************************************** */ -private bool isKeyword(const(char)[] str) @safe +bool isKeyword(const(char)[] str) @safe { immutable string[3] table = ["true", "false", "null"]; foreach (s; table) @@ -2621,7 +2602,7 @@ private bool isKeyword(const(char)[] str) @safe /**************************************************** */ -private TypeFunction isTypeFunction(Dsymbol s) @safe +TypeFunction isTypeFunction(Dsymbol s) @safe { FuncDeclaration f = s.isFuncDeclaration(); /* f.type may be NULL for template members. @@ -2637,7 +2618,7 @@ private TypeFunction isTypeFunction(Dsymbol s) @safe /**************************************************** */ -private Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe +Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe { TypeFunction tf = isTypeFunction(s); if (tf && tf.parameterList.parameters) @@ -2655,7 +2636,7 @@ private Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe /**************************************************** */ -private Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe +Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe { foreach (Dsymbol sym; *a) { @@ -2670,7 +2651,7 @@ private Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe /**************************************************** */ -private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe +Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe { foreach (Dsymbol dsym; *a) { @@ -2718,7 +2699,7 @@ private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @sa /**************************************************** */ -private TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_t len) +TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_t len) { for (size_t i = 0; i < a.length; i++) { @@ -2744,7 +2725,7 @@ private TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_ * Return true if str is a reserved symbol name * that starts with a double underscore. */ -private bool isReservedName(const(char)[] str) @safe +bool isReservedName(const(char)[] str) @safe { immutable string[] table = [ @@ -2791,7 +2772,7 @@ private bool isReservedName(const(char)[] str) @safe /**************************************************** * A delimiter for Markdown inline content like emphasis and links. */ -private struct MarkdownDelimiter +struct MarkdownDelimiter { size_t iStart; /// the index where this delimiter starts int count; /// the length of this delimeter's start sequence @@ -2811,7 +2792,7 @@ private struct MarkdownDelimiter /**************************************************** * Info about a Markdown list. */ -private struct MarkdownList +struct MarkdownList { string orderedStart; /// an optional start number--if present then the list starts at this number size_t iStart; /// the index where the list item starts @@ -3028,7 +3009,7 @@ private struct MarkdownList /**************************************************** * A Markdown link. */ -private struct MarkdownLink +struct MarkdownLink { string href; /// the link destination string title; /// an optional title for the link @@ -3607,7 +3588,7 @@ private struct MarkdownLink /************************************************** * A set of Markdown link references. */ -private struct MarkdownLinkReferences +struct MarkdownLinkReferences { MarkdownLink[string] references; // link references keyed by normalized label MarkdownLink[string] symbols; // link symbols keyed by name @@ -3872,7 +3853,7 @@ private struct MarkdownLinkReferences } } -private enum TableColumnAlignment +enum TableColumnAlignment { none, left, @@ -3893,7 +3874,7 @@ private enum TableColumnAlignment * columnAlignments = alignments to populate for each column * Returns: the index of the end of the parsed delimiter, or `0` if not found */ -private size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bool inQuote, ref TableColumnAlignment[] columnAlignments) @safe +size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bool inQuote, ref TableColumnAlignment[] columnAlignments) @safe { size_t i = skipChars(buf, iStart, inQuote ? ">| \t" : "| \t"); while (i < buf.length && buf[i] != '\r' && buf[i] != '\n') @@ -3945,7 +3926,7 @@ private size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bo * columnAlignments = the parsed alignments for each column * Returns: the number of characters added by starting the table, or `0` if unchanged */ -private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, bool inQuote, ref MarkdownDelimiter[] inlineDelimiters, out TableColumnAlignment[] columnAlignments) +size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, bool inQuote, ref MarkdownDelimiter[] inlineDelimiters, out TableColumnAlignment[] columnAlignments) { const iDelimiterRowEnd = parseTableDelimiterRow(buf, iEnd + 1, inQuote, columnAlignments); if (iDelimiterRowEnd) @@ -3981,7 +3962,7 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r * delta = the number of characters added by replacing the row, or `0` if unchanged * Returns: `true` if a table row was found and replaced */ -private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta) +bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta) { delta = 0; @@ -4108,7 +4089,7 @@ private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, cons * columnAlignments = alignments for each column; upon return is set to length `0` * Returns: the number of characters added by ending the table, or `0` if unchanged */ -private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[] columnAlignments) +size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[] columnAlignments) { if (!columnAlignments.length) return 0; @@ -4130,7 +4111,7 @@ private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[] * columnAlignments = alignments for each column; upon return is set to length `0` * Returns: the number of characters added by replacing the row, or `0` if unchanged */ -private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments) +size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments) { size_t delta; replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false, delta); @@ -4148,7 +4129,7 @@ private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, con * buf = an OutBuffer containing the DDoc * offset = the index within buf to start highlighting */ -private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset) +void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset) { const incrementLoc = loc.linnum == 0 ? 1 : 0; loc.linnum = loc.linnum + incrementLoc; @@ -4417,7 +4398,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s codebuf.write(buf[iCodeStart + count .. i]); // escape the contents, but do not perform highlighting except for DDOC_PSYMBOL highlightCode(sc, a, codebuf, 0); - escapeStrayParenthesis(loc, &codebuf, 0, false, sc.eSink); + escapeStrayParenthesis(loc, codebuf, 0, false, sc.eSink); buf.remove(iCodeStart, i - iCodeStart + count); // also trimming off the current ` immutable pre = "$(DDOC_BACKQUOTED "; i = buf.insert(iCodeStart, pre); @@ -4626,7 +4607,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s highlightCode2(sc, a, codebuf, 0); else codebuf.remove(codebuf.length-1, 1); // remove the trailing 0 byte - escapeStrayParenthesis(loc, &codebuf, 0, false, sc.eSink); + escapeStrayParenthesis(loc, codebuf, 0, false, sc.eSink); buf.remove(iCodeStart, i - iCodeStart); i = buf.insert(iCodeStart, codebuf[]); i = buf.insert(i, ")\n"); @@ -5002,7 +4983,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s /************************************************** * Highlight code for DDOC section. */ -private void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset) +void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset) { auto imp = s.isImport(); if (imp && imp.aliases.length > 0) @@ -5037,7 +5018,7 @@ private void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offse /**************************************************** */ -private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset) +void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset) { //printf("highlightCode(a = '%s')\n", a.toChars()); bool resolvedTemplateParameters = false; @@ -5119,7 +5100,7 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off size_t lastOffset = parametersBuf.length; - .toCBuffer(tp, ¶metersBuf, &hgs); + toCBuffer(tp, parametersBuf, hgs); paramLens[parami] = parametersBuf.length - lastOffset; } @@ -5163,7 +5144,7 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off /**************************************** */ -private void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const(char)* pend) +void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const(char)* pend) { for (; p < pend; p++) { @@ -5178,7 +5159,7 @@ private void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const( /************************************************** * Highlight code for CODE section. */ -private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset) +void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset) { scope eSinkNull = new ErrorSinkNull(); @@ -5236,7 +5217,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of * https://issues.dlang.org/show_bug.cgi?id=7715 * https://issues.dlang.org/show_bug.cgi?id=10519 */ - escapeDdocString(&res, o); + escapeDdocString(res, o); res.writeByte(')'); } else @@ -5252,7 +5233,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of /**************************************** * Determine if p points to the start of a "..." parameter identifier. */ -private bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe +bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe { return p.length >= 3 && p[0 .. 3] == "..."; } @@ -5260,6 +5241,7 @@ private bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe /**************************************** * Determine if p points to the start of an identifier. */ +@trusted bool isIdStart(const(char)* p) @nogc nothrow pure { dchar c = *p; @@ -5279,6 +5261,7 @@ bool isIdStart(const(char)* p) @nogc nothrow pure /**************************************** * Determine if p points to the rest of an identifier. */ +@trusted bool isIdTail(const(char)* p) @nogc nothrow pure { dchar c = *p; @@ -5298,7 +5281,7 @@ bool isIdTail(const(char)* p) @nogc nothrow pure /**************************************** * Determine if p points to the indentation space. */ -private bool isIndentWS(const(char)* p) @nogc nothrow pure @safe +bool isIndentWS(const(char)* p) @nogc nothrow pure @safe { return (*p == ' ') || (*p == '\t'); } @@ -5316,7 +5299,7 @@ int utfStride(const(char)* p) @nogc nothrow pure return cast(int)i; } -private inout(char)* stripLeadingNewlines(inout(char)* s) @nogc nothrow pure +inout(char)* stripLeadingNewlines(inout(char)* s) @nogc nothrow pure { while (s && *s == '\n' || *s == '\r') s++; diff --git a/gcc/d/dmd/doc.h b/gcc/d/dmd/doc.h index 669e308dcf6..562427f1a4d 100644 --- a/gcc/d/dmd/doc.h +++ b/gcc/d/dmd/doc.h @@ -13,4 +13,5 @@ class Module; class ErrorSink; -void gendocfile(Module *m, ErrorSink *eSink); +void gendocfile(Module *m, const char *ddoctext_ptr, size_t ddoctext_length, + const char *datetime, ErrorSink *eSink, OutBuffer &outbuf); diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index c2c0628f5ed..981e093934c 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -169,6 +169,7 @@ extern (C++) struct Scope sc.scopesym = new ScopeDsymbol(); sc.scopesym.symtab = new DsymbolTable(); sc.eSink = eSink; + assert(eSink); // Add top level package as member of this global scope Dsymbol m = _module; while (m.parent) diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index 49b98411ad3..a131a8a721c 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -105,6 +105,7 @@ extern (C++) void semanticTypeInfo(Scope* sc, Type t) if (!sc) // inline may request TypeInfo. { Scope scx; + scx.eSink = global.errorSink; scx._module = sd.getModule(); getTypeInfoType(sd.loc, t, &scx); sd.requestTypeInfo = true; diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 0fa4dbcfa5c..c9a2c92194b 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -1801,6 +1801,7 @@ public: if (!tfgetmembers) { Scope sc; + sc.eSink = global.errorSink; auto parameters = new Parameters(); Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); parameters.push(p); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 378d3e6dd64..ebdd3a8566d 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -83,7 +83,7 @@ else version = MARS; enum LOG = false; -private uint setMangleOverride(Dsymbol s, const(char)[] sym) +package uint setMangleOverride(Dsymbol s, const(char)[] sym) { if (s.isFuncDeclaration() || s.isVarDeclaration()) { @@ -766,7 +766,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else { OutBuffer buf; - stcToBuffer(&buf, stc); + stcToBuffer(buf, stc); dsym.error("cannot be `%s`", buf.peekChars()); } dsym.storage_class &= ~stc; // strip off @@ -783,7 +783,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (stc) { OutBuffer buf; - stcToBuffer(&buf, stc); + stcToBuffer(buf, stc); dsym.error("cannot be `scope` and `%s`", buf.peekChars()); } else if (dsym.isMember()) @@ -1121,11 +1121,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (ne.member && !(ne.member.storage_class & STC.scope_)) { import dmd.escape : setUnsafeDIP1000; - const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); + const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe(). if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym)) errorSupplemental(ne.member.loc, "is the location of the constructor"); - else if (global.params.obsolete && inSafeFunc) - warningSupplemental(ne.member.loc, "is the location of the constructor"); } ne.onstack = 1; dsym.onstack = true; @@ -1512,11 +1510,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor ob.writestring(") : "); // use visibility instead of sc.visibility because it couldn't be // resolved yet, see the comment above - visibilityToBuffer(ob, imp.visibility); + visibilityToBuffer(*ob, imp.visibility); ob.writeByte(' '); if (imp.isstatic) { - stcToBuffer(ob, STC.static_); + stcToBuffer(*ob, STC.static_); ob.writeByte(' '); } ob.writestring(": "); @@ -2528,9 +2526,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!em.ed.isAnonymous()) em.ed.memtype = t; } + const errors = global.startGagging(); Expression e = new IntegerExp(em.loc, 0, t); e = e.ctfeInterpret(); - + if (global.endGagging(errors)) + { + error(em.loc, "cannot generate 0 value of type `%s` for `%s`", + t.toChars(), em.toChars()); + } // save origValue for better json output em.origValue = e; @@ -2564,7 +2567,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (emprev.errors) return errorReturn(); + auto errors = global.startGagging(); Expression eprev = emprev.value; + assert(eprev); // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645 Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable()) ? em.ed.memtype @@ -2578,12 +2583,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor emax = emax.expressionSemantic(sc); emax = emax.ctfeInterpret(); - // Set value to (eprev + 1). - // But first check that (eprev != emax) - assert(eprev); + // check that (eprev != emax) Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax); e = e.expressionSemantic(sc); e = e.ctfeInterpret(); + if (global.endGagging(errors)) + { + // display an introductory error before showing what actually failed + error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars()); + // rerun to show errors + Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max); + e2 = e2.expressionSemantic(sc); + e2 = e2.ctfeInterpret(); + e2 = new EqualExp(EXP.equal, em.loc, eprev, e2); + e2 = e2.expressionSemantic(sc); + e2 = e2.ctfeInterpret(); + } + // now any errors are for generating a value if (e.toInteger()) { auto mt = em.ed.memtype; @@ -2593,13 +2609,21 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor emprev.ed.toChars(), emprev.toChars(), mt.toChars()); return errorReturn(); } - + errors = global.startGagging(); // Now set e to (eprev + 1) e = new AddExp(em.loc, eprev, IntegerExp.literal!1); e = e.expressionSemantic(sc); e = e.castTo(sc, eprev.type); e = e.ctfeInterpret(); - + if (global.endGagging(errors)) + { + error(em.loc, "cannot generate value for `%s`", em.toPrettyChars()); + // rerun to show errors + Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1); + e2 = e2.expressionSemantic(sc); + e2 = e2.castTo(sc, eprev.type); + e2 = e2.ctfeInterpret(); + } // save origValue (without cast) for better json output if (e.op != EXP.error) // avoid duplicate diagnostics { @@ -3351,7 +3375,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested())) { OutBuffer buf; - MODtoBuffer(&buf, tf.mod); + MODtoBuffer(buf, tf.mod); funcdecl.error("without `this` cannot be `%s`", buf.peekChars()); tf.mod = 0; // remove qualifiers } @@ -3889,7 +3913,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor OutBuffer buf; auto fd = s.isFuncDeclaration(); - functionToBufferFull(cast(TypeFunction)(funcdecl.type), &buf, + functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf, new Identifier(funcdecl.toPrettyChars()), &hgs, null); const(char)* funcdeclToChars = buf.peekChars(); @@ -3912,7 +3936,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } else { - functionToBufferFull(cast(TypeFunction)(fd.type), &buf1, + functionToBufferFull(cast(TypeFunction)(fd.type), buf1, new Identifier(fd.toPrettyChars()), &hgs, null); error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index e492c7e7aef..67ca2ef66a4 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -750,7 +750,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol { if (i) buf.writestring(", "); - .toCBuffer(tp, &buf, &hgs); + toCBuffer(tp, buf, hgs); } buf.writeByte(')'); @@ -768,7 +768,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol constraint) { buf.writestring(" if ("); - .toCBuffer(constraint, &buf, &hgs); + toCBuffer(constraint, buf, hgs); buf.writeByte(')'); } @@ -865,7 +865,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol if (!fparam.ident) continue; // don't add it, if it has no name - auto v = new VarDeclaration(loc, fparam.type, fparam.ident, null); + auto v = new VarDeclaration(fparam.loc, fparam.type, fparam.ident, null); fparam.storageClass |= STC.parameter; v.storage_class = fparam.storageClass; v.dsymbolSemantic(scx); @@ -6024,14 +6024,14 @@ extern (C++) class TemplateInstance : ScopeDsymbol override const(char)* toChars() const { OutBuffer buf; - toCBufferInstance(this, &buf); + toCBufferInstance(this, buf); return buf.extractChars(); } override final const(char)* toPrettyCharsHelper() { OutBuffer buf; - toCBufferInstance(this, &buf, true); + toCBufferInstance(this, buf, true); return buf.extractChars(); } @@ -6058,11 +6058,9 @@ extern (C++) class TemplateInstance : ScopeDsymbol { case Classification.error: return &errorSupplemental; - case Classification.warning: - return &warningSupplemental; case Classification.deprecation: return &deprecationSupplemental; - case Classification.gagged, Classification.tip: + case Classification.gagged, Classification.tip, Classification.warning: assert(0); } }(); @@ -7056,10 +7054,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol if (td_ambig) { - .error(loc, "%s `%s.%s` matches more than one template declaration:\n%s: `%s`\nand\n%s: `%s`", - td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars(), - td_best.loc.toChars(), td_best.toChars(), - td_ambig.loc.toChars(), td_ambig.toChars()); + .error(loc, "%s `%s.%s` matches more than one template declaration:", + td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars()); + .errorSupplemental(td_best.loc, "`%s`\nand:", td_best.toChars()); + .errorSupplemental(td_ambig.loc, "`%s`", td_ambig.toChars()); return false; } if (td_best) @@ -7825,7 +7823,7 @@ extern (C++) final class TemplateMixin : TemplateInstance override const(char)* toChars() const { OutBuffer buf; - toCBufferInstance(this, &buf); + toCBufferInstance(this, buf); return buf.extractChars(); } diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d index 6a7442ad702..d5f658a8a42 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -199,7 +199,8 @@ struct _d_dynamicArray final else { const(char)[] name = FileName.combine(global.params.cxxhdr.dir, global.params.cxxhdr.name); - writeFile(Loc.initial, name, buf[]); + if (!writeFile(Loc.initial, name, buf[])) + return fatal(); } } @@ -2327,7 +2328,12 @@ public: { //printf("%s %d\n", p.defaultArg.toChars, p.defaultArg.op); buf.writestring(" = "); + // Always emit the FDN of a symbol for the default argument, + // to avoid generating an ambiguous assignment. + auto save = adparent; + adparent = null; printExpressionFor(p.type, p.defaultArg); + adparent = save; } } @@ -2636,7 +2642,7 @@ public: import dmd.hdrgen; // Hex floating point literals were introduced in C++ 17 const allowHex = global.params.cplusplus >= CppStdRevision.cpp17; - floatToBuffer(e.type, e.value, buf, allowHex); + floatToBuffer(e.type, e.value, *buf, allowHex); } } diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h index c6b5975113a..759ad277fda 100644 --- a/gcc/d/dmd/errors.h +++ b/gcc/d/dmd/errors.h @@ -14,6 +14,7 @@ struct Loc; +// Constants used to discriminate kinds of error messages. enum class ErrorKind { warning = 0, @@ -43,7 +44,7 @@ D_ATTRIBUTE_FORMAT(1, 2) void message(const char *format, ...); D_ATTRIBUTE_FORMAT(2, 3) void message(const Loc& loc, const char *format, ...); D_ATTRIBUTE_FORMAT(1, 2) void tip(const char *format, ...); -D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL); +D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, ErrorKind kind, const char *p1 = NULL, const char *p2 = NULL); D_ATTRIBUTE_FORMAT(2, 0) void verrorReportSupplemental(const Loc& loc, const char* format, va_list ap, ErrorKind kind); #if defined(__GNUC__) || defined(__clang__) diff --git a/gcc/d/dmd/errorsink.d b/gcc/d/dmd/errorsink.d index e14829ecfdb..ce2351738d6 100644 --- a/gcc/d/dmd/errorsink.d +++ b/gcc/d/dmd/errorsink.d @@ -62,6 +62,7 @@ class ErrorSinkNull : ErrorSink /***************************************** * Simplest implementation, just sends messages to stderr. + * See also: ErrorSinkCompiler. */ class ErrorSinkStderr : ErrorSink { diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index f817a4ee42f..8562e2eabd6 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -37,6 +37,8 @@ import dmd.tokens; import dmd.visitor; import dmd.arraytypes; +private: + /// Groups global state for escape checking together package(dmd) struct EscapeState { @@ -69,6 +71,7 @@ package(dmd) struct EscapeState * Returns: * `true` if error */ +public bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, Expression ethis, Expressions* arguments, bool gag) { @@ -179,7 +182,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, const(char)* msg = eb.isMutable && eb2.isMutable ? "more than one mutable reference %s `%s` in arguments to `%s()`" : "mutable and const references %s `%s` in arguments to `%s()`"; - error((*arguments)[i].loc, msg, + sc.eSink.error((*arguments)[i].loc, msg, referenceVerb, v.toChars(), fd ? fd.toPrettyChars() : "indirectly"); @@ -226,6 +229,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, * Returns: * `true` if any elements escaped */ +public bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag) { bool errors; @@ -249,6 +253,7 @@ bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag) * Returns: * `true` if any elements escaped */ +public bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag) { bool errors; @@ -274,6 +279,7 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag) * v = parameter that was not inferred * recursionLimit = recursion limit for printing the reason */ +private void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit) { recursionLimit--; @@ -316,12 +322,13 @@ void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit) * Returns: * `true` if pointers to the stack can escape via assignment */ +public bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag) { enum log = false; - if (log) printf("checkParamArgumentEscape(arg: %s par: %s)\n", + if (log) printf("checkParamArgumentEscape(arg: %s par: %s parSTC: %llx)\n", arg ? arg.toChars() : "null", - parId ? parId.toChars() : "null"); + parId ? parId.toChars() : "null", parStc); //printf("type = %s, %d\n", arg.type.toChars(), arg.type.hasPointers()); if (!arg.type.hasPointers()) @@ -334,7 +341,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, if (parStc & STC.scope_) { // These errors only apply to non-scope parameters - // When the paraneter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed + // When the parameter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed er.byfunc.setDim(0); er.byvalue.setDim(0); er.byexp.setDim(0); @@ -467,6 +474,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, * Returns: * `true` if assignment to `firstArg` would cause an error */ +public bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Parameter param, bool gag) { enum log = false; @@ -502,6 +510,7 @@ bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Pa * Returns: * `true` if construction would cause an escaping reference error */ +public bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag) { enum log = false; @@ -543,6 +552,7 @@ bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag) } /// How a `return` parameter escapes its pointer value +public enum ReturnParamDest { returnVal, /// through return statement: `return x` @@ -564,6 +574,7 @@ enum ReturnParamDest * tthis = type of `this` parameter, or `null` if none * Returns: What a `return` parameter should transfer the lifetime of the argument to */ +public ReturnParamDest returnParamDest(TypeFunction tf, Type tthis) { assert(tf); @@ -596,6 +607,7 @@ ReturnParamDest returnParamDest(TypeFunction tf, Type tthis) * Returns: * `true` if pointers to the stack can escape via assignment */ +public bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) { enum log = false; @@ -912,7 +924,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) !(va && va.storage_class & STC.temp)) { if (!gag) - deprecation(ee.loc, "slice of static array temporary returned by `%s` assigned to longer lived variable `%s`", + sc.eSink.deprecation(ee.loc, "slice of static array temporary returned by `%s` assigned to longer lived variable `%s`", ee.toChars(), e1.toChars()); //result = true; continue; @@ -959,6 +971,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) * Returns: * `true` if pointers to the stack can escape */ +public bool checkThrowEscape(Scope* sc, Expression e, bool gag) { //printf("[%s] checkThrowEscape, e = %s\n", e.loc.toChars(), e.toChars()); @@ -1002,6 +1015,7 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag) * Returns: * `true` if pointers to the stack can escape */ +public bool checkNewEscape(Scope* sc, Expression e, bool gag) { import dmd.globals: FeatureState; @@ -1124,7 +1138,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) { if (log) printf("byexp %s\n", ee.toChars()); if (!gag) - error(ee.loc, "storing reference to stack allocated value returned by `%s` into allocated memory causes it to escape", + sc.eSink.error(ee.loc, "storing reference to stack allocated value returned by `%s` into allocated memory causes it to escape", ee.toChars()); result = true; } @@ -1144,6 +1158,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) * Returns: * `true` if pointers to the stack can escape */ +public bool checkReturnEscape(Scope* sc, Expression e, bool gag) { //printf("[%s] checkReturnEscape, e: %s\n", e.loc.toChars(), e.toChars()); @@ -1161,6 +1176,7 @@ bool checkReturnEscape(Scope* sc, Expression e, bool gag) * Returns: * `true` if references to the stack can escape */ +public bool checkReturnEscapeRef(Scope* sc, Expression e, bool gag) { version (none) @@ -1266,7 +1282,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) else if (v.isTypesafeVariadicArray && p == sc.func) { if (!gag) - error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars()); + sc.eSink.error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars()); result = false; } else @@ -1420,7 +1436,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) else { if (!gag) - error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars()); + sc.eSink.error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars()); result = true; } } @@ -1434,6 +1450,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) * va = variable to infer scope for * Returns: `true` if succesful or already `scope` */ +private bool inferScope(VarDeclaration va) { if (!va) @@ -1526,6 +1543,7 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`. * retRefTransition = if `e` is returned through a `return ref scope` function call */ +public void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false) { //printf("[%s] escapeByValue, e: %s\n", e.loc.toChars(), e.toChars()); @@ -1924,6 +1942,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`. * retRefTransition = if `e` is returned through a `return ref scope` function call */ +private void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false) { //printf("[%s] escapeByRef, e: %s, retRefTransition: %d\n", e.loc.toChars(), e.toChars(), retRefTransition); @@ -2158,6 +2177,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR /************************************ * Aggregate the data collected by the escapeBy??() functions. */ +public struct EscapeByResults { VarDeclarations byref; // array into which variables being returned by ref are inserted @@ -2295,6 +2315,7 @@ private void doNotInferScope(VarDeclaration v, RootObject o) * f = final function type. `funcdecl.type` started as the 'premature type' before attribute * inference, then its inferred attributes are copied over to final type `f` */ +public void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) { @@ -2427,6 +2448,7 @@ private void eliminateMaybeScopes(VarDeclaration[] array) * Returns: * true if it's a pointer (or reference) to mutable data */ +private bool isReferenceToMutable(Type t) { t = t.baseElemOf(); @@ -2486,6 +2508,7 @@ bool isReferenceToMutable(Type t) * Returns: * true if it's a pointer (or reference) to mutable data */ +private bool isReferenceToMutable(Parameter p, Type t) { if (p.isReference()) @@ -2561,6 +2584,7 @@ private void addMaybe(VarDeclaration va, VarDeclaration v) } // `setUnsafePreview` partially evaluated for dip1000 +public bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 07cc8d4b7e8..99f65879046 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -40,6 +40,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.escape; import dmd.expressionsem; import dmd.func; @@ -813,7 +814,7 @@ extern (C++) abstract class Expression : ASTNode { OutBuffer buf; HdrGenState hgs; - toCBuffer(this, &buf, &hgs); + toCBuffer(this, buf, hgs); return buf.extractChars(); } @@ -1186,7 +1187,7 @@ extern (C++) abstract class Expression : ASTNode return checkValue(); } - extern (D) final bool checkArithmetic() + extern (D) final bool checkArithmetic(EXP op) { if (op == EXP.error) return true; @@ -1194,7 +1195,11 @@ extern (C++) abstract class Expression : ASTNode return true; if (!type.isintegral() && !type.isfloating()) { - error("`%s` is not of arithmetic type, it is a `%s`", toChars(), type.toChars()); + // unary aggregate ops error here + const char* msg = type.isAggregate() ? + "operator `%s` is not defined for `%s` of type `%s`" : + "illegal operator `%s` for `%s` of type `%s`"; + error(msg, EXPtoString(op).ptr, toChars(), type.toChars()); return true; } return checkValue(); @@ -3250,6 +3255,8 @@ extern (C++) final class AssocArrayLiteralExp : Expression Expressions* keys; Expressions* values; + /// Lower to core.internal.newaa for static initializaton + Expression lowering; extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values) @safe { @@ -4036,13 +4043,11 @@ extern (C++) final class FuncExp : Expression return new FuncExp(loc, fd); } - extern (D) MATCH matchType(Type to, Scope* sc, FuncExp* presult, int flag = 0) + extern (D) MATCH matchType(Type to, Scope* sc, FuncExp* presult, ErrorSink eSink) { - - static MATCH cannotInfer(Expression e, Type to, int flag) + MATCH cannotInfer() { - if (!flag) - e.error("cannot infer parameter types from `%s`", to.toChars()); + eSink.error(loc, "cannot infer parameter types from `%s`", to.toChars()); return MATCH.nomatch; } @@ -4055,8 +4060,7 @@ extern (C++) final class FuncExp : Expression { if (tok == TOK.function_) { - if (!flag) - error("cannot match function literal to delegate type `%s`", to.toChars()); + eSink.error(loc, "cannot match function literal to delegate type `%s`", to.toChars()); return MATCH.nomatch; } tof = cast(TypeFunction)to.nextOf(); @@ -4065,8 +4069,7 @@ extern (C++) final class FuncExp : Expression { if (tok == TOK.delegate_) { - if (!flag) - error("cannot match delegate literal to function pointer type `%s`", to.toChars()); + eSink.error(loc, "cannot match delegate literal to function pointer type `%s`", to.toChars()); return MATCH.nomatch; } } @@ -4075,7 +4078,7 @@ extern (C++) final class FuncExp : Expression { if (!tof) { - return cannotInfer(this, to, flag); + return cannotInfer(); } // Parameter types inference from 'tof' @@ -4086,7 +4089,7 @@ extern (C++) final class FuncExp : Expression const dim = tf.parameterList.length; if (tof.parameterList.length != dim || tof.parameterList.varargs != tf.parameterList.varargs) - return cannotInfer(this, to, flag); + return cannotInfer(); auto tiargs = new Objects(); tiargs.reserve(td.parameters.length); @@ -4106,7 +4109,7 @@ extern (C++) final class FuncExp : Expression Parameter pto = tof.parameterList[u]; Type t = pto.type; if (t.ty == Terror) - return cannotInfer(this, to, flag); + return cannotInfer(); tf.parameterList[u].storageClass = tof.parameterList[u].storageClass; tiargs.push(t); } @@ -4124,9 +4127,9 @@ extern (C++) final class FuncExp : Expression if (ex.op == EXP.error) return MATCH.nomatch; if (auto ef = ex.isFuncExp()) - return ef.matchType(to, sc, presult, flag); + return ef.matchType(to, sc, presult, eSink); else - return cannotInfer(this, to, flag); + return cannotInfer(); } if (!tof || !tof.next) @@ -4198,10 +4201,10 @@ extern (C++) final class FuncExp : Expression (*presult).fd.modifyReturns(sc, tof.next); } } - else if (!flag) + else if (!cast(ErrorSinkNull)eSink) { auto ts = toAutoQualChars(tx, to); - error("cannot implicitly convert expression `%s` of type `%s` to `%s`", + eSink.error(loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", toChars(), ts[0], ts[1]); } return m; @@ -4674,8 +4677,8 @@ extern (C++) abstract class BinExp : Expression extern (D) final bool checkArithmeticBin() { - bool r1 = e1.checkArithmetic(); - bool r2 = e2.checkArithmetic(); + bool r1 = e1.checkArithmetic(this.op); + bool r2 = e2.checkArithmetic(this.op); return (r1 || r2); } @@ -7217,7 +7220,7 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp { const funcStr = fd.Dsymbol.toPrettyChars(); OutBuffer buf; - functionToBufferWithIdent(fd.type.isTypeFunction(), &buf, funcStr, fd.isStatic); + functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic); s = buf.extractChars(); } else diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 1f04c6cb1db..2189757e61f 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -94,7 +94,7 @@ public: const char *toChars() const override; void error(const char *format, ...) const; - void warning(const char *format, ...) const; + void warning(unsigned flag, const char *format, ...) const; void deprecation(const char *format, ...) const; virtual dinteger_t toInteger(); @@ -446,6 +446,7 @@ public: OwnedBy ownedByCtfe; Expressions *keys; Expressions *values; + Expression* lowering; bool equals(const RootObject * const o) const override; AssocArrayLiteralExp *syntaxCopy() override; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 69999cbf32a..30382bbc6bb 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -1197,6 +1197,11 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) if (thisAd == requiredAd) return true; + // if outerfunc is the member of a nested aggregate, then let + // getRightThis take care of this. + if (thisAd.isNested()) + return true; + // outerfunc is the member of a base class that contains calledFunc, // then we consider that they have the same this. auto cd = requiredAd.isClassDeclaration(); @@ -1206,11 +1211,6 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) if (cd.isBaseOf2(thisAd.isClassDeclaration())) return true; - // if outerfunc is the member of a nested aggregate, then let - // getRightThis take care of this. - if (thisAd.isNested()) - return true; - return false; } @@ -2319,6 +2319,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } err |= arg.checkValue(); err |= arg.checkSharedAccess(sc); + err |= checkParamArgumentEscape(sc, fd, Id.dotdotdot, null, cast(STC) tf.parameterList.stc, arg, false, false); arg = arg.optimize(WANTvalue); } (*arguments)[i] = arg; @@ -2331,14 +2332,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc, { if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) { - checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); + checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list, sc.eSink); } } else if (fd && fd.scanf) { if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) { - checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); + checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list, sc.eSink); } } else @@ -2528,7 +2529,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, auto args = new Parameters(arguments.length - nparams); for (size_t i = 0; i < arguments.length - nparams; i++) { - auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null); + Expression earg = (*arguments)[nparams + i]; + auto arg = new Parameter(earg.loc, STC.in_, earg.type, null, null, null); (*args)[i] = arg; } auto tup = new TypeTuple(args); @@ -3889,10 +3891,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor foreach (v; c.fields) { if (v.inuse || v._scope is null || v._init is null || - v._init.isVoidInitializer()) + v._init.isVoidInitializer() || v.semanticRun >= PASS.semantic2done) continue; v.inuse++; v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret); + import dmd.semantic2 : lowerStaticAAs; + lowerStaticAAs(v, sc); v.inuse--; } } @@ -4312,7 +4316,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.fd.treq) // defer type determination { FuncExp fe; - if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch) + if (exp.matchType(exp.fd.treq, sc, &fe, sc.eSink) > MATCH.nomatch) e = fe; else e = ErrorExp.get(); @@ -5275,10 +5279,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { OutBuffer buf; buf.writeByte('('); - argExpTypesToCBuffer(&buf, exp.arguments); + argExpTypesToCBuffer(buf, exp.arguments); buf.writeByte(')'); if (tthis) - tthis.modToBuffer(&buf); + tthis.modToBuffer(buf); //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", @@ -5348,7 +5352,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { OutBuffer buf; buf.writeByte('('); - argExpTypesToCBuffer(&buf, exp.arguments); + argExpTypesToCBuffer(buf, exp.arguments); buf.writeByte(')'); //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); @@ -5947,7 +5951,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor for (size_t i = 0; i < cd.baseclasses.length; i++) { BaseClass* b = (*cd.baseclasses)[i]; - args.push(new Parameter(STC.in_, b.type, null, null, null)); + args.push(new Parameter(Loc.initial, STC.in_, b.type, null, null, null)); } tded = new TypeTuple(args); } @@ -5993,7 +5997,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error) return setError(); - args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl)); + args.push(new Parameter(arg.loc, arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl)); } tded = new TypeTuple(args); break; @@ -7278,7 +7282,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else if (!exp.e1.type.deco) { // try to resolve the type - exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null); + exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, sc); if (!exp.e1.type.deco) // still couldn't resolve it { if (auto ve = exp.e1.isVarExp()) @@ -7527,7 +7531,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (exp.e1.checkNoBool()) return setError(); - if (exp.e1.checkArithmetic() || + if (exp.e1.checkArithmetic(exp.op) || exp.e1.checkSharedAccess(sc)) return setError(); @@ -7557,7 +7561,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (exp.e1.checkNoBool()) return setError(); - if (exp.e1.checkArithmetic()) + if (exp.e1.checkArithmetic(exp.op)) return setError(); if (exp.e1.checkSharedAccess(sc)) return setError(); @@ -10024,19 +10028,22 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign && - e2x.op != EXP.slice && e2x.op != EXP.assign && - e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ && - !(e2x.op == EXP.add || e2x.op == EXP.min || - e2x.op == EXP.mul || e2x.op == EXP.div || - e2x.op == EXP.mod || e2x.op == EXP.xor || - e2x.op == EXP.and || e2x.op == EXP.or || - e2x.op == EXP.pow || - e2x.op == EXP.tilde || e2x.op == EXP.negate)) + version (none) { - const(char)* e1str = exp.e1.toChars(); - const(char)* e2str = e2x.toChars(); - exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str); + if (global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign && + e2x.op != EXP.slice && e2x.op != EXP.assign && + e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ && + !(e2x.op == EXP.add || e2x.op == EXP.min || + e2x.op == EXP.mul || e2x.op == EXP.div || + e2x.op == EXP.mod || e2x.op == EXP.xor || + e2x.op == EXP.and || e2x.op == EXP.or || + e2x.op == EXP.pow || + e2x.op == EXP.tilde || e2x.op == EXP.negate)) + { + const(char)* e1str = exp.e1.toChars(); + const(char)* e2str = e2x.toChars(); + exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str); + } } Type t2n = t2.nextOf(); @@ -10085,17 +10092,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign && - t1.ty == Tarray && t2.ty == Tsarray && - e2x.op != EXP.slice && - t2.implicitConvTo(t1)) + version (none) { - // Disallow ar[] = sa (Converted to ar[] = sa[]) - // Disallow da = sa (Converted to da = sa[]) - const(char)* e1str = exp.e1.toChars(); - const(char)* e2str = e2x.toChars(); - const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice"; - exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str); + if (global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign && + t1.ty == Tarray && t2.ty == Tsarray && + e2x.op != EXP.slice && + t2.implicitConvTo(t1)) + { + // Disallow ar[] = sa (Converted to ar[] = sa[]) + // Disallow da = sa (Converted to da = sa[]) + const(char)* e1str = exp.e1.toChars(); + const(char)* e2str = e2x.toChars(); + const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice"; + exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str); + } } if (exp.op == EXP.blit) e2x = e2x.castTo(sc, exp.e1.type); @@ -10785,11 +10795,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor bool err = false; if (tb1.ty == Tdelegate || tb1.isPtrToFunction()) { - err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); + err |= exp.e1.checkArithmetic(exp.op) || exp.e1.checkSharedAccess(sc); } if (tb2.ty == Tdelegate || tb2.isPtrToFunction()) { - err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); + err |= exp.e2.checkArithmetic(exp.op) || exp.e2.checkSharedAccess(sc); } if (err) return setError(); @@ -10891,11 +10901,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor bool err = false; if (t1.ty == Tdelegate || t1.isPtrToFunction()) { - err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); + err |= exp.e1.checkArithmetic(exp.op) || exp.e1.checkSharedAccess(sc); } if (t2.ty == Tdelegate || t2.isPtrToFunction()) { - err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); + err |= exp.e2.checkArithmetic(exp.op) || exp.e2.checkSharedAccess(sc); } if (err) return setError(); @@ -11032,7 +11042,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor (exp.e2.isStringExp() && (exp.e1.isIntegerExp() || exp.e1.isStringExp()))) return exp; - Identifier hook = global.params.tracegc ? Id._d_arraycatnTXTrace : Id._d_arraycatnTX; + bool useTraceGCHook = global.params.tracegc && sc.needsCodegen(); + + Identifier hook = useTraceGCHook ? Id._d_arraycatnTXTrace : Id._d_arraycatnTX; if (!verifyHookExist(exp.loc, *sc, hook, "concatenating arrays")) { setError(); @@ -11061,7 +11073,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } auto arguments = new Expressions(); - if (global.params.tracegc) + if (useTraceGCHook) { auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); @@ -11088,7 +11100,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.useGC || !sc.needsCodegen()) + if (!global.params.useGC) return; if (auto ce = exp.isCatExp()) @@ -12087,8 +12099,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - if (sc.needsCodegen() && - (t1.ty == Tarray || t1.ty == Tsarray) && + if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays")) diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 73f1ba786cb..bf7ad7ee8d5 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -173,7 +173,7 @@ public: Identifier id = Identifier.generateId("__o"); Statement handler = new PeelStatement(sexception); - if (sexception.blockExit(fd, false) & BE.fallthru) + if (sexception.blockExit(fd, null) & BE.fallthru) { auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id)); ts.internalThrow = true; @@ -1311,7 +1311,7 @@ extern (C++) class FuncDeclaration : Declaration final const(char)* toFullSignature() { OutBuffer buf; - functionToBufferWithIdent(type.toTypeFunction(), &buf, toChars(), isStatic); + functionToBufferWithIdent(type.toTypeFunction(), buf, toChars(), isStatic); return buf.extractChars(); } @@ -2279,8 +2279,11 @@ extern (C++) class FuncDeclaration : Declaration break LcheckAncestorsOfANestedRef; } a.push(f); - .errorSupplemental(f.loc, "`%s` closes over variable `%s` at %s", - f.toPrettyChars(), v.toChars(), v.loc.toChars()); + .errorSupplemental(f.loc, "%s `%s` closes over variable `%s`", + f.kind, f.toPrettyChars(), v.toChars()); + if (v.ident != Id.This) + .errorSupplemental(v.loc, "`%s` declared here", v.toChars()); + break LcheckAncestorsOfANestedRef; } } @@ -2657,7 +2660,7 @@ extern (C++) class FuncDeclaration : Declaration auto fparams = new Parameters(); if (canBuildResultVar()) { - Parameter p = new Parameter(STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null); + Parameter p = new Parameter(loc, STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null); fparams.push(p); } auto fo = cast(TypeFunction)(originalType ? originalType : f); @@ -3340,14 +3343,14 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, s = fd = td.funcroot; OutBuffer tiargsBuf; - arrayObjectsToBuffer(&tiargsBuf, tiargs); + arrayObjectsToBuffer(tiargsBuf, tiargs); OutBuffer fargsBuf; fargsBuf.writeByte('('); - argExpTypesToCBuffer(&fargsBuf, fargs); + argExpTypesToCBuffer(fargsBuf, fargs); fargsBuf.writeByte(')'); if (tthis) - tthis.modToBuffer(&fargsBuf); + tthis.modToBuffer(fargsBuf); // The call is ambiguous if (m.lastf && m.nextf) @@ -4623,7 +4626,7 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) { if (!gag) { - if (!sc.isDeprecated() && global.params.obsolete) + version (none) // disable obsolete warning warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); } } diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index af711a0fd0a..840074e5d8f 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -101,6 +101,23 @@ extern(C++) struct Output OutBuffer* buffer; // if this output is buffered, this is the buffer int bufferLines; // number of lines written to the buffer } + +/// Command line state related to printing usage about other switches +extern(C++) struct Help +{ + bool manual; // open browser on compiler manual + bool usage; // print usage and exit + // print help of switch: + bool mcpu; // -mcpu + bool transition; // -transition + bool check; // -check + bool checkAction; // -checkaction + bool revert; // -revert + bool preview; // -preview + bool externStd; // -extern-std + bool hc; // -HC +} + /// Put command line switches in here extern (C++) struct Param { @@ -124,7 +141,6 @@ extern (C++) struct Param bool release; // build release version bool preservePaths; // true means don't strip path from source file DiagnosticReporting warnings = DiagnosticReporting.off; // how compiler warnings are handled - bool obsolete; // enable warnings about use of obsolete messages bool color; // use ANSI colors in console output bool cov; // generate code coverage data ubyte covPercent; // 0..100 code coverage percentage required @@ -143,16 +159,7 @@ extern (C++) struct Param bool showGaggedErrors; // print gagged errors anyway bool printErrorContext; // print errors with the error context (the error line in the source file) - bool manual; // open browser on compiler manual - bool usage; // print usage and exit - bool mcpuUsage; // print help on -mcpu switch - bool transitionUsage; // print help on -transition switch - bool checkUsage; // print help on -check switch - bool checkActionUsage; // print help on -checkaction switch - bool revertUsage; // print help on -revert switch - bool previewUsage; // print help on -preview switch - bool externStdUsage; // print help on -extern-std switch - bool hcUsage; // print help on -HC switch + Help help; bool logo; // print compiler logo // Options for `-preview=/-revert=` @@ -258,6 +265,7 @@ extern (C++) struct Global Array!(const(char)*)* filePath; /// Array of char*'s which form the file import lookup path private enum string _version = import("VERSION"); + char[26] datetime; /// string returned by ctime() CompileEnv compileEnv; Param params; /// command line parameters @@ -281,6 +289,7 @@ extern (C++) struct Global enum recursionLimit = 500; /// number of recursive template expansions before abort ErrorSink errorSink; /// where the error messages go + ErrorSink errorSinkNull; /// where the error messages are ignored extern (C++) FileName function(FileName, ref const Loc, out bool, OutBuffer*) preprocess; @@ -337,6 +346,7 @@ extern (C++) struct Global extern (C++) void _init() { errorSink = new ErrorSinkCompiler; + errorSinkNull = new ErrorSinkNull; this.fileManager = new FileManager(); version (MARS) @@ -369,6 +379,7 @@ extern (C++) struct Global core.stdc.time.time(&ct); const p = ctime(&ct); assert(p); + datetime[] = p[0 .. 26]; __gshared char[11 + 1] date = 0; // put in BSS segment __gshared char[8 + 1] time = 0; diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 0ef9eed405c..e24042a4f21 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -96,6 +96,22 @@ struct Output int bufferLines; // number of lines written to the buffer }; +/// Command line state related to printing uasage about other switches +struct Help +{ + d_bool manual; // open browser on compiler manual + d_bool usage; // print usage and exit + // print help of switch: + d_bool mcpu; // -mcpu + d_bool transition; // -transition + d_bool check; // -check + d_bool checkAction; // -checkaction + d_bool revert; // -revert + d_bool preview; // -preview + d_bool externStd; // -extern-std + d_bool hc; // -HC +}; + // Put command line switches in here struct Param { @@ -119,7 +135,6 @@ struct Param d_bool release; // build release version d_bool preservePaths; // true means don't strip path from source file Diagnostic warnings; - d_bool obsolete; // warn about use of obsolete features d_bool color; // use ANSI colors in console output d_bool cov; // generate code coverage data unsigned char covPercent; // 0..100 code coverage percentage required @@ -136,16 +151,7 @@ struct Param CppStdRevision cplusplus; // version of C++ name mangling to support d_bool showGaggedErrors; // print gagged errors anyway d_bool printErrorContext; // print errors with the error context (the error line in the source file) - d_bool manual; // open browser on compiler manual - d_bool usage; // print usage and exit - d_bool mcpuUsage; // print help on -mcpu switch - d_bool transitionUsage; // print help on -transition switch - d_bool checkUsage; // print help on -check switch - d_bool checkActionUsage; // print help on -checkaction switch - d_bool revertUsage; // print help on -revert switch - d_bool previewUsage; // print help on -preview switch - d_bool externStdUsage; // print help on -extern-std switch - d_bool hcUsage; // print help on -HC switch + Help help; d_bool logo; // print logo; // Options for `-preview=/-revert=` @@ -265,7 +271,6 @@ struct CompileEnv bool previewIn; bool ddocOutput; bool shortenedMethods; - bool obsolete; }; struct Global @@ -277,6 +282,7 @@ struct Global Array<const char *> *path; // Array of char*'s which form the import lookup path Array<const char *> *filePath; // Array of char*'s which form the file import lookup path + char datetime[26]; /// string returned by ctime() CompileEnv compileEnv; Param params; @@ -296,6 +302,7 @@ struct Global FileManager* fileManager; ErrorSink* errorSink; // where the error messages go + ErrorSink* errorSinkNull; // where the error messages disappear FileName (*preprocess)(FileName, const Loc&, bool&, OutBuffer&); @@ -358,8 +365,8 @@ struct Loc { private: unsigned _linnum; - unsigned short _charnum; - unsigned short fileIndex; + unsigned _charnum; + unsigned fileIndex; public: static void set(bool showColumns, MessageStyle messageStyle); diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 33cbc19c690..b4c8e8b899b 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -51,7 +51,6 @@ import dmd.statement; import dmd.staticassert; import dmd.target; import dmd.tokens; -import dmd.utils; import dmd.visitor; struct HdrGenState @@ -73,16 +72,20 @@ struct HdrGenState enum TEST_EMIT_ALL = 0; -extern (C++) void genhdrfile(Module m) +/**************************************** + * Generate a header (.di) file for Module m. + * Params: + * m = Module to generate header for + * buf = buffer to write the data to + */ +extern (C++) void genhdrfile(Module m, ref OutBuffer buf) { - OutBuffer buf; buf.doindent = 1; buf.printf("// D import file generated from '%s'", m.srcfile.toChars()); buf.writenl(); HdrGenState hgs; hgs.hdrgen = true; - toCBuffer(m, &buf, &hgs); - writeFile(m.loc, m.hdrfile.toString(), buf[]); + toCBuffer(m, buf, hgs); } /** @@ -91,14 +94,14 @@ extern (C++) void genhdrfile(Module m) * buf = buffer to write to. * m = module to visit all members of. */ -extern (C++) void moduleToBuffer(OutBuffer* buf, Module m) +extern (C++) void moduleToBuffer(ref OutBuffer buf, Module m) { HdrGenState hgs; hgs.fullDump = true; - toCBuffer(m, buf, &hgs); + toCBuffer(m, buf, hgs); } -void moduleToBuffer2(Module m, OutBuffer* buf, HdrGenState* hgs) +void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs) { if (m.md) { @@ -132,7 +135,7 @@ void moduleToBuffer2(Module m, OutBuffer* buf, HdrGenState* hgs) } } -private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs) +private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs) { void visitDefaultCase(Statement s) { @@ -201,8 +204,7 @@ private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs) auto d = ds.exp.isDeclarationExp().declaration; if (auto v = d.isVarDeclaration()) { - scope ppv = new DsymbolPrettyPrintVisitor(buf, hgs); - ppv.visitVarDecl(v, anywritten); + visitVarDecl(v, anywritten, buf, *hgs); } else d.dsymbolToBuffer(buf, hgs); @@ -792,9 +794,9 @@ private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs) visit.VisitStatement(s); } -private void dsymbolToBuffer(Dsymbol s, OutBuffer* buf, HdrGenState* hgs) +private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, HdrGenState* hgs) { - scope v = new DsymbolPrettyPrintVisitor(buf, hgs); + scope v = new DsymbolPrettyPrintVisitor(&buf, hgs); s.accept(v); } @@ -822,13 +824,13 @@ public: { buf.writestring(s.kind()); buf.writeByte('('); - s.exp.expressionToBuffer(buf, hgs); + s.exp.expressionToBuffer(*buf, hgs); if (s.msgs) { foreach (m; (*s.msgs)[]) { buf.writestring(", "); - m.expressionToBuffer(buf, hgs); + m.expressionToBuffer(*buf, hgs); } } buf.writestring(");"); @@ -860,13 +862,13 @@ public: override void visit(EnumMember em) { if (em.type) - typeToBuffer(em.type, em.ident, buf, hgs); + typeToBuffer(em.type, em.ident, *buf, hgs); else buf.writestring(em.ident.toString()); if (em.value) { buf.writestring(" = "); - em.value.expressionToBuffer(buf, hgs); + em.value.expressionToBuffer(*buf, hgs); } } @@ -916,7 +918,7 @@ public: bool hasSTC; if (auto stcd = d.isStorageClassDeclaration) { - hasSTC = stcToBuffer(buf, stcd.stc); + hasSTC = stcToBuffer(*buf, stcd.stc); } if (!d.decl) @@ -959,7 +961,7 @@ public: override void visit(DeprecatedDeclaration d) { buf.writestring("deprecated("); - d.msg.expressionToBuffer(buf, hgs); + d.msg.expressionToBuffer(*buf, hgs); buf.writestring(") "); visit(cast(AttribDeclaration)d); } @@ -994,7 +996,7 @@ public: override void visit(VisibilityDeclaration d) { - visibilityToBuffer(buf, d.visibility); + visibilityToBuffer(*buf, d.visibility); AttribDeclaration ad = cast(AttribDeclaration)d; if (ad.decl.length <= 1) buf.writeByte(' '); @@ -1047,7 +1049,7 @@ public: if (d.args && d.args.length) { buf.writestring(", "); - argsToBuffer(d.args, buf, hgs); + argsToBuffer(d.args, *buf, hgs); } buf.writeByte(')'); @@ -1065,7 +1067,7 @@ public: override void visit(ConditionalDeclaration d) { - d.condition.conditionToBuffer(buf, hgs); + d.condition.conditionToBuffer(*buf, hgs); if (d.decl || d.elsedecl) { buf.writenl(); @@ -1108,15 +1110,15 @@ public: { if (i) buf.writestring(", "); - if (stcToBuffer(buf, p.storageClass)) + if (stcToBuffer(*buf, p.storageClass)) buf.writeByte(' '); if (p.type) - typeToBuffer(p.type, p.ident, buf, hgs); + typeToBuffer(p.type, p.ident, *buf, hgs); else buf.writestring(p.ident.toString()); } buf.writestring("; "); - s.aggr.expressionToBuffer(buf, hgs); + s.aggr.expressionToBuffer(*buf, hgs); buf.writeByte(')'); buf.writenl(); } @@ -1128,13 +1130,13 @@ public: buf.writestring(Token.toString(s.op)); buf.writestring(" ("); if (s.prm.type) - typeToBuffer(s.prm.type, s.prm.ident, buf, hgs); + typeToBuffer(s.prm.type, s.prm.ident, *buf, hgs); else buf.writestring(s.prm.ident.toString()); buf.writestring("; "); - s.lwr.expressionToBuffer(buf, hgs); + s.lwr.expressionToBuffer(*buf, hgs); buf.writestring(" .. "); - s.upr.expressionToBuffer(buf, hgs); + s.upr.expressionToBuffer(*buf, hgs); buf.writeByte(')'); buf.writenl(); } @@ -1162,7 +1164,7 @@ public: override void visit(MixinDeclaration d) { buf.writestring("mixin("); - argsToBuffer(d.exps, buf, hgs, null); + argsToBuffer(d.exps, *buf, hgs, null); buf.writestring(");"); buf.writenl(); } @@ -1170,7 +1172,7 @@ public: override void visit(UserAttributeDeclaration d) { buf.writestring("@("); - argsToBuffer(d.atts, buf, hgs); + argsToBuffer(d.atts, *buf, hgs); buf.writeByte(')'); visit(cast(AttribDeclaration)d); } @@ -1221,9 +1223,9 @@ public: if (FuncDeclaration fd = onemember.isFuncDeclaration()) { assert(fd.type); - if (stcToBuffer(buf, fd.storage_class)) + if (stcToBuffer(*buf, fd.storage_class)) buf.writeByte(' '); - functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, hgs, d); + functionToBufferFull(cast(TypeFunction)fd.type, *buf, d.ident, hgs, d); visitTemplateConstraint(d.constraint); hgs.tpltMember++; bodyToBuffer(fd); @@ -1262,10 +1264,10 @@ public: { if (d.constraint) return false; - if (stcToBuffer(buf, vd.storage_class)) + if (stcToBuffer(*buf, vd.storage_class)) buf.writeByte(' '); if (vd.type) - typeToBuffer(vd.type, vd.ident, buf, hgs); + typeToBuffer(vd.type, vd.ident, *buf, hgs); else buf.writestring(vd.ident.toString()); buf.writeByte('('); @@ -1276,9 +1278,9 @@ public: buf.writestring(" = "); ExpInitializer ie = vd._init.isExpInitializer(); if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) - (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); + (cast(AssignExp)ie.exp).e2.expressionToBuffer(*buf, hgs); else - vd._init.initializerToBuffer(buf, hgs); + vd._init.initializerToBuffer(*buf, hgs); } buf.writeByte(';'); buf.writenl(); @@ -1295,7 +1297,7 @@ public: { if (i) buf.writestring(", "); - p.templateParameterToBuffer(buf, hgs); + p.templateParameterToBuffer(*buf, hgs); } } @@ -1304,27 +1306,27 @@ public: if (!constraint) return; buf.writestring(" if ("); - constraint.expressionToBuffer(buf, hgs); + constraint.expressionToBuffer(*buf, hgs); buf.writeByte(')'); } override void visit(TemplateInstance ti) { buf.writestring(ti.name.toChars()); - tiargsToBuffer(ti, buf, hgs); + tiargsToBuffer(ti, *buf, hgs); if (hgs.fullDump) { buf.writenl(); - dumpTemplateInstance(ti, buf, hgs); + dumpTemplateInstance(ti, *buf, hgs); } } override void visit(TemplateMixin tm) { buf.writestring("mixin "); - typeToBuffer(tm.tqual, null, buf, hgs); - tiargsToBuffer(tm, buf, hgs); + typeToBuffer(tm.tqual, null, *buf, hgs); + tiargsToBuffer(tm, *buf, hgs); if (tm.ident && memcmp(tm.ident.toChars(), cast(const(char)*)"__mixin", 7) != 0) { buf.writeByte(' '); @@ -1333,7 +1335,7 @@ public: buf.writeByte(';'); buf.writenl(); if (hgs.fullDump) - dumpTemplateInstance(tm, buf, hgs); + dumpTemplateInstance(tm, *buf, hgs); } override void visit(EnumDeclaration d) @@ -1349,7 +1351,7 @@ public: if (d.memtype) { buf.writestring(" : "); - typeToBuffer(d.memtype, null, buf, hgs); + typeToBuffer(d.memtype, null, *buf, hgs); } if (!d.members) { @@ -1452,7 +1454,7 @@ public: { if (i) buf.writestring(", "); - typeToBuffer(b.type, null, buf, hgs); + typeToBuffer(b.type, null, *buf, hgs); } } @@ -1465,7 +1467,7 @@ public: { buf.writestring(d.ident.toString()); buf.writestring(" = "); - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); /* https://issues.dlang.org/show_bug.cgi?id=23223 @@ -1484,18 +1486,18 @@ public: } else if (d.type.ty == Tfunction) { - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); - typeToBuffer(d.type, d.ident, buf, hgs); + typeToBuffer(d.type, d.ident, *buf, hgs); } else if (d.ident) { hgs.declstring = (d.ident == Id.string || d.ident == Id.wstring || d.ident == Id.dstring); buf.writestring(d.ident.toString()); buf.writestring(" = "); - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); - typeToBuffer(d.type, null, buf, hgs); + typeToBuffer(d.type, null, *buf, hgs); hgs.declstring = false; } buf.writeByte(';'); @@ -1509,7 +1511,7 @@ public: if (d.aliassym) d.aliassym.accept(this); else // d.type - typeToBuffer(d.type, null, buf, hgs); + typeToBuffer(d.type, null, *buf, hgs); buf.writeByte(';'); buf.writenl(); } @@ -1518,69 +1520,18 @@ public: { if (d.storage_class & STC.local) return; - visitVarDecl(d, false); + visitVarDecl(d, false, *buf, *hgs); buf.writeByte(';'); buf.writenl(); } - void visitVarDecl(VarDeclaration v, bool anywritten) - { - const bool isextern = hgs.hdrgen && - !hgs.insideFuncBody && - !hgs.tpltMember && - !hgs.insideAggregate && - !(v.storage_class & STC.manifest); - - void vinit(VarDeclaration v) - { - auto ie = v._init.isExpInitializer(); - if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) - (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); - else - v._init.initializerToBuffer(buf, hgs); - } - - if (anywritten) - { - buf.writestring(", "); - buf.writestring(v.ident.toString()); - } - else - { - const bool useTypeof = isextern && v._init && !v.type; - auto stc = v.storage_class; - if (isextern) - stc |= STC.extern_; - if (useTypeof) - stc &= ~STC.auto_; - if (stcToBuffer(buf, stc)) - buf.writeByte(' '); - if (v.type) - typeToBuffer(v.type, v.ident, buf, hgs); - else if (useTypeof) - { - buf.writestring("typeof("); - vinit(v); - buf.writestring(") "); - buf.writestring(v.ident.toString()); - } - else - buf.writestring(v.ident.toString()); - } - if (v._init && !isextern) - { - buf.writestring(" = "); - vinit(v); - } - } - override void visit(FuncDeclaration f) { //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars()); - if (stcToBuffer(buf, f.storage_class)) + if (stcToBuffer(*buf, f.storage_class)) buf.writeByte(' '); auto tf = cast(TypeFunction)f.type; - typeToBuffer(tf, f.ident, buf, hgs); + typeToBuffer(tf, f.ident, *buf, hgs); if (hgs.hdrgen) { @@ -1627,7 +1578,7 @@ public: { assert(es.exp && es.exp.op == EXP.assert_); buf.writestring(" ("); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs); buf.writeByte(')'); buf.writenl(); requireDo = false; @@ -1635,7 +1586,7 @@ public: else { buf.writenl(); - frequire.statementToBuffer(buf, hgs); + frequire.statementToBuffer(*buf, hgs); requireDo = true; } } @@ -1655,7 +1606,7 @@ public: buf.writestring(fensure.id.toString()); } buf.writestring("; "); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs); buf.writeByte(')'); buf.writenl(); requireDo = false; @@ -1669,7 +1620,7 @@ public: buf.writeByte(')'); } buf.writenl(); - fensure.ensure.statementToBuffer(buf, hgs); + fensure.ensure.statementToBuffer(*buf, hgs); requireDo = true; } } @@ -1717,7 +1668,7 @@ public: buf.writeByte('{'); buf.writenl(); buf.level++; - f.fbody.statementToBuffer(buf, hgs); + f.fbody.statementToBuffer(*buf, hgs); buf.level--; buf.writeByte('}'); buf.writenl(); @@ -1740,8 +1691,8 @@ public: TypeFunction tf = cast(TypeFunction)f.type; if (!f.inferRetType && tf.next) - typeToBuffer(tf.next, null, buf, hgs); - parametersToBuffer(tf.parameterList, buf, hgs); + typeToBuffer(tf.next, null, *buf, hgs); + parametersToBuffer(tf.parameterList, *buf, hgs); // https://issues.dlang.org/show_bug.cgi?id=20074 void printAttribute(string str) @@ -1764,7 +1715,7 @@ public: if (rs && rs.exp) { buf.writestring(" => "); - rs.exp.expressionToBuffer(buf, hgs); + rs.exp.expressionToBuffer(*buf, hgs); } else { @@ -1776,7 +1727,7 @@ public: override void visit(PostBlitDeclaration d) { - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); buf.writestring("this(this)"); bodyToBuffer(d); @@ -1784,7 +1735,7 @@ public: override void visit(DtorDeclaration d) { - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); buf.writestring("~this()"); bodyToBuffer(d); @@ -1792,7 +1743,7 @@ public: override void visit(StaticCtorDeclaration d) { - if (stcToBuffer(buf, d.storage_class & ~STC.static_)) + if (stcToBuffer(*buf, d.storage_class & ~STC.static_)) buf.writeByte(' '); if (d.isSharedStaticCtorDeclaration()) buf.writestring("shared "); @@ -1808,7 +1759,7 @@ public: override void visit(StaticDtorDeclaration d) { - if (stcToBuffer(buf, d.storage_class & ~STC.static_)) + if (stcToBuffer(*buf, d.storage_class & ~STC.static_)) buf.writeByte(' '); if (d.isSharedStaticDtorDeclaration()) buf.writestring("shared "); @@ -1826,14 +1777,14 @@ public: { if (hgs.hdrgen) return; - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); buf.writestring("invariant"); if(auto es = d.fbody.isExpStatement()) { assert(es.exp && es.exp.op == EXP.assert_); buf.writestring(" ("); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs); buf.writestring(");"); buf.writenl(); } @@ -1847,7 +1798,7 @@ public: { if (hgs.hdrgen) return; - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); buf.writestring("unittest"); bodyToBuffer(d); @@ -1855,33 +1806,88 @@ public: override void visit(BitFieldDeclaration d) { - if (stcToBuffer(buf, d.storage_class)) + if (stcToBuffer(*buf, d.storage_class)) buf.writeByte(' '); Identifier id = d.isAnonymous() ? null : d.ident; - typeToBuffer(d.type, id, buf, hgs); + typeToBuffer(d.type, id, *buf, hgs); buf.writestring(" : "); - d.width.expressionToBuffer(buf, hgs); + d.width.expressionToBuffer(*buf, hgs); buf.writeByte(';'); buf.writenl(); } override void visit(NewDeclaration d) { - if (stcToBuffer(buf, d.storage_class & ~STC.static_)) + if (stcToBuffer(*buf, d.storage_class & ~STC.static_)) buf.writeByte(' '); buf.writestring("new();"); } override void visit(Module m) { - moduleToBuffer2(m, buf, hgs); + moduleToBuffer2(m, *buf, hgs); + } +} + +/******************************************* + * Pretty-print a VarDeclaration to buf. + */ +private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, ref HdrGenState hgs) +{ + const bool isextern = hgs.hdrgen && + !hgs.insideFuncBody && + !hgs.tpltMember && + !hgs.insideAggregate && + !(v.storage_class & STC.manifest); + + void vinit(VarDeclaration v) + { + auto ie = v._init.isExpInitializer(); + if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) + (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs); + else + v._init.initializerToBuffer(buf, &hgs); + } + + if (anywritten) + { + buf.writestring(", "); + buf.writestring(v.ident.toString()); + } + else + { + const bool useTypeof = isextern && v._init && !v.type; + auto stc = v.storage_class; + if (isextern) + stc |= STC.extern_; + if (useTypeof) + stc &= ~STC.auto_; + if (stcToBuffer(buf, stc)) + buf.writeByte(' '); + if (v.type) + typeToBuffer(v.type, v.ident, buf, &hgs); + else if (useTypeof) + { + buf.writestring("typeof("); + vinit(v); + buf.writestring(") "); + buf.writestring(v.ident.toString()); + } + else + buf.writestring(v.ident.toString()); + } + if (v._init && !isextern) + { + buf.writestring(" = "); + vinit(v); } } + /********************************************* * Print expression to buffer. */ -private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hgs) +private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* hgs) { void visit(Expression e) { @@ -1922,7 +1928,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg case Tdchar: { const o = buf.length; - writeSingleCharLiteral(*buf, cast(dchar) v); + writeSingleCharLiteral(buf, cast(dchar) v); if (hgs.ddoc) escapeDdocString(buf, o); break; @@ -2064,7 +2070,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg const o = buf.length; foreach (i; 0 .. e.len) { - writeCharLiteral(*buf, e.getCodeUnit(i)); + writeCharLiteral(buf, e.getCodeUnit(i)); } if (hgs.ddoc) escapeDdocString(buf, o); @@ -2251,8 +2257,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg // which isn't correct as regular D code. buf.writeByte('('); - scope v = new DsymbolPrettyPrintVisitor(buf, hgs); - v.visitVarDecl(var, false); + visitVarDecl(var, false, buf, *hgs); buf.writeByte(';'); buf.writeByte(')'); @@ -2308,7 +2313,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg if (e.parameters && e.parameters.length) { buf.writestring(", "); - scope v = new DsymbolPrettyPrintVisitor(buf, hgs); + scope v = new DsymbolPrettyPrintVisitor(&buf, hgs); v.visitTemplateParameters(e.parameters); } buf.writeByte(')'); @@ -2717,7 +2722,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg * allowHex = whether hex floating point literals may be used * for greater accuracy */ -void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool allowHex) +void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool allowHex) { /** sizeof(value)*3 is because each byte of mantissa is max of 256 (3 characters). The string will be "-M.MMMMe-4932". @@ -2762,9 +2767,9 @@ void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool all } } -private void templateParameterToBuffer(TemplateParameter tp, OutBuffer* buf, HdrGenState* hgs) +private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs) { - scope v = new TemplateParameterPrettyPrintVisitor(buf, hgs); + scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs); tp.accept(v); } @@ -2787,12 +2792,12 @@ public: if (tp.specType) { buf.writestring(" : "); - typeToBuffer(tp.specType, null, buf, hgs); + typeToBuffer(tp.specType, null, *buf, hgs); } if (tp.defaultType) { buf.writestring(" = "); - typeToBuffer(tp.defaultType, null, buf, hgs); + typeToBuffer(tp.defaultType, null, *buf, hgs); } } @@ -2806,33 +2811,33 @@ public: { buf.writestring("alias "); if (tp.specType) - typeToBuffer(tp.specType, tp.ident, buf, hgs); + typeToBuffer(tp.specType, tp.ident, *buf, hgs); else buf.writestring(tp.ident.toString()); if (tp.specAlias) { buf.writestring(" : "); - objectToBuffer(tp.specAlias, buf, hgs); + objectToBuffer(tp.specAlias, *buf, hgs); } if (tp.defaultAlias) { buf.writestring(" = "); - objectToBuffer(tp.defaultAlias, buf, hgs); + objectToBuffer(tp.defaultAlias, *buf, hgs); } } override void visit(TemplateValueParameter tp) { - typeToBuffer(tp.valType, tp.ident, buf, hgs); + typeToBuffer(tp.valType, tp.ident, *buf, hgs); if (tp.specValue) { buf.writestring(" : "); - tp.specValue.expressionToBuffer(buf, hgs); + tp.specValue.expressionToBuffer(*buf, hgs); } if (tp.defaultValue) { buf.writestring(" = "); - tp.defaultValue.expressionToBuffer(buf, hgs); + tp.defaultValue.expressionToBuffer(*buf, hgs); } } @@ -2843,9 +2848,9 @@ public: } } -private void conditionToBuffer(Condition c, OutBuffer* buf, HdrGenState* hgs) +private void conditionToBuffer(Condition c, ref OutBuffer buf, HdrGenState* hgs) { - scope v = new ConditionPrettyPrintVisitor(buf, hgs); + scope v = new ConditionPrettyPrintVisitor(&buf, hgs); c.accept(v); } @@ -2885,42 +2890,42 @@ public: override void visit(StaticIfCondition c) { buf.writestring("static if ("); - c.exp.expressionToBuffer(buf, hgs); + c.exp.expressionToBuffer(*buf, hgs); buf.writeByte(')'); } } -void toCBuffer(const Statement s, OutBuffer* buf, HdrGenState* hgs) +void toCBuffer(const Statement s, ref OutBuffer buf, ref HdrGenState hgs) { - (cast()s).statementToBuffer(buf, hgs); + (cast()s).statementToBuffer(buf, &hgs); } -void toCBuffer(const Type t, OutBuffer* buf, const Identifier ident, HdrGenState* hgs) +void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs) { - typeToBuffer(cast() t, ident, buf, hgs); + typeToBuffer(cast() t, ident, buf, &hgs); } -void toCBuffer(Dsymbol s, OutBuffer* buf, HdrGenState* hgs) +void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { - scope v = new DsymbolPrettyPrintVisitor(buf, hgs); + scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs); s.accept(v); } // used from TemplateInstance::toChars() and TemplateMixin::toChars() -void toCBufferInstance(const TemplateInstance ti, OutBuffer* buf, bool qualifyTypes = false) +void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualifyTypes = false) { HdrGenState hgs; hgs.fullQual = qualifyTypes; - scope v = new DsymbolPrettyPrintVisitor(buf, &hgs); + scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs); v.visit(cast() ti); } -void toCBuffer(const Initializer iz, OutBuffer* buf, HdrGenState* hgs) +void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs) { - initializerToBuffer(cast() iz, buf, hgs); + initializerToBuffer(cast() iz, buf, &hgs); } -bool stcToBuffer(OutBuffer* buf, StorageClass stc) @safe +bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe { //printf("stc: %llx\n", stc); bool result = false; @@ -3039,7 +3044,7 @@ string stcToString(ref StorageClass stc) @safe return null; } -private void linkageToBuffer(OutBuffer* buf, LINK linkage) @safe +private void linkageToBuffer(ref OutBuffer buf, LINK linkage) @safe { const s = linkageToString(linkage); if (s.length) @@ -3077,7 +3082,7 @@ string linkageToString(LINK linkage) pure nothrow @safe } } -void visibilityToBuffer(OutBuffer* buf, Visibility vis) +void visibilityToBuffer(ref OutBuffer buf, Visibility vis) { buf.writestring(visibilityToString(vis.kind)); if (vis.kind == Visibility.Kind.package_ && vis.pkg) @@ -3121,28 +3126,28 @@ extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe } // Print the full function signature with correct ident, attributes and template args -void functionToBufferFull(TypeFunction tf, OutBuffer* buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td) +void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td) { //printf("TypeFunction::toCBuffer() this = %p\n", this); visitFuncIdentWithPrefix(tf, ident, td, buf, hgs); } // ident is inserted before the argument list and will be "function" or "delegate" for a type -void functionToBufferWithIdent(TypeFunction tf, OutBuffer* buf, const(char)* ident, bool isStatic) +void functionToBufferWithIdent(TypeFunction tf, ref OutBuffer buf, const(char)* ident, bool isStatic) { HdrGenState hgs; visitFuncIdentWithPostfix(tf, ident.toDString(), buf, &hgs, isStatic); } -void toCBuffer(const Expression e, OutBuffer* buf, HdrGenState* hgs) +void toCBuffer(const Expression e, ref OutBuffer buf, ref HdrGenState hgs) { - expressionPrettyPrint(cast()e, buf, hgs); + expressionPrettyPrint(cast()e, buf, &hgs); } /************************************************** * Write out argument types to buf. */ -void argExpTypesToCBuffer(OutBuffer* buf, Expressions* arguments) +void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments) { if (!arguments || !arguments.length) return; @@ -3155,13 +3160,13 @@ void argExpTypesToCBuffer(OutBuffer* buf, Expressions* arguments) } } -void toCBuffer(const TemplateParameter tp, OutBuffer* buf, HdrGenState* hgs) +void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs) { - scope v = new TemplateParameterPrettyPrintVisitor(buf, hgs); + scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs); (cast() tp).accept(v); } -void arrayObjectsToBuffer(OutBuffer* buf, Objects* objects) +void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects) { if (!objects || !objects.length) return; @@ -3184,7 +3189,7 @@ extern (C++) const(char)* parametersTypeToChars(ParameterList pl) { OutBuffer buf; HdrGenState hgs; - parametersToBuffer(pl, &buf, &hgs); + parametersToBuffer(pl, buf, &hgs); return buf.extractChars(); } @@ -3202,7 +3207,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua HdrGenState hgs; hgs.fullQual = fullQual; - parameterToBuffer(parameter, &buf, &hgs); + parameterToBuffer(parameter, buf, &hgs); if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1]) { @@ -3220,7 +3225,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua * hgs = context */ -private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* hgs) +private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, HdrGenState* hgs) { buf.writeByte('('); foreach (i; 0 .. pl.length) @@ -3258,7 +3263,7 @@ private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* h * buf = buffer to write it to * hgs = context */ -private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs) +private void parameterToBuffer(Parameter p, ref OutBuffer buf, HdrGenState* hgs) { if (p.userAttribDecl) { @@ -3330,7 +3335,7 @@ private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs) * basis = replace `null`s in argument list with this expression (for sparse array literals) * names = if non-null, use these as the names for the arguments */ -private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null) +private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null) { if (!expressions || !expressions.length) return; @@ -3381,7 +3386,7 @@ private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* } } -private void sizeToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs) +private void sizeToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs) { if (e.type == Type.tsize_t) { @@ -3409,7 +3414,7 @@ private void sizeToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs) expToBuffer(e, PREC.assign, buf, hgs); } -private void expressionToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs) +private void expressionToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs) { expressionPrettyPrint(e, buf, hgs); } @@ -3418,7 +3423,7 @@ private void expressionToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs) * Write expression out to buf, but wrap it * in ( ) if its precedence is less than pr. */ -private void expToBuffer(Expression e, PREC pr, OutBuffer* buf, HdrGenState* hgs) +private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, HdrGenState* hgs) { debug { @@ -3452,7 +3457,7 @@ private void expToBuffer(Expression e, PREC pr, OutBuffer* buf, HdrGenState* hgs /************************************************** * An entry point to pretty-print type. */ -private void typeToBuffer(Type t, const Identifier ident, OutBuffer* buf, HdrGenState* hgs, +private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, HdrGenState* hgs, ubyte modMask = 0) { if (auto tf = t.isTypeFunction()) @@ -3468,7 +3473,7 @@ private void typeToBuffer(Type t, const Identifier ident, OutBuffer* buf, HdrGen } } -private void visitWithMask(Type t, ubyte modMask, OutBuffer* buf, HdrGenState* hgs) +private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, HdrGenState* hgs) { // Tuples and functions don't use the type constructor syntax if (modMask == t.mod || t.ty == Tfunction || t.ty == Ttuple) @@ -3504,7 +3509,7 @@ private void visitWithMask(Type t, ubyte modMask, OutBuffer* buf, HdrGenState* h } -private void dumpTemplateInstance(TemplateInstance ti, OutBuffer* buf, HdrGenState* hgs) +private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs) { buf.writeByte('{'); buf.writenl(); @@ -3527,7 +3532,7 @@ private void dumpTemplateInstance(TemplateInstance ti, OutBuffer* buf, HdrGenSta } -private void tiargsToBuffer(TemplateInstance ti, OutBuffer* buf, HdrGenState* hgs) +private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs) { buf.writeByte('!'); if (ti.nest) @@ -3576,7 +3581,7 @@ private void tiargsToBuffer(TemplateInstance ti, OutBuffer* buf, HdrGenState* hg * This makes a 'pretty' version of the template arguments. * It's analogous to genIdent() which makes a mangled version. */ -private void objectToBuffer(RootObject oarg, OutBuffer* buf, HdrGenState* hgs) +private void objectToBuffer(RootObject oarg, ref OutBuffer buf, HdrGenState* hgs) { //printf("objectToBuffer()\n"); /* The logic of this should match what genIdent() does. The _dynamic_cast() @@ -3629,7 +3634,7 @@ private void objectToBuffer(RootObject oarg, OutBuffer* buf, HdrGenState* hgs) } -private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, OutBuffer* buf, HdrGenState* hgs, bool isStatic) +private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, HdrGenState* hgs, bool isStatic) { if (t.inuse) { @@ -3674,7 +3679,7 @@ private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, OutBu } private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, TemplateDeclaration td, - OutBuffer* buf, HdrGenState* hgs) + ref OutBuffer buf, HdrGenState* hgs) { if (t.inuse) { @@ -3743,7 +3748,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te } -private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* hgs) +private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState* hgs) { void visitError(ErrorInitializer iz) { @@ -3811,7 +3816,7 @@ private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* h if (d.exp) { buf.writeByte('['); - toCBuffer(d.exp, buf, hgs); + toCBuffer(d.exp, buf, *hgs); buf.writeByte(']'); } else @@ -3832,7 +3837,7 @@ private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* h } -private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs) +private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs) { void visitType(Type t) { @@ -4020,7 +4025,7 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs) buf.writeByte(' '); if (t.id) buf.writestring(t.id.toChars()); - if (t.tok == TOK.enum_ && t.base.ty != TY.Tint32) + if (t.tok == TOK.enum_ && t.base && t.base.ty != TY.Tint32) { buf.writestring(" : "); visitWithMask(t.base, t.mod, buf, hgs); diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h index 43fea34255f..e43a35510c2 100644 --- a/gcc/d/dmd/hdrgen.h +++ b/gcc/d/dmd/hdrgen.h @@ -15,7 +15,7 @@ class Module; -void genhdrfile(Module *m); +void genhdrfile(Module *m, OutBuffer &buf); void genCppHdrFiles(Modules &ms); -void moduleToBuffer(OutBuffer *buf, Module *m); +void moduleToBuffer(OutBuffer& buf, Module *m); const char *parametersTypeToChars(ParameterList pl); diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d index 1d4dea47b81..5494fecd70c 100644 --- a/gcc/d/dmd/iasmgcc.d +++ b/gcc/d/dmd/iasmgcc.d @@ -330,7 +330,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc) s.insn = semanticString(sc, s.insn, "asm instruction template"); if (s.labels && s.outputargs) - s.error("extended asm statements with labels cannot have output constraints"); + error(s.loc, "extended asm statements with labels cannot have output constraints"); // Analyse all input and output operands. if (s.args) diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 43b2e5f5a50..62fb51f752e 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -114,6 +114,7 @@ immutable Msgtable[] msgtable = { "returnLabel", "__returnLabel" }, { "line" }, { "empty", "" }, + { "dotdotdot", "..." }, // use for error messages { "p" }, { "__vptr" }, { "__monitor" }, @@ -305,6 +306,7 @@ immutable Msgtable[] msgtable = { "aaKeys", "_aaKeys" }, { "aaValues", "_aaValues" }, { "aaRehash", "_aaRehash" }, + { "_aaAsStruct" }, { "monitorenter", "_d_monitorenter" }, { "monitorexit", "_d_monitorexit" }, { "criticalenter", "_d_criticalenter2" }, diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d index e7cf9051034..4501185b393 100644 --- a/gcc/d/dmd/init.d +++ b/gcc/d/dmd/init.d @@ -61,7 +61,7 @@ extern (C++) class Initializer : ASTNode { OutBuffer buf; HdrGenState hgs; - .toCBuffer(this, &buf, &hgs); + toCBuffer(this, buf, hgs); return buf.extractChars(); } diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index c60b4311ff5..45f09af8733 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -53,31 +53,38 @@ import dmd.typesem; */ Expression toAssocArrayLiteral(ArrayInitializer ai) { - Expression e; - //printf("ArrayInitializer::toAssocArrayInitializer()\n"); + //printf("ArrayInitializer::toAssocArrayInitializer(%s)\n", ai.toChars()); //static int i; if (++i == 2) assert(0); const dim = ai.value.length; + if (!dim) + { + error(ai.loc, "invalid associative array initializer `%s`, use `null` instead", + ai.toChars()); + return ErrorExp.get(); + } + auto no(const char* format, Initializer i) + { + error(i.loc, format, i.toChars()); + return ErrorExp.get(); + } + Expression e; auto keys = new Expressions(dim); auto values = new Expressions(dim); for (size_t i = 0; i < dim; i++) { - e = ai.index[i]; - if (!e) - goto Lno; - (*keys)[i] = e; Initializer iz = ai.value[i]; - if (!iz) - goto Lno; + assert(iz); e = iz.initializerToExpression(); if (!e) - goto Lno; + return no("invalid value `%s` in initializer", iz); (*values)[i] = e; + e = ai.index[i]; + if (!e) + return no("missing key for value `%s` in initializer", iz); + (*keys)[i] = e; } e = new AssocArrayLiteralExp(ai.loc, keys, values); return e; -Lno: - error(ai.loc, "not an associative array initializer"); - return ErrorExp.get(); } /****************************************** diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d index 96899869d52..c803bf80cc0 100644 --- a/gcc/d/dmd/json.d +++ b/gcc/d/dmd/json.d @@ -810,17 +810,14 @@ public: Params: modules = array of the "root modules" */ - private void generateModules(Modules* modules) + private void generateModules(ref Modules modules) { arrayStart(); - if (modules) + foreach (m; modules) { - foreach (m; *modules) - { - if (global.params.verbose) - message("json gen %s", m.toChars()); - m.accept(this); - } + if (global.params.verbose) + message("json gen %s", m.toChars()); + m.accept(this); } arrayEnd(); } @@ -981,9 +978,15 @@ public: } } -extern (C++) void json_generate(OutBuffer* buf, Modules* modules) +/*********************************** + * Generate json for the modules. + * Params: + * modules = array of Modules + * buf = write json output to buf + */ +extern (C++) void json_generate(ref Modules modules, ref OutBuffer buf) { - scope ToJsonVisitor json = new ToJsonVisitor(buf); + scope ToJsonVisitor json = new ToJsonVisitor(&buf); // write trailing newline scope(exit) buf.writeByte('\n'); diff --git a/gcc/d/dmd/json.h b/gcc/d/dmd/json.h index 7a238979e20..09fdecdb9ee 100644 --- a/gcc/d/dmd/json.h +++ b/gcc/d/dmd/json.h @@ -15,5 +15,5 @@ struct OutBuffer; -void json_generate(OutBuffer *, Modules *); +void json_generate(Modules &, OutBuffer &); JsonFieldFlags tryParseJsonField(const char *fieldName); diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index c28fe5c2220..28ffbf8ed6d 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -51,7 +51,7 @@ struct CompileEnv bool previewIn; /// `in` means `[ref] scope const`, accepts rvalues bool ddocOutput; /// collect embedded documentation comments bool shortenedMethods = true; /// allow => in normal function declarations - bool obsolete; /// warn on use of legacy code + bool masm; /// use MASM inline asm syntax } /*********************************************************** @@ -484,6 +484,12 @@ class Lexer goto default; wysiwygStringConstant(t); return; + case 'x': + if (p[1] != '"') + goto case_ident; + p++; + t.value = hexStringConstant(t); + return; case 'q': if (Ccompile) goto case_ident; @@ -526,7 +532,7 @@ class Lexer //case 'u': case 'v': case 'w': - case 'x': + /*case 'x':*/ case 'y': case 'z': case 'A': @@ -1476,6 +1482,84 @@ class Lexer } } + /************************************** + * Lex hex strings: + * x"0A ae 34FE BD" + */ + final TOK hexStringConstant(Token* t) + { + Loc start = loc(); + uint n = 0; + uint v = ~0; // dead assignment, needed to suppress warning + p++; + stringbuffer.setsize(0); + while (1) + { + dchar c = *p++; + switch (c) + { + case ' ': + case '\t': + case '\v': + case '\f': + continue; // skip white space + case '\r': + if (*p == '\n') + continue; // ignore '\r' if followed by '\n' + // Treat isolated '\r' as if it were a '\n' + goto case '\n'; + case '\n': + endOfLine(); + continue; + case 0: + case 0x1A: + error("unterminated string constant starting at %s", start.toChars()); + t.setString(); + // decrement `p`, because it needs to point to the next token (the 0 or 0x1A character is the TOK.endOfFile token). + p--; + return TOK.hexadecimalString; + case '"': + if (n & 1) + { + error("odd number (%d) of hex characters in hex string", n); + stringbuffer.writeByte(v); + } + t.setString(stringbuffer); + stringPostfix(t); + return TOK.hexadecimalString; + default: + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c & 0x80) + { + p--; + const u = decodeUTF(); + p++; + if (u == PS || u == LS) + endOfLine(); + else + error("non-hex character \\u%04x in hex string", u); + } + else + error("non-hex character '%c' in hex string", c); + if (n & 1) + { + v = (v << 4) | c; + stringbuffer.writeByte(v); + } + else + v = c; + n++; + break; + } + } + assert(0); // see bug 15731 + } + /** Lex a delimited string. Some examples of delimited strings are: --- diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d index 0f3b9a7aa44..ef2bd0af779 100644 --- a/gcc/d/dmd/location.d +++ b/gcc/d/dmd/location.d @@ -38,8 +38,8 @@ debug info etc. struct Loc { private uint _linnum; - private ushort _charnum; - private ushort fileIndex; // index into filenames[], starting from 1 (0 means no filename) + private uint _charnum; + private uint 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 @@ -67,7 +67,7 @@ nothrow: extern (D) this(const(char)* filename, uint linnum, uint charnum) @safe { this._linnum = linnum; - this._charnum = cast(ushort) charnum; + this._charnum = charnum; this.filename = filename; } @@ -80,7 +80,7 @@ nothrow: /// ditto extern (C++) uint charnum(uint num) @nogc @safe { - return _charnum = cast(ushort) num; + return _charnum = num; } /// line number, starting from 1 @@ -114,8 +114,16 @@ nothrow: { //printf("setting %s\n", name); filenames.push(name); - fileIndex = cast(ushort)filenames.length; - assert(fileIndex); // no overflow + fileIndex = cast(uint)filenames.length; + if (!fileIndex) + { + import dmd.globals : global; + import dmd.errors : error, fatal; + + global.gag = 0; // ensure error message gets printed + error(Loc.initial, "internal compiler error: file name index overflow!"); + fatal(); + } } else fileIndex = 0; diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 8b481108f8c..ce512667694 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -142,7 +142,7 @@ public: int doppelganger; // sub-module Symbol *cov; // private uint[] __coverage; - unsigned *covb; // bit array of valid code line numbers + DArray<unsigned> covb; // bit array of valid code line numbers Symbol *sictor; // module order independent constructor Symbol *sctor; // module constructor diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 9d83db13b67..63e20ed89d0 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -157,7 +157,7 @@ MOD MODmerge(MOD mod1, MOD mod2) pure nothrow @nogc @safe /********************************* * Store modifier name into buf. */ -void MODtoBuffer(OutBuffer* buf, MOD mod) nothrow @safe +void MODtoBuffer(ref OutBuffer buf, MOD mod) nothrow @safe { buf.writestring(MODtoString(mod)); } @@ -787,7 +787,7 @@ extern (C++) abstract class Type : ASTNode HdrGenState hgs; hgs.fullQual = (ty == Tclass && !mod); - .toCBuffer(this, &buf, null, &hgs); + toCBuffer(this, buf, null, hgs); return buf.extractChars(); } @@ -799,7 +799,7 @@ extern (C++) abstract class Type : ASTNode HdrGenState hgs; hgs.fullQual = QualifyTypes; - .toCBuffer(this, &buf, null, &hgs); + toCBuffer(this, buf, null, hgs); return buf.extractChars(); } @@ -973,7 +973,7 @@ extern (C++) abstract class Type : ASTNode /********************************* * Store this type's modifier name into buf. */ - final void modToBuffer(OutBuffer* buf) nothrow const + final void modToBuffer(ref OutBuffer buf) nothrow const { if (mod) { @@ -989,7 +989,7 @@ extern (C++) abstract class Type : ASTNode { OutBuffer buf; buf.reserve(16); - modToBuffer(&buf); + modToBuffer(buf); return buf.extractChars(); } @@ -4563,7 +4563,7 @@ extern (C++) final class TypeFunction : TypeNext continue; if (params == parameterList.parameters) params = parameterList.parameters.copy(); - (*params)[i] = new Parameter(p.storageClass, t, null, null, null); + (*params)[i] = new Parameter(p.loc, p.storageClass, t, null, null, null); } if (next == tret && params == parameterList.parameters) return this; @@ -6218,7 +6218,7 @@ extern (C++) final class TypeTuple : Type Expression e = (*exps)[i]; if (e.type.ty == Ttuple) e.error("cannot form sequence of sequences"); - auto arg = new Parameter(STC.undefined_, e.type, null, null, null); + auto arg = new Parameter(e.loc, STC.undefined_, e.type, null, null, null); (*arguments)[i] = arg; } } @@ -6244,15 +6244,15 @@ extern (C++) final class TypeTuple : Type { super(Ttuple); arguments = new Parameters(); - arguments.push(new Parameter(0, t1, null, null, null)); + arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null)); } extern (D) this(Type t1, Type t2) { super(Ttuple); arguments = new Parameters(); - arguments.push(new Parameter(0, t1, null, null, null)); - arguments.push(new Parameter(0, t2, null, null, null)); + arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null)); + arguments.push(new Parameter(Loc.initial, 0, t2, null, null, null)); } static TypeTuple create() @safe @@ -6661,14 +6661,16 @@ extern (C++) final class Parameter : ASTNode { import dmd.attrib : UserAttributeDeclaration; + Loc loc; StorageClass storageClass; Type type; Identifier ident; Expression defaultArg; UserAttributeDeclaration userAttribDecl; // user defined attributes - extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe + extern (D) this(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe { + this.loc = loc; this.type = type; this.ident = ident; this.storageClass = storageClass; @@ -6676,14 +6678,14 @@ extern (C++) final class Parameter : ASTNode this.userAttribDecl = userAttribDecl; } - static Parameter create(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe + static Parameter create(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe { - return new Parameter(storageClass, type, ident, defaultArg, userAttribDecl); + return new Parameter(loc, storageClass, type, ident, defaultArg, userAttribDecl); } Parameter syntaxCopy() { - return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? userAttribDecl.syntaxCopy(null) : null); + return new Parameter(loc, storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? userAttribDecl.syntaxCopy(null) : null); } /**************************************************** @@ -7688,3 +7690,28 @@ pure string visitTYCase(string handler) @safe } assert(0); } + + +/** + * Returns: + * `TypeIdentifier` corresponding to `object.Throwable` + */ +TypeIdentifier getThrowable() +{ + auto tid = new TypeIdentifier(Loc.initial, Id.empty); + tid.addIdent(Id.object); + tid.addIdent(Id.Throwable); + return tid; +} + +/** + * Returns: + * TypeIdentifier corresponding to `object.Exception` + */ +TypeIdentifier getException() +{ + auto tid = new TypeIdentifier(Loc.initial, Id.empty); + tid.addIdent(Id.object); + tid.addIdent(Id.Exception); + return tid; +} diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 457b91f1cee..aeeee8c7dad 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -237,7 +237,7 @@ public: virtual unsigned alignsize(); Type *trySemantic(const Loc &loc, Scope *sc); Type *merge2(); - void modToBuffer(OutBuffer *buf) const; + void modToBuffer(OutBuffer& buf) const; char *modToChars() const; virtual bool isintegral(); @@ -563,13 +563,14 @@ enum class PURE : unsigned char class Parameter final : public ASTNode { public: + Loc loc; StorageClass storageClass; Type *type; Identifier *ident; Expression *defaultArg; UserAttributeDeclaration *userAttribDecl; // user defined attributes - static Parameter *create(StorageClass storageClass, Type *type, Identifier *ident, + static Parameter *create(const Loc &loc, StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg, UserAttributeDeclaration *userAttribDecl); Parameter *syntaxCopy(); Type *isLazyArray(); diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index 457e8b6479c..f9de1ee5a11 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -1767,10 +1767,10 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f if (fd_ambig) { - .error(ethis.loc, "`%s.%s` matches more than one declaration:\n`%s`: `%s`\nand:\n`%s`: `%s`", - ethis.toChars(), fstart.ident.toChars(), - fd_best.loc.toChars(), fd_best.type.toChars(), - fd_ambig.loc.toChars(), fd_ambig.type.toChars()); + .error(ethis.loc, "`%s.%s` matches more than one declaration:", + ethis.toChars(), fstart.ident.toChars()); + .errorSupplemental(fd_best.loc, "`%s`\nand:", fd_best.type.toChars()); + .errorSupplemental(fd_ambig.loc, "`%s`", fd_ambig.type.toChars()); return null; } diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d index f98e7c76bcc..37563826a2d 100644 --- a/gcc/d/dmd/optimize.d +++ b/gcc/d/dmd/optimize.d @@ -1280,19 +1280,25 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) //printf("CatExp::optimize(%d) %s\n", result, e.toChars()); if (binOptimize(e, result)) return; - if (auto ce1 = e.e1.isCatExp()) - { - // https://issues.dlang.org/show_bug.cgi?id=12798 - // optimize ((expr ~ str1) ~ str2) - scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2); - cex.type = e.type; - Expression ex = Expression_optimize(cex, result, false); - if (ex != cex) + + if (e.type == Type.tstring) + if (auto ce1 = e.e1.isCatExp()) { - e.e1 = ce1.e1; - e.e2 = ex; + // https://issues.dlang.org/show_bug.cgi?id=12798 + // optimize ((expr ~ str1) ~ str2) + // https://issues.dlang.org/show_bug.cgi?id=24078 + // This optimization is only valid if `expr` is a string. + // Otherwise it leads to: + // `["c"] ~ "a" ~ "b"` becoming `["c"] ~ "ab"` + scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2); + cex.type = e.type; + Expression ex = Expression_optimize(cex, result, false); + if (ex != cex) + { + e.e1 = ce1.e1; + e.e2 = ex; + } } - } // optimize "str"[] -> "str" if (auto se1 = e.e1.isSliceExp()) { diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 13bba4fb284..2a964151be5 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -1204,7 +1204,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (orig & added) { OutBuffer buf; - AST.stcToBuffer(&buf, added); + AST.stcToBuffer(buf, added); error("redundant attribute `%s`", buf.peekChars()); return orig | added; } @@ -2007,6 +2007,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.wcharLiteral: case TOK.dcharLiteral: case TOK.string_: + case TOK.hexadecimalString: case TOK.file: case TOK.fileFullPath: case TOK.line: @@ -2545,7 +2546,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (StorageClass modStc = stc & STC.TYPECTOR) { OutBuffer buf; - AST.stcToBuffer(&buf, modStc); + AST.stcToBuffer(buf, modStc); error(loc, "static constructor cannot be `%s`", buf.peekChars()); } stc &= ~(STC.static_ | STC.TYPECTOR); @@ -2580,7 +2581,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (StorageClass modStc = stc & STC.TYPECTOR) { OutBuffer buf; - AST.stcToBuffer(&buf, modStc); + AST.stcToBuffer(buf, modStc); error(loc, "static destructor cannot be `%s`", buf.peekChars()); } stc &= ~(STC.static_ | STC.TYPECTOR); @@ -2619,7 +2620,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (StorageClass modStc = stc & STC.TYPECTOR) { OutBuffer buf; - AST.stcToBuffer(&buf, modStc); + AST.stcToBuffer(buf, modStc); error(loc, "shared static constructor cannot be `%s`", buf.peekChars()); } stc &= ~(STC.static_ | STC.TYPECTOR); @@ -2653,7 +2654,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (StorageClass modStc = stc & STC.TYPECTOR) { OutBuffer buf; - AST.stcToBuffer(&buf, modStc); + AST.stcToBuffer(buf, modStc); error(loc, "shared static destructor cannot be `%s`", buf.peekChars()); } stc &= ~(STC.static_ | STC.TYPECTOR); @@ -2837,7 +2838,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (varargsStc & ~VarArgsStc) { OutBuffer buf; - AST.stcToBuffer(&buf, varargsStc & ~VarArgsStc); + AST.stcToBuffer(buf, varargsStc & ~VarArgsStc); error("variadic parameter cannot have attributes `%s`", buf.peekChars()); varargsStc &= VarArgsStc; } @@ -2935,11 +2936,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer //error("scope cannot be ref or out"); const tv = peekNext(); + Loc loc; if (tpl && token.value == TOK.identifier && (tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot)) { Identifier id = Identifier.generateId("__T"); - const loc = token.loc; + loc = token.loc; at = new AST.TypeIdentifier(loc, id); if (!*tpl) *tpl = new AST.TemplateParameters(); @@ -2951,7 +2953,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else { - at = parseType(&ai); + at = parseType(&ai, null, &loc); } ae = null; if (token.value == TOK.assign) // = defaultArg @@ -2959,7 +2961,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); ae = parseDefaultInitExp(); } - auto param = new AST.Parameter(storageClass | STC.parameter, at, ai, ae, null); + auto param = new AST.Parameter(loc, storageClass | STC.parameter, at, ai, ae, null); if (udas) { auto a = new AST.Dsymbols(); @@ -3083,7 +3085,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else { OutBuffer buf; - AST.stcToBuffer(&buf, _stc); + AST.stcToBuffer(buf, _stc); error(attributeErrorMessage, buf.peekChars()); } nextToken(); @@ -3284,8 +3286,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value != TOK.rightCurly) { /* { */ - error(token.loc, "`}` expected following members in `%s` declaration at %s", - Token.toChars(tok), loc.toChars()); + error(token.loc, "`}` expected following members in `%s` declaration", + Token.toChars(tok)); + if (id) + eSink.errorSupplemental(loc, "%s `%s` starts here", + Token.toChars(tok), id.toChars()); + else + eSink.errorSupplemental(loc, "%s starts here", + Token.toChars(tok)); } nextToken(); } @@ -3481,8 +3489,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * Params: * pident = set to Identifier if there is one, null if not * ptpl = if !null, then set to TemplateParameterList + * pdeclLoc = if !null, then set to location of the declarator */ - AST.Type parseType(Identifier* pident = null, AST.TemplateParameters** ptpl = null) + AST.Type parseType(Identifier* pident = null, AST.TemplateParameters** ptpl = null, Loc* pdeclLoc = null) { /* Take care of the storage class prefixes that * serve as type attributes: @@ -3539,6 +3548,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Type t; t = parseBasicType(); + if (pdeclLoc) + *pdeclLoc = token.loc; int alt = 0; t = parseDeclarator(t, alt, pident, ptpl); checkCstyleTypeSyntax(typeLoc, t, alt, pident ? *pident : null); @@ -4575,8 +4586,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else if (t.ty == Tfunction) { + /* @@@DEPRECATED_2.115@@@ + * change to error, deprecated in 2.105.1 */ if (storage_class & STC.manifest) - error("function cannot have enum storage class"); + deprecation("function cannot have enum storage class"); AST.Expression constraint = null; //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t.toChars(), storage_class); @@ -4953,7 +4966,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (remStc) { OutBuffer buf; - AST.stcToBuffer(&buf, remStc); + AST.stcToBuffer(buf, remStc); // @@@DEPRECATED_2.103@@@ // Deprecated in 2020-07, can be made an error in 2.103 eSink.deprecation(token.loc, "storage class `%s` has no effect in type aliases", buf.peekChars()); @@ -5108,7 +5121,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (save == TOK.function_) { OutBuffer buf; - AST.stcToBuffer(&buf, modStc); + AST.stcToBuffer(buf, modStc); error("function literal cannot be `%s`", buf.peekChars()); } else @@ -5126,7 +5139,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer parameterList.parameters = new AST.Parameters(); Identifier id = Identifier.generateId("__T"); AST.Type t = new AST.TypeIdentifier(loc, id); - parameterList.parameters.push(new AST.Parameter(STC.parameter, t, token.ident, null, null)); + parameterList.parameters.push(new AST.Parameter(loc, STC.parameter, t, token.ident, null, null)); tpl = new AST.TemplateParameters(); AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null); @@ -5443,6 +5456,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { Identifier ai = null; AST.Type at; + Loc aloc; StorageClass storageClass = 0; StorageClass stc = 0; @@ -5524,6 +5538,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer lastai = token.ident; ai = token.ident; at = null; // infer argument type + aloc = token.loc; nextToken(); goto Larg; } @@ -5532,7 +5547,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (!ai) noIdentifierForDeclarator(at); Larg: - auto p = new AST.Parameter(storageClass, at, ai, null, null); + auto p = new AST.Parameter(aloc, storageClass, at, ai, null, null); parameters.push(p); if (token.value == TOK.comma) { @@ -5684,16 +5699,18 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { Identifier ai = token.ident; AST.Type at = null; // infer parameter type + const aloc = token.loc; nextToken(); check(TOK.assign); - param = new AST.Parameter(storageClass, at, ai, null, null); + param = new AST.Parameter(aloc, storageClass, at, ai, null, null); } else if (isDeclaration(&token, NeedDeclaratorId.must, TOK.assign, null)) { Identifier ai; + const aloc = token.loc; AST.Type at = parseType(&ai); check(TOK.assign); - param = new AST.Parameter(storageClass, at, ai, null, null); + param = new AST.Parameter(aloc, storageClass, at, ai, null, null); } else if (storageClass != 0) error("found `%s` while expecting `=` or identifier", n.toChars()); @@ -5789,6 +5806,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.true_: case TOK.false_: case TOK.string_: + case TOK.hexadecimalString: case TOK.leftParenthesis: case TOK.cast_: case TOK.mul: @@ -5816,7 +5834,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Expression exp = parseExpression(); /* https://issues.dlang.org/show_bug.cgi?id=15103 * Improve declaration / initialization syntax error message - * Error: found 'foo' when expecting ';' following statement + * Error: found 'foo' when expecting ';' following expression * becomes Error: found `(` when expecting `;` or `=`, did you mean `Foo foo = 42`? */ if (token.value == TOK.identifier && exp.op == EXP.identifier) @@ -5841,11 +5859,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * otherwise we fall back on the old path (advancing the token). */ if (token.value != TOK.semicolon && peek(&token).value == TOK.semicolon) - error("found `%s` when expecting `;` following statement", token.toChars()); + error("found `%s` when expecting `;` following expression", token.toChars()); else { if (token.value != TOK.semicolon) - error("found `%s` when expecting `;` following statement `%s` on line %s", token.toChars(), exp.toChars(), exp.loc.toChars()); + { + error("found `%s` when expecting `;` following expression", token.toChars()); + eSink.errorSupplemental(exp.loc, "expression: `%s`", exp.toChars()); + } nextToken(); } } @@ -6580,7 +6601,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } case TOK.asm_: - s = parseAsm(); + s = parseAsm(false); break; case TOK.import_: @@ -6951,10 +6972,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * AsmInstruction ; * AsmInstruction ; AsmInstruction * + * Params: + * endOfLine = true if EOL means end of asm statement * Returns: * inline assembler block as a Statement */ - AST.Statement parseAsm() + AST.Statement parseAsm(bool endOfLine) { // Parse the asm block into a sequence of AsmStatements, // each AsmStatement is one instruction. @@ -6977,6 +7000,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer size_t nestlevel = 0; while (1) { + if (endOfLine) + nextDefineLine(); switch (token.value) { case TOK.identifier: @@ -7011,6 +7036,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } break; + case TOK.endOfLine: + nextDefineLine(); + goto case; + case TOK.semicolon: if (nestlevel != 0) error("mismatched number of curly brackets"); @@ -7018,7 +7047,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (toklist || label) { // Create AsmStatement from list of tokens we've saved - AST.Statement s = new AST.AsmStatement(token.loc, toklist); + AST.AsmStatement as = new AST.AsmStatement(token.loc, toklist); + as.caseSensitive = !endOfLine; + AST.Statement s = as; toklist = null; ptoklist = &toklist; if (label) @@ -7062,6 +7093,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer break; } nextToken(); + if (token.value == TOK.endOfLine) + nextToken(); auto s = new AST.CompoundAsmStatement(loc, statements, stc); return s; } @@ -7291,6 +7324,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.wcharLiteral: case TOK.dcharLiteral: case TOK.string_: + case TOK.hexadecimalString: case TOK.file: case TOK.fileFullPath: case TOK.line: @@ -7562,7 +7596,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } continue; - // Valid tokens that follow a declaration + // Valid tokens that follow the start of a declaration case TOK.rightParenthesis: case TOK.rightBracket: case TOK.assign: @@ -7581,6 +7615,23 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } return false; + // To recognize the shortened function declaration syntax + case TOK.goesTo: + /* + 1. https://issues.dlang.org/show_bug.cgi?id=24088 + + 2. We need to make sure the would-be + declarator has an identifier otherwise function literals + are handled incorrectly. Some special treatment is required + here, it turns out that a lot of code in the compiler relies + on this mess (in the parser), i.e. having isDeclarator be more + precise the parsing of other things go kaboom, so we do it in a + separate case. + */ + if (*haveId) + goto case TOK.do_; + goto default; + case TOK.identifier: if (t.ident == Id._body) { @@ -8148,6 +8199,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer break; case TOK.string_: + case TOK.hexadecimalString: { // cat adjacent strings auto s = token.ustring; @@ -8157,7 +8209,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { const prev = token; nextToken(); - if (token.value == TOK.string_) + if (token.value == TOK.string_ || token.value == TOK.hexadecimalString) { if (token.postfix) { @@ -9549,7 +9601,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer void usageOfBodyKeyword() { - if (compileEnv.obsolete) + version (none) // disable obsolete warning { eSink.warning(token.loc, "usage of identifer `body` as a keyword is obsolete. Use `do` instead."); } diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d index e43ffad2570..e1deb2c8786 100644 --- a/gcc/d/dmd/printast.d +++ b/gcc/d/dmd/printast.d @@ -64,7 +64,7 @@ extern (C++) final class PrintASTVisitor : Visitor import dmd.hdrgen : floatToBuffer; import dmd.common.outbuffer : OutBuffer; OutBuffer buf; - floatToBuffer(e.type, e.value, &buf, false); + floatToBuffer(e.type, e.value, buf, false); printf("Real %s %s\n", buf.peekChars(), e.type ? e.type.toChars() : ""); } diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index c3fa90d7f79..bd531c0081e 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -51,7 +51,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) DotVarExp dve = cast(DotVarExp)e; if (VarDeclaration v = dve.var.isVarDeclaration()) { - if (sc.intypeof || !sc.func || !sc.func.isSafeBypassingInference()) + if (!sc.func) return false; auto ad = v.isMember2(); if (!ad) @@ -65,6 +65,11 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) return true; } + // This branch shouldn't be here, but unfortunately calling `ad.determineSize` + // breaks code with circular reference errors. Specifically, test23589.d fails + if (ad.sizeok != Sizeok.done && !sc.func.isSafeBypassingInference()) + return false; + // needed to set v.overlapped and v.overlapUnsafe if (ad.sizeok != Sizeok.done) ad.determineSize(ad.loc); @@ -74,9 +79,23 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) { if (v.overlapped) { - if (sc.setUnsafe(!printmsg, e.loc, + if (sc.func.isSafeBypassingInference() && sc.setUnsafe(!printmsg, e.loc, "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v)) + { return true; + } + else + { + import dmd.globals : FeatureState; + // @@@DEPRECATED_2.116@@@ + // https://issues.dlang.org/show_bug.cgi?id=20655 + // Inferring `@system` because of union access breaks code, + // so make it a deprecation safety violation as of 2.106 + // To turn into an error, remove `isSafeBypassingInference` check in the + // above if statement and remove the else branch + sc.setUnsafePreview(FeatureState.default_, !printmsg, e.loc, + "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v); + } } } diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d index 53c8714510c..e2d2e041162 100644 --- a/gcc/d/dmd/semantic2.d +++ b/gcc/d/dmd/semantic2.d @@ -275,6 +275,7 @@ private extern(C++) final class Semantic2Visitor : Visitor // https://issues.dlang.org/show_bug.cgi?id=20417 // Don't run CTFE for the temporary variables inside typeof or __traits(compiles) vd._init = vd._init.initializerSemantic(sc, vd.type, sc.intypeof == 1 || sc.flags & SCOPE.compile ? INITnointerpret : INITinterpret); + lowerStaticAAs(vd, sc); vd.inuse--; } if (vd._init && vd.storage_class & STC.manifest) @@ -819,3 +820,55 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag) } ale.elements.sort!predicate; } + +/** + * Try lower a variable's static Associative Array to a newaa struct. + * Params: + * vd = Variable to lower + * sc = Scope + */ +void lowerStaticAAs(VarDeclaration vd, Scope* sc) +{ + if (vd.storage_class & STC.manifest) + return; + if (auto ei = vd._init.isExpInitializer()) + { + scope v = new StaticAAVisitor(sc); + v.vd = vd; + ei.exp.accept(v); + } +} + +/// Visit Associative Array literals and lower them to structs for static initialization +private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor +{ + alias visit = SemanticTimeTransitiveVisitor.visit; + Scope* sc; + VarDeclaration vd; + + this(Scope* sc) scope @safe + { + this.sc = sc; + } + + override void visit(AssocArrayLiteralExp aaExp) + { + if (!verifyHookExist(aaExp.loc, *sc, Id._aaAsStruct, "initializing static associative arrays", Id.object)) + return; + + Expression hookFunc = new IdentifierExp(aaExp.loc, Id.empty); + hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id.object); + hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id._aaAsStruct); + auto arguments = new Expressions(); + arguments.push(aaExp.syntaxCopy()); + Expression loweredExp = new CallExp(aaExp.loc, hookFunc, arguments); + + sc = sc.startCTFE(); + loweredExp = loweredExp.expressionSemantic(sc); + loweredExp = resolveProperties(sc, loweredExp); + sc = sc.endCTFE(); + loweredExp = loweredExp.ctfeInterpret(); + + aaExp.lowering = loweredExp; + } +} diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index bff89f8eaf3..04f57a4c021 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -471,7 +471,7 @@ private extern(C++) final class Semantic3Visitor : Visitor stc |= STC.temp; } Type vtype = fparam.type; - auto v = new VarDeclaration(funcdecl.loc, vtype, id, null); + auto v = new VarDeclaration(fparam.loc, vtype, id, null); //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars()); stc |= STC.parameter; if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) @@ -749,7 +749,7 @@ private extern(C++) final class Semantic3Visitor : Visitor funcdecl.buildEnsureRequire(); // Check for errors related to 'nothrow'. - const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow); + const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null); if (f.isnothrow && blockexit & BE.throw_) error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars()); @@ -993,7 +993,7 @@ private extern(C++) final class Semantic3Visitor : Visitor freq = freq.statementSemantic(sc2); // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg` - const blockExit = freq.blockExit(funcdecl, false); + const blockExit = freq.blockExit(funcdecl, null); if (blockExit & BE.throw_) { if (isnothrow) @@ -1040,7 +1040,7 @@ private extern(C++) final class Semantic3Visitor : Visitor fens = fens.statementSemantic(sc2); // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg` - const blockExit = fens.blockExit(funcdecl, false); + const blockExit = fens.blockExit(funcdecl, null); if (blockExit & BE.throw_) { if (isnothrow) @@ -1177,7 +1177,7 @@ private extern(C++) final class Semantic3Visitor : Visitor s = s.statementSemantic(sc2); - const blockexit = s.blockExit(funcdecl, isnothrow); + const blockexit = s.blockExit(funcdecl, isnothrow ? global.errorSink : null); if (blockexit & BE.throw_) { funcdecl.hasNoEH = false; @@ -1187,7 +1187,7 @@ private extern(C++) final class Semantic3Visitor : Visitor f.isnothrow = false; } - if (sbody.blockExit(funcdecl, f.isnothrow) == BE.fallthru) + if (sbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null) == BE.fallthru) sbody = new CompoundStatement(Loc.initial, sbody, s); else sbody = new TryFinallyStatement(Loc.initial, sbody, s); @@ -1453,7 +1453,7 @@ private extern(C++) final class Semantic3Visitor : Visitor { // storage_class is apparently not set for dtor & ctor OutBuffer ob; - stcToBuffer(&ob, + stcToBuffer(ob, (ngErr ? STC.nogc : 0) | (puErr ? STC.pure_ : 0) | (saErr ? STC.system : 0) diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d index 607dd51e087..58550fe6ca4 100644 --- a/gcc/d/dmd/statement.d +++ b/gcc/d/dmd/statement.d @@ -16,20 +16,14 @@ module dmd.statement; import core.stdc.stdarg; import core.stdc.stdio; -import dmd.aggregate; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; +import dmd.errors; import dmd.gluelayer; import dmd.cond; -import dmd.dclass; import dmd.declaration; -import dmd.denum; -import dmd.dimport; -import dmd.dscope; import dmd.dsymbol; -import dmd.dtemplate; -import dmd.errors; import dmd.expression; import dmd.func; import dmd.globals; @@ -37,40 +31,14 @@ import dmd.hdrgen; import dmd.id; import dmd.identifier; import dmd.location; -import dmd.dinterpret; import dmd.mtype; import dmd.common.outbuffer; import dmd.root.rootobject; import dmd.sapply; -import dmd.sideeffect; import dmd.staticassert; import dmd.tokens; import dmd.visitor; -/** - * Returns: - * `TypeIdentifier` corresponding to `object.Throwable` - */ -TypeIdentifier getThrowable() -{ - auto tid = new TypeIdentifier(Loc.initial, Id.empty); - tid.addIdent(Id.object); - tid.addIdent(Id.Throwable); - return tid; -} - -/** - * Returns: - * TypeIdentifier corresponding to `object.Exception` - */ -TypeIdentifier getException() -{ - auto tid = new TypeIdentifier(Loc.initial, Id.empty); - tid.addIdent(Id.object); - tid.addIdent(Id.Exception); - return tid; -} - /*********************************************************** * Specification: https://dlang.org/spec/statement.html */ @@ -118,64 +86,11 @@ extern (C++) abstract class Statement : ASTNode { HdrGenState hgs; OutBuffer buf; - .toCBuffer(this, &buf, &hgs); + toCBuffer(this, buf, hgs); buf.writeByte(0); return buf.extractSlice().ptr; } - static if (__VERSION__ < 2092) - { - final void error(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.error); - va_end(ap); - } - - final void warning(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.warning); - va_end(ap); - } - - final void deprecation(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.deprecation); - va_end(ap); - } - } - else - { - pragma(printf) final void error(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.error); - va_end(ap); - } - - pragma(printf) final void warning(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.warning); - va_end(ap); - } - - pragma(printf) final void deprecation(const(char)* format, ...) - { - va_list ap; - va_start(ap, format); - .verrorReport(loc, format, ap, ErrorKind.deprecation); - va_end(ap); - } - } - Statement getRelatedLabeled() { return this; @@ -1252,9 +1167,10 @@ extern (C++) final class SwitchStatement : Statement if (v.isDataseg() || (v.storage_class & (STC.manifest | STC.temp) && vd.ident != Id.withSym) || v._init.isVoidInitializer()) continue; if (vd.ident == Id.withSym) - error("`switch` skips declaration of `with` temporary at %s", v.loc.toChars()); + error(loc, "`switch` skips declaration of `with` temporary"); else - error("`switch` skips declaration of variable `%s` at %s", v.toPrettyChars(), v.loc.toChars()); + error(loc, "`switch` skips declaration of variable `%s`", v.toPrettyChars()); + errorSupplemental(v.loc, "declared here"); return true; } return false; @@ -1813,22 +1729,22 @@ extern (C++) final class GotoStatement : Statement else { if (label.statement.os) - error("cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok)); + error(loc, "cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok)); else - error("cannot `goto` out of `%s` block", Token.toChars(os.tok)); + error(loc, "cannot `goto` out of `%s` block", Token.toChars(os.tok)); return true; } } if (label.statement.tf != tf) { - error("cannot `goto` in or out of `finally` block"); + error(loc, "cannot `goto` in or out of `finally` block"); return true; } if (label.statement.inCtfeBlock && !inCtfeBlock) { - error("cannot `goto` into `if (__ctfe)` block"); + error(loc, "cannot `goto` into `if (__ctfe)` block"); return true; } @@ -1837,7 +1753,7 @@ extern (C++) final class GotoStatement : Statement { if (!stb) { - error("cannot `goto` into `try` block"); + error(loc, "cannot `goto` into `try` block"); return true; } if (auto stf = stb.isTryFinallyStatement()) @@ -1863,17 +1779,15 @@ extern (C++) final class GotoStatement : Statement { // Lifetime ends at end of expression, so no issue with skipping the statement } - else if (vd.ident == Id.withSym) - { - error("`goto` skips declaration of `with` temporary at %s", vd.loc.toChars()); - return true; - } else { - error("`goto` skips declaration of variable `%s` at %s", vd.toPrettyChars(), vd.loc.toChars()); + if (vd.ident == Id.withSym) + error(loc, "`goto` skips declaration of `with` temporary"); + else + error(loc, "`goto` skips declaration of variable `%s`", vd.toPrettyChars()); + errorSupplemental(vd.loc, "declared here"); return true; } - return false; } @@ -1959,6 +1873,7 @@ extern (C++) final class LabelDsymbol : Dsymbol extern (C++) class AsmStatement : Statement { Token* tokens; + bool caseSensitive; // for register names extern (D) this(const ref Loc loc, Token* tokens) @safe { diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h index eb4849dfc1b..dd8b9f21c05 100644 --- a/gcc/d/dmd/statement.h +++ b/gcc/d/dmd/statement.h @@ -116,7 +116,7 @@ public: const char *toChars() const override final; void error(const char *format, ...); - void warning(const char *format, ...); + void warning(unsigned flag, const char *format, ...); void deprecation(const char *format, ...); virtual Statement *getRelatedLabeled() { return this; } virtual bool hasBreak() const; @@ -712,6 +712,7 @@ class AsmStatement : public Statement { public: Token *tokens; + bool caseSensitive; // for register names AsmStatement *syntaxCopy() override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 178cef5af8c..304cb862f32 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -38,6 +38,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.escape; import dmd.expression; import dmd.expressionsem; @@ -349,7 +350,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Identifier id = Identifier.generateId("__o"); Statement handler = new PeelStatement(sexception); - if (sexception.blockExit(sc.func, false) & BE.fallthru) + if (sexception.blockExit(sc.func, null) & BE.fallthru) { auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id)); ts.internalThrow = true; @@ -704,7 +705,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (!p.type) { - fs.error("cannot infer type for `foreach` variable `%s`, perhaps set it explicitly", p.ident.toChars()); + error(fs.loc, "cannot infer type for `foreach` variable `%s`, perhaps set it explicitly", p.ident.toChars()); p.type = Type.terror; result = true; } @@ -753,7 +754,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { assert(oaggr.type); - fs.error("invalid `%s` aggregate `%s` of type `%s`", + error(fs.loc, "invalid `%s` aggregate `%s` of type `%s`", Token.toChars(fs.op), oaggr.toChars(), oaggr.type.toPrettyChars()); if (auto ad = isAggregate(fs.aggr.type)) @@ -815,11 +816,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (foundMismatch && dim != foreachParamCount) { const(char)* plural = foreachParamCount > 1 ? "s" : ""; - fs.error("cannot infer argument types, expected %llu argument%s, not %llu", + error(fs.loc, "cannot infer argument types, expected %llu argument%s, not %llu", cast(ulong) foreachParamCount, plural, cast(ulong) dim); } else - fs.error("cannot uniquely infer `foreach` argument types"); + error(fs.loc, "cannot uniquely infer `foreach` argument types"); return setError(); } @@ -845,11 +846,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (p.storageClass & STC.manifest) { - fs.error("cannot declare `enum` loop variables for non-unrolled foreach"); + error(fs.loc, "cannot declare `enum` loop variables for non-unrolled foreach"); } if (p.storageClass & STC.alias_) { - fs.error("cannot declare `alias` loop variables for non-unrolled foreach"); + error(fs.loc, "cannot declare `alias` loop variables for non-unrolled foreach"); } } @@ -861,7 +862,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) void rangeError() { - fs.error("cannot infer argument types"); + error(fs.loc, "cannot infer argument types"); return retError(); } @@ -959,7 +960,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (dim < 1 || dim > 2) { - fs.error("only one or two arguments for array `foreach`"); + error(fs.loc, "only one or two arguments for array `foreach`"); return retError(); } @@ -978,7 +979,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Type tindex = (*fs.parameters)[0].type; if (!tindex.isintegral()) { - fs.error("foreach: key cannot be of non-integral type `%s`", tindex.toChars()); + error(fs.loc, "foreach: key cannot be of non-integral type `%s`", tindex.toChars()); return retError(); } /* What cases to deprecate implicit conversions for: @@ -990,7 +991,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) (tn.ty != tv.ty && tn.ty.isSomeChar && tv.ty.isSomeChar)) && !Type.tsize_t.implicitConvTo(tindex)) { - fs.deprecation("foreach: loop index implicitly converted from `size_t` to `%s`", + deprecation(fs.loc, "foreach: loop index implicitly converted from `size_t` to `%s`", tindex.toChars()); } } @@ -1007,7 +1008,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (p.storageClass & STC.ref_) { - fs.error("`foreach`: value of UTF conversion cannot be `ref`"); + error(fs.loc, "`foreach`: value of UTF conversion cannot be `ref`"); return retError(); } if (dim == 2) @@ -1015,7 +1016,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) p = (*fs.parameters)[0]; if (p.storageClass & STC.ref_) { - fs.error("`foreach`: key cannot be `ref`"); + error(fs.loc, "`foreach`: key cannot be `ref`"); return retError(); } } @@ -1036,7 +1037,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (fs.key.type.constConv(p.type) == MATCH.nomatch) { - fs.error("key type mismatch, `%s` to `ref %s`", + error(fs.loc, "key type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), p.type.toChars()); return retError(); } @@ -1048,7 +1049,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) dimrange.imax = SignExtendedNumber(dimrange.imax.value-1); if (!IntRange.fromType(fs.key.type).contains(dimrange)) { - fs.error("index type `%s` cannot cover index range 0..%llu", + error(fs.loc, "index type `%s` cannot cover index range 0..%llu", p.type.toChars(), ta.dim.toInteger()); return retError(); } @@ -1071,7 +1072,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Type t = tab.nextOf(); if (t.constConv(p.type) == MATCH.nomatch) { - fs.error("argument type mismatch, `%s` to `ref %s`", + error(fs.loc, "argument type mismatch, `%s` to `ref %s`", t.toChars(), p.type.toChars()); return retError(); } @@ -1197,13 +1198,13 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } case Taarray: if (fs.op == TOK.foreach_reverse_) - fs.warning("cannot use `foreach_reverse` with an associative array"); + warning(fs.loc, "cannot use `foreach_reverse` with an associative array"); if (checkForArgTypes(fs)) return retError(); if (dim < 1 || dim > 2) { - fs.error("only one or two arguments for associative array `foreach`"); + error(fs.loc, "only one or two arguments for associative array `foreach`"); return retError(); } return retStmt(apply()); @@ -1308,7 +1309,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } if (tfront.ty == Tvoid) { - fs.error("`%s.front` is `void` and has no value", oaggr.toChars()); + error(fs.loc, "`%s.front` is `void` and has no value", oaggr.toChars()); return retError(); } @@ -1348,7 +1349,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (exps.length != dim) { const(char)* plural = exps.length > 1 ? "s" : ""; - fs.error("cannot infer argument types, expected %llu argument%s, not %llu", + error(fs.loc, "cannot infer argument types, expected %llu argument%s, not %llu", cast(ulong) exps.length, plural, cast(ulong) dim); return retError(); } @@ -1371,7 +1372,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) p.type = p.type.addStorageClass(sc).typeSemantic(loc, sc2); if (!exp.implicitConvTo(p.type)) { - fs.error("cannot implicilty convert range element of type `%s` to variable `%s` of type `%s`", + error(fs.loc, "cannot implicilty convert range element of type `%s` to variable `%s` of type `%s`", exp.type.toChars(), p.toChars(), p.type.toChars()); return retError(); } @@ -1399,12 +1400,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } case Tdelegate: if (fs.op == TOK.foreach_reverse_) - fs.deprecation("cannot use `foreach_reverse` with a delegate"); + deprecation(fs.loc, "cannot use `foreach_reverse` with a delegate"); return retStmt(apply()); case Terror: return retError(); default: - fs.error("`foreach`: `%s` is not an aggregate type", fs.aggr.type.toChars()); + error(fs.loc, "`foreach`: `%s` is not an aggregate type", fs.aggr.type.toChars()); return retError(); } } @@ -1421,7 +1422,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) fs.lwr = fs.lwr.optimize(WANTvalue); if (!fs.lwr.type) { - fs.error("invalid range lower bound `%s`", fs.lwr.toChars()); + error(fs.loc, "invalid range lower bound `%s`", fs.lwr.toChars()); return setError(); } @@ -1430,7 +1431,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) fs.upr = fs.upr.optimize(WANTvalue); if (!fs.upr.type) { - fs.error("invalid range upper bound `%s`", fs.upr.toChars()); + error(fs.loc, "invalid range upper bound `%s`", fs.upr.toChars()); return setError(); } @@ -1584,7 +1585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (fs.key.type.constConv(fs.prm.type) == MATCH.nomatch) { - fs.error("argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.prm.type.toChars()); + error(fs.loc, "argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.prm.type.toChars()); return setError(); } } @@ -1762,14 +1763,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { /* Should this be allowed? */ - ps.error("`pragma(lib)` not allowed as statement"); + error(ps.loc, "`pragma(lib)` not allowed as statement"); return setError(); } else { if (!ps.args || ps.args.length != 1) { - ps.error("`string` expected for library name"); + error(ps.loc, "`string` expected for library name"); return setError(); } else @@ -1789,7 +1790,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { /* Should this be allowed? */ - ps.error("`pragma(linkerDirective)` not allowed as statement"); + error(ps.loc, "`pragma(linkerDirective)` not allowed as statement"); return setError(); } else if (ps.ident == Id.startaddress) @@ -1805,13 +1806,32 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } else { - ps.error("`pragma(inline)` is not inside a function"); + error(ps.loc, "`pragma(inline)` is not inside a function"); return setError(); } } + else if (ps.ident == Id.mangle) + { + auto es = ps._body ? ps._body.isExpStatement() : null; + auto de = es ? es.exp.isDeclarationExp() : null; + if (!de) + { + error(ps.loc, "`pragma(mangle)` must be attached to a declaration"); + return setError(); + } + const se = ps.args && (*ps.args).length == 1 ? semanticString(sc, (*ps.args)[0], "pragma mangle argument") : null; + if (!se) + { + error(ps.loc, "`pragma(mangle)` takes a single argument that must be a string literal"); + return setError(); + } + const cnt = setMangleOverride(de.declaration, cast(const(char)[])se.peekData()); + if (cnt != 1) + assert(0); + } else if (!global.params.ignoreUnsupportedPragmas) { - ps.error("unrecognized `pragma(%s)`", ps.ident.toChars()); + error(ps.loc, "unrecognized `pragma(%s)`", ps.ident.toChars()); return setError(); } @@ -1819,7 +1839,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (ps.ident == Id.msg || ps.ident == Id.startaddress) { - ps.error("`pragma(%s)` is missing a terminating `;`", ps.ident.toChars()); + error(ps.loc, "`pragma(%s)` is missing a terminating `;`", ps.ident.toChars()); return setError(); } ps._body = ps._body.statementSemantic(sc); @@ -1885,7 +1905,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (!ss.condition.isErrorExp()) { - ss.error("`%s` must be of integral or string type, it is a `%s`", + error(ss.loc, "`%s` must be of integral or string type, it is a `%s`", ss.condition.toChars(), ss.condition.type.toChars()); conditionError = true; break; @@ -1924,7 +1944,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (!gcs.exp) { - gcs.error("no `case` statement following `goto case;`"); + error(gcs.loc, "no `case` statement following `goto case;`"); sc.pop(); return setError(); } @@ -1942,7 +1962,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } } } - gcs.error("`case %s` not found", gcs.exp.toChars()); + error(gcs.loc, "`case %s` not found", gcs.exp.toChars()); sc.pop(); return setError(); } @@ -1975,7 +1995,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) continue Lmembers; } if (missingMembers == 0) - ss.error("missing cases for `enum` members in `final switch`:"); + error(ss.loc, "missing cases for `enum` members in `final switch`:"); if (missingMembers < maxShown) errorSupplemental(ss.loc, "`%s`", em.toChars()); @@ -2000,7 +2020,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ss.hasNoDefault = 1; if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()) && !(sc.flags & SCOPE.Cfile)) - ss.error("`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`"); + error(ss.loc, "`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`"); // Generate runtime error if the default is hit auto a = new Statements(); @@ -2051,7 +2071,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) a.reserve(2); sc.sw.sdefault = new DefaultStatement(ss.loc, s); a.push(ss._body); - if (ss._body.blockExit(sc.func, false) & BE.fallthru) + if (ss._body.blockExit(sc.func, null) & BE.fallthru) a.push(new BreakStatement(Loc.initial, null)); a.push(sc.sw.sdefault); cs = new CompoundStatement(ss.loc, a); @@ -2193,12 +2213,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) */ if (!v.isConst() && !v.isImmutable()) { - cs.error("`case` variables have to be `const` or `immutable`"); + error(cs.loc, "`case` variables have to be `const` or `immutable`"); } if (sw.isFinal) { - cs.error("`case` variables not allowed in `final switch` statements"); + error(cs.loc, "`case` variables not allowed in `final switch` statements"); errors = true; } @@ -2213,7 +2233,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (!scx.search(cs.exp.loc, v.ident, null)) { - cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body", + error(cs.loc, "`case` variable `%s` declared at %s cannot be declared in `switch` body", v.toChars(), v.loc.toChars()); errors = true; } @@ -2229,7 +2249,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) cs.exp = se; else if (!cs.exp.isIntegerExp() && !cs.exp.isErrorExp()) { - cs.error("`case` expression must be a compile-time `string` or an integral constant, not `%s`", cs.exp.toChars()); + error(cs.loc, "`case` expression must be a compile-time `string` or an integral constant, not `%s`", cs.exp.toChars()); errors = true; } @@ -2242,7 +2262,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (cs2.exp.equals(cs.exp)) { // https://issues.dlang.org/show_bug.cgi?id=15909 - cs.error("duplicate `case %s` in `switch` statement", initialExp.toChars()); + error(cs.loc, "duplicate `case %s` in `switch` statement", initialExp.toChars()); errors = true; break; } @@ -2265,18 +2285,18 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (sc.sw.tf != sc.tf) { - cs.error("`switch` and `case` are in different `finally` blocks"); + error(cs.loc, "`switch` and `case` are in different `finally` blocks"); errors = true; } if (sc.sw.tryBody != sc.tryBody) { - cs.error("case cannot be in different `try` block level from `switch`"); + error(cs.loc, "case cannot be in different `try` block level from `switch`"); errors = true; } } else { - cs.error("`case` not in `switch` statement"); + error(cs.loc, "`case` not in `switch` statement"); errors = true; } @@ -2299,7 +2319,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) SwitchStatement sw = sc.sw; if (sw is null) { - crs.error("case range not in `switch` statement"); + error(crs.loc, "case range not in `switch` statement"); return setError(); } @@ -2307,7 +2327,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) bool errors = false; if (sw.isFinal) { - crs.error("case ranges not allowed in `final switch`"); + error(crs.loc, "case ranges not allowed in `final switch`"); errors = true; } @@ -2336,14 +2356,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) uinteger_t lval = crs.last.toInteger(); if ((crs.first.type.isunsigned() && fval > lval) || (!crs.first.type.isunsigned() && cast(sinteger_t)fval > cast(sinteger_t)lval)) { - crs.error("first `case %s` is greater than last `case %s`", crs.first.toChars(), crs.last.toChars()); + error(crs.loc, "first `case %s` is greater than last `case %s`", crs.first.toChars(), crs.last.toChars()); errors = true; lval = fval; } if (lval - fval > 256) { - crs.error("had %llu cases which is more than 257 cases in case range", 1 + lval - fval); + error(crs.loc, "had %llu cases which is more than 257 cases in case range", 1 + lval - fval); errors = true; lval = fval + 256; } @@ -2385,30 +2405,30 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (sc.sw.sdefault) { - ds.error("`switch` statement already has a default"); + error(ds.loc, "`switch` statement already has a default"); errors = true; } sc.sw.sdefault = ds; if (sc.sw.tf != sc.tf) { - ds.error("`switch` and `default` are in different `finally` blocks"); + error(ds.loc, "`switch` and `default` are in different `finally` blocks"); errors = true; } if (sc.sw.tryBody != sc.tryBody) { - ds.error("default cannot be in different `try` block level from `switch`"); + error(ds.loc, "default cannot be in different `try` block level from `switch`"); errors = true; } if (sc.sw.isFinal) { - ds.error("`default` statement not allowed in `final switch` statement"); + error(ds.loc, "`default` statement not allowed in `final switch` statement"); errors = true; } } else { - ds.error("`default` not in `switch` statement"); + error(ds.loc, "`default` not in `switch` statement"); errors = true; } @@ -2429,12 +2449,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) gds.sw = sc.sw; if (!gds.sw) { - gds.error("`goto default` not in `switch` statement"); + error(gds.loc, "`goto default` not in `switch` statement"); return setError(); } if (gds.sw.isFinal) { - gds.error("`goto default` not allowed in `final switch` statement"); + error(gds.loc, "`goto default` not allowed in `final switch` statement"); return setError(); } result = gds; @@ -2447,7 +2467,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (!sc.sw) { - gcs.error("`goto case` not in `switch` statement"); + error(gcs.loc, "`goto case` not in `switch` statement"); return setError(); } @@ -2512,7 +2532,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) bool errors = false; if (sc.flags & SCOPE.contract) { - rs.error("`return` statements cannot be in contracts"); + error(rs.loc, "`return` statements cannot be in contracts"); errors = true; } if (sc.os) @@ -2521,18 +2541,18 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // Deprecated in 2.100, transform into an error in 2.112 if (sc.os.tok == TOK.onScopeFailure) { - rs.deprecation("`return` statements cannot be in `scope(failure)` bodies."); + deprecation(rs.loc, "`return` statements cannot be in `scope(failure)` bodies."); deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose"); } else { - rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok)); + error(rs.loc, "`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok)); errors = true; } } if (sc.tf) { - rs.error("`return` statements cannot be in `finally` bodies"); + error(rs.loc, "`return` statements cannot be in `finally` bodies"); errors = true; } @@ -2540,7 +2560,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (rs.exp) { - rs.error("cannot return expression from constructor"); + error(rs.loc, "cannot return expression from constructor"); errors = true; } @@ -2595,7 +2615,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (!convToVoid) { - rs.error("cannot return non-void from `void` function"); + error(rs.loc, "cannot return non-void from `void` function"); errors = true; rs.exp = new CastExp(rs.loc, rs.exp, Type.tvoid); rs.exp = rs.exp.expressionSemantic(sc); @@ -2655,7 +2675,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } else if (!rs.exp.isErrorExp()) { - rs.error("expected return type of `%s`, not `%s`:", + error(rs.loc, "expected return type of `%s`, not `%s`:", tret.toChars(), rs.exp.type.toChars()); errorSupplemental((fd.returns) ? (*fd.returns)[0].loc : fd.loc, @@ -2697,7 +2717,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { /* May return by ref */ - if (checkReturnEscapeRef(sc, rs.exp, true)) + Scope* sc2 = sc.push(); + sc2.eSink = global.errorSinkNull; + bool err = checkReturnEscapeRef(sc2, rs.exp, true); + sc2.pop(); + + if (err) turnOffRef(() { checkReturnEscapeRef(sc, rs.exp, false); }); else if (!rs.exp.type.constConv(tf.next)) turnOffRef( @@ -2736,7 +2761,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { if (tf.next.ty != Terror) { - rs.error("mismatched function return type inference of `void` and `%s`", tf.next.toChars()); + error(rs.loc, "mismatched function return type inference of `void` and `%s`", tf.next.toChars()); } errors = true; tf.next = Type.terror; @@ -2755,15 +2780,15 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (tbret.ty != Terror) { if (e0) - rs.error("expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars()); + error(rs.loc, "expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars()); else if (tbret.isTypeNoreturn()) { - rs.error("cannot return from `noreturn` function"); + error(rs.loc, "cannot return from `noreturn` function"); .errorSupplemental(rs.loc, "Consider adding an endless loop, `assert(0)`, or another `noreturn` expression"); } else - rs.error("`return` expression expected"); + error(rs.loc, "`return` expression expected"); } errors = true; } @@ -2777,7 +2802,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // If any branches have called a ctor, but this branch hasn't, it's an error if (sc.ctorflow.callSuper & CSX.any_ctor && !(sc.ctorflow.callSuper & (CSX.this_ctor | CSX.super_ctor))) { - rs.error("`return` without calling constructor"); + error(rs.loc, "`return` without calling constructor"); errors = true; } @@ -2790,7 +2815,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested()); if (mustInit && !(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor)) { - rs.error("an earlier `return` statement skips field `%s` initialization", v.toChars()); + error(rs.loc, "an earlier `return` statement skips field `%s` initialization", v.toChars()); errors = true; } } @@ -2904,9 +2929,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { Statement s = ls.statement; if (!s || !s.hasBreak()) - bs.error("label `%s` has no `break`", bs.ident.toChars()); + error(bs.loc, "label `%s` has no `break`", bs.ident.toChars()); else if (ls.tf != sc.tf) - bs.error("cannot break out of `finally` block"); + error(bs.loc, "cannot break out of `finally` block"); else { ls.breaks = true; @@ -2916,14 +2941,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return setError(); } } - bs.error("enclosing label `%s` for `break` not found", bs.ident.toChars()); + error(bs.loc, "enclosing label `%s` for `break` not found", bs.ident.toChars()); return setError(); } else if (!sc.sbreak) { if (sc.os && sc.os.tok != TOK.onScopeFailure) { - bs.error("`break` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok)); + error(bs.loc, "`break` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok)); } else if (sc.fes) { @@ -2932,12 +2957,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return; } else - bs.error("`break` is not inside a loop or `switch`"); + error(bs.loc, "`break` is not inside a loop or `switch`"); return setError(); } else if (sc.sbreak.isForwardingStatement()) { - bs.error("must use labeled `break` within `static foreach`"); + error(bs.loc, "must use labeled `break` within `static foreach`"); } result = bs; } @@ -2992,9 +3017,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { Statement s = ls.statement; if (!s || !s.hasContinue()) - cs.error("label `%s` has no `continue`", cs.ident.toChars()); + error(cs.loc, "label `%s` has no `continue`", cs.ident.toChars()); else if (ls.tf != sc.tf) - cs.error("cannot continue out of `finally` block"); + error(cs.loc, "cannot continue out of `finally` block"); else { result = cs; @@ -3003,14 +3028,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return setError(); } } - cs.error("enclosing label `%s` for `continue` not found", cs.ident.toChars()); + error(cs.loc, "enclosing label `%s` for `continue` not found", cs.ident.toChars()); return setError(); } else if (!sc.scontinue) { if (sc.os && sc.os.tok != TOK.onScopeFailure) { - cs.error("`continue` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok)); + error(cs.loc, "`continue` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok)); } else if (sc.fes) { @@ -3019,12 +3044,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return; } else - cs.error("`continue` is not inside a loop"); + error(cs.loc, "`continue` is not inside a loop"); return setError(); } else if (sc.scontinue.isForwardingStatement()) { - cs.error("must use labeled `continue` within `static foreach`"); + error(cs.loc, "must use labeled `continue` within `static foreach`"); } result = cs; } @@ -3050,7 +3075,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ClassDeclaration cd = ss.exp.type.isClassHandle(); if (!cd) { - ss.error("can only `synchronize` on class objects, not `%s`", ss.exp.type.toChars()); + error(ss.loc, "can only `synchronize` on class objects, not `%s`", ss.exp.type.toChars()); return setError(); } else if (cd.isInterfaceDeclaration()) @@ -3060,7 +3085,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) */ if (!ClassDeclaration.object) { - ss.error("missing or corrupt object.d"); + error(ss.loc, "missing or corrupt object.d"); fatal(); } @@ -3085,7 +3110,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) cs.push(new ExpStatement(ss.loc, tmp)); auto args = new Parameters(); - args.push(new Parameter(0, ClassDeclaration.object.type, null, null, null)); + args.push(new Parameter(Loc.initial, 0, ClassDeclaration.object.type, null, null, null)); FuncDeclaration fdenter = FuncDeclaration.genCfunc(args, Type.tvoid, Id.monitorenter); Expression e = new CallExp(ss.loc, fdenter, new VarExp(ss.loc, tmp)); @@ -3127,7 +3152,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) cs.push(new ExpStatement(ss.loc, v)); auto enterArgs = new Parameters(); - enterArgs.push(new Parameter(0, t.pointerTo(), null, null, null)); + enterArgs.push(new Parameter(Loc.initial, 0, t.pointerTo(), null, null, null)); FuncDeclaration fdenter = FuncDeclaration.genCfunc(enterArgs, Type.tvoid, Id.criticalenter, STC.nothrow_); Expression e = new AddrExp(ss.loc, tmpExp); @@ -3137,7 +3162,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) cs.push(new ExpStatement(ss.loc, e)); auto exitArgs = new Parameters(); - exitArgs.push(new Parameter(0, t, null, null, null)); + exitArgs.push(new Parameter(Loc.initial, 0, t, null, null, null)); FuncDeclaration fdexit = FuncDeclaration.genCfunc(exitArgs, Type.tvoid, Id.criticalexit, STC.nothrow_); e = new CallExp(ss.loc, fdexit, tmpExp); @@ -3177,7 +3202,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Dsymbol s = (cast(TypeExp)ws.exp).type.toDsymbol(sc); if (!s || !s.isScopeDsymbol()) { - ws.error("`with` type `%s` has no members", ws.exp.toChars()); + error(ws.loc, "`with` type `%s` has no members", ws.exp.toChars()); return setError(); } sym = new WithScopeSymbol(ws); @@ -3252,7 +3277,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } else { - ws.error("`with` expression types must be enums or aggregates or pointers to them, not `%s`", olde.type.toChars()); + error(ws.loc, "`with` expression types must be enums or aggregates or pointers to them, not `%s`", olde.type.toChars()); return setError(); } } @@ -3281,13 +3306,13 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (!global.params.useExceptions) { - tcs.error("cannot use try-catch statements with -betterC"); + error(tcs.loc, "cannot use try-catch statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr); return setError(); } if (!ClassDeclaration.throwable) { - tcs.error("cannot use try-catch statements because `object.Throwable` was not declared"); + error(tcs.loc, "cannot use try-catch statements because `object.Throwable` was not declared"); return setError(); } @@ -3320,7 +3345,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) const sj = cj.loc.toChars(); if (c.type.toBasetype().implicitConvTo(cj.type.toBasetype())) { - tcs.error("`catch` at %s hides `catch` at %s", sj, si); + error(tcs.loc, "`catch` at %s hides `catch` at %s", sj, si); catchErrors = true; } } @@ -3331,7 +3356,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) sc.func.hasCatches = true; if (flags == (FLAGcpp | FLAGd)) { - tcs.error("cannot mix catching D and C++ exceptions in the same try-catch"); + error(tcs.loc, "cannot mix catching D and C++ exceptions in the same try-catch"); catchErrors = true; } } @@ -3353,7 +3378,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) /* If the try body never throws, we can eliminate any catches * of recoverable exceptions. */ - if (!(tcs._body.blockExit(sc.func, false) & BE.throw_) && ClassDeclaration.exception) + if (!(tcs._body.blockExit(sc.func, null) & BE.throw_) && ClassDeclaration.exception) { foreach_reverse (i; 0 .. tcs.catches.length) { @@ -3403,7 +3428,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return; } - auto blockexit = tfs._body.blockExit(sc.func, false); + auto blockexit = tfs._body.blockExit(sc.func, null); // if not worrying about exceptions if (!(global.params.useExceptions && ClassDeclaration.throwable)) @@ -3429,7 +3454,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // https://issues.dlang.org/show_bug.cgi?id=23159 if (!global.params.useExceptions) { - oss.error("`%s` cannot be used with -betterC", Token.toChars(oss.tok)); + error(oss.loc, "`%s` cannot be used with -betterC", Token.toChars(oss.tok)); return setError(); } @@ -3439,12 +3464,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (sc.os && sc.os.tok != TOK.onScopeFailure) { // If enclosing is scope(success) or scope(exit), this will be placed in finally block. - oss.error("cannot put `%s` statement inside `%s`", Token.toChars(oss.tok), Token.toChars(sc.os.tok)); + error(oss.loc, "cannot put `%s` statement inside `%s`", Token.toChars(oss.tok), Token.toChars(sc.os.tok)); return setError(); } if (sc.tf) { - oss.error("cannot put `%s` statement inside `finally` block", Token.toChars(oss.tok)); + error(oss.loc, "cannot put `%s` statement inside `finally` block", Token.toChars(oss.tok)); return setError(); } } @@ -3556,12 +3581,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (ls.loc == ls2.loc) { ls2.duplicated = true; - ls.error("label `%s` is duplicated", ls2.toChars()); + error(ls.loc, "label `%s` is duplicated", ls2.toChars()); .errorSupplemental(ls2.loc, "labels cannot be used in a static foreach with more than 1 iteration"); } else { - ls.error("label `%s` is already defined", ls2.toChars()); + error(ls.loc, "label `%s` is already defined", ls2.toChars()); .errorSupplemental(ls2.loc, "first definition is here"); } return setError(); @@ -3620,14 +3645,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) assert(sc.func); if (!(cas.stc & STC.pure_) && sc.func.setImpure(cas.loc, "`asm` statement is assumed to be impure - mark it with `pure` if it is not")) - cas.error("`asm` statement is assumed to be impure - mark it with `pure` if it is not"); + error(cas.loc, "`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"); + error(cas.loc, "`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"); + deprecation(cas.loc, "`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"); @@ -3696,7 +3721,7 @@ public bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc) { if (!global.params.useExceptions) { - loc.error("cannot use `throw` statements with -betterC"); + loc.error("cannot use `throw` statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr); return false; } @@ -3767,7 +3792,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, return null; if (ec.type != Type.tint32) { - fs.error("`opApply()` function for `%s` must return an `int`", tab.toChars()); + error(fs.loc, "`opApply()` function for `%s` must return an `int`", tab.toChars()); return null; } return ec; @@ -3792,7 +3817,7 @@ private extern(D) Expression applyDelegate(ForeachStatement fs, Expression flde, return null; if (ec.type != Type.tint32) { - fs.error("`opApply()` function for `%s` must return an `int`", tab.toChars()); + error(fs.loc, "`opApply()` function for `%s` must return an `int`", tab.toChars()); return null; } return ec; @@ -3841,13 +3866,13 @@ private extern(D) Expression applyArray(ForeachStatement fs, Expression flde, FuncDeclaration fdapply; TypeDelegate dgty; auto params = new Parameters(); - params.push(new Parameter(STC.in_, tn.arrayOf(), null, null, null)); + params.push(new Parameter(Loc.initial, STC.in_, tn.arrayOf(), null, null, null)); auto dgparams = new Parameters(); - dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null)); + dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null)); if (dim == 2) - dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null)); + dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null)); dgty = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d)); - params.push(new Parameter(0, dgty, null, null, null)); + params.push(new Parameter(Loc.initial, 0, dgty, null, null, null)); fdapply = FuncDeclaration.genCfunc(params, Type.tint32, fdname.ptr); if (tab.isTypeSArray()) @@ -3879,7 +3904,7 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld Type ti = (isRef ? taa.index.addMod(MODFlags.const_) : taa.index); if (isRef ? !ti.constConv(ta) : !ti.implicitConvTo(ta)) { - fs.error("`foreach`: index must be type `%s`, not `%s`", + error(fs.loc, "`foreach`: index must be type `%s`, not `%s`", ti.toChars(), ta.toChars()); return null; } @@ -3890,7 +3915,7 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld Type taav = taa.nextOf(); if (isRef ? !taav.constConv(ta) : !taav.implicitConvTo(ta)) { - fs.error("`foreach`: value must be type `%s`, not `%s`", + error(fs.loc, "`foreach`: value must be type `%s`, not `%s`", taav.toChars(), ta.toChars()); return null; } @@ -3908,14 +3933,14 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld if (!fdapply[i]) { auto params = new Parameters(); - params.push(new Parameter(0, Type.tvoid.pointerTo(), null, null, null)); - params.push(new Parameter(STC.const_, Type.tsize_t, null, null, null)); + params.push(new Parameter(Loc.initial, 0, Type.tvoid.pointerTo(), null, null, null)); + params.push(new Parameter(Loc.initial, STC.const_, Type.tsize_t, null, null, null)); auto dgparams = new Parameters(); - dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null)); + dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null)); if (dim == 2) - dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null)); + dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null)); fldeTy[i] = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d)); - params.push(new Parameter(0, fldeTy[i], null, null, null)); + params.push(new Parameter(Loc.initial, 0, fldeTy[i], null, null, null)); fdapply[i] = FuncDeclaration.genCfunc(params, Type.tint32, i ? Id._aaApply2 : Id._aaApply); } @@ -4000,7 +4025,7 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti { if (!(prm.storageClass & STC.ref_)) { - fs.error("`foreach`: cannot make `%s` `ref`", p.ident.toChars()); + error(fs.loc, "`foreach`: cannot make `%s` `ref`", p.ident.toChars()); return null; } goto LcopyArg; @@ -4026,7 +4051,7 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti Statement s = new ExpStatement(fs.loc, v); fs._body = new CompoundStatement(fs.loc, s, fs._body); } - params.push(new Parameter(stc, p.type, id, null, null)); + params.push(new Parameter(fs.loc, stc, p.type, id, null, null)); } // https://issues.dlang.org/show_bug.cgi?id=13840 // Throwable nested function inside nothrow function is acceptable. @@ -4328,7 +4353,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState const bool skipCheck = isStatic && needExpansion; if (!skipCheck && (dim < 1 || dim > 2)) { - fs.error("only one (value) or two (key,value) arguments allowed for sequence `foreach`"); + error(fs.loc, "only one (value) or two (key,value) arguments allowed for sequence `foreach`"); return returnEarly(); } @@ -4390,7 +4415,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState // Declare key if (p.isReference() || p.isLazy()) { - fs.error("no storage class for key `%s`", p.ident.toChars()); + error(fs.loc, "no storage class for key `%s`", p.ident.toChars()); return returnEarly(); } @@ -4405,7 +4430,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState if (!p.type.isintegral()) { - fs.error("foreach: key cannot be of non-integral type `%s`", + error(fs.loc, "foreach: key cannot be of non-integral type `%s`", p.type.toChars()); return returnEarly(); } @@ -4416,7 +4441,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState dimrange.imax = SignExtendedNumber(dimrange.imax.value-1); if (!IntRange.fromType(p.type).contains(dimrange)) { - fs.error("index type `%s` cannot cover index range 0..%llu", + error(fs.loc, "index type `%s` cannot cover index range 0..%llu", p.type.toChars(), cast(ulong)length); return returnEarly(); } @@ -4450,7 +4475,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState if (storageClass & (STC.out_ | STC.lazy_) || storageClass & STC.ref_ && !te) { - fs.error("no storage class for value `%s`", ident.toChars()); + error(fs.loc, "no storage class for value `%s`", ident.toChars()); return false; } Declaration var; @@ -4478,7 +4503,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState } else if (storageClass & STC.alias_) { - fs.error("`foreach` loop variable cannot be both `enum` and `alias`"); + error(fs.loc, "`foreach` loop variable cannot be both `enum` and `alias`"); return false; } @@ -4487,12 +4512,12 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState var = new AliasDeclaration(loc, ident, ds); if (storageClass & STC.ref_) { - fs.error("symbol `%s` cannot be `ref`", ds.toChars()); + error(fs.loc, "symbol `%s` cannot be `ref`", ds.toChars()); return false; } if (paramtype) { - fs.error("cannot specify element type for symbol `%s`", ds.toChars()); + error(fs.loc, "cannot specify element type for symbol `%s`", ds.toChars()); return false; } } @@ -4501,7 +4526,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState var = new AliasDeclaration(loc, ident, e.type); if (paramtype) { - fs.error("cannot specify element type for type `%s`", e.type.toChars()); + error(fs.loc, "cannot specify element type for type `%s`", e.type.toChars()); return false; } } @@ -4522,17 +4547,17 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState { if (!isStatic) { - fs.error("constant value `%s` cannot be `ref`", ie.toChars()); + error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars()); } else { if (!needExpansion) { - fs.error("constant value `%s` cannot be `ref`", ie.toChars()); + error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars()); } else { - fs.error("constant value `%s` cannot be `ref`", ident.toChars()); + error(fs.loc, "constant value `%s` cannot be `ref`", ident.toChars()); } } return false; @@ -4548,7 +4573,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState var = new AliasDeclaration(loc, ident, t); if (paramtype) { - fs.error("cannot specify element type for symbol `%s`", fs.toChars()); + error(fs.loc, "cannot specify element type for symbol `%s`", fs.toChars()); return false; } } diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d index 950c830cb33..c76d549550a 100644 --- a/gcc/d/dmd/tokens.d +++ b/gcc/d/dmd/tokens.d @@ -124,6 +124,7 @@ enum TOK : ubyte // Leaf operators identifier, string_, + hexadecimalString, this_, super_, error, @@ -855,6 +856,7 @@ extern (C++) struct Token TOK.wcharLiteral: "wcharv", TOK.dcharLiteral: "dcharv", TOK.wchar_tLiteral: "wchar_tv", + TOK.hexadecimalString: "xstring", TOK.endOfLine: "\\n", TOK.whitespace: "whitespace", @@ -898,7 +900,7 @@ extern (C++) struct Token nothrow: - int isKeyword() const @safe + int isKeyword() pure const @safe @nogc { foreach (kw; keywords) { @@ -1014,6 +1016,24 @@ nothrow: p = buf.extractChars(); } break; + case TOK.hexadecimalString: + { + OutBuffer buf; + buf.writeByte('x'); + buf.writeByte('"'); + foreach (size_t i; 0 .. len) + { + if (i) + buf.writeByte(' '); + buf.printf("%02x", ustring[i]); + } + buf.writeByte('"'); + if (postfix) + buf.writeByte(postfix); + buf.writeByte(0); + p = buf.extractData(); + break; + } case TOK.identifier: case TOK.enum_: case TOK.struct_: diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h index 6c1b9792dbb..b1f633fb9d9 100644 --- a/gcc/d/dmd/tokens.h +++ b/gcc/d/dmd/tokens.h @@ -133,6 +133,7 @@ enum class TOK : unsigned char // Leaf operators identifier, string_, + hexadecimalString, this_, super_, error, diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index 0d9c95ff173..2bde9f2aee9 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -1920,7 +1920,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) StringExp se = ex ? ex.ctfeInterpret().toStringExp() : null; if (!ex || !se || se.len == 0) { - e.error("string expected as argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars()); + e.error("string expected as argument of __traits `%s` instead of `%s`", e.ident.toChars(), (*e.args)[0].toChars()); return ErrorExp.get(); } se = se.toUTF8(sc); diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index a80aa80a89d..1422689dce0 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -1170,8 +1170,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) StorageClass stc2 = narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_); if (stc1 && stc2 && stc1 != stc2) { - OutBuffer buf1; stcToBuffer(&buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0)); - OutBuffer buf2; stcToBuffer(&buf2, stc2); + OutBuffer buf1; stcToBuffer(buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0)); + OutBuffer buf2; stcToBuffer(buf2, stc2); .error(loc, "incompatible parameter storage classes `%s` and `%s`", buf1.peekChars(), buf2.peekChars()); @@ -1179,7 +1179,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) stc = stc1 | (stc & ~(STC.ref_ | STC.out_ | STC.lazy_)); } (*newparams)[j] = new Parameter( - stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl); + loc, stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl); } fparam.type = new TypeTuple(newparams); fparam.type = fparam.type.typeSemantic(loc, argsc); @@ -2089,6 +2089,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden { e = new StringExp(loc, mt.deco.toDString()); Scope sc; + sc.eSink = global.errorSink; e = e.expressionSemantic(&sc); } } @@ -2097,6 +2098,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden const s = mt.toChars(); e = new StringExp(loc, s.toDString()); Scope sc; + sc.eSink = global.errorSink; e = e.expressionSemantic(&sc); } else if (flag && mt != Type.terror) @@ -2127,7 +2129,9 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden error(loc, "no property `%s` for `%s` of type `%s`", ident.toChars(), src.toChars(), mt.toPrettyChars(true)); else error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true)); + if (auto dsym = mt.toDsymbol(scope_)) + { if (auto sym = dsym.isAggregateDeclaration()) { if (auto fd = search_function(sym, Id.opDispatch)) @@ -2135,6 +2139,9 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden else if (!sym.members) errorSupplemental(sym.loc, "`%s %s` is opaque and has no members.", sym.kind, mt.toPrettyChars(true)); } + errorSupplemental(dsym.loc, "%s `%s` defined here", + dsym.kind, dsym.toChars()); + } } } e = ErrorExp.get(); @@ -3482,7 +3489,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag if (fd_aaLen is null) { auto fparams = new Parameters(); - fparams.push(new Parameter(STC.const_ | STC.scope_, mt, null, null, null)); + fparams.push(new Parameter(Loc.initial, STC.const_ | STC.scope_, mt, null, null, null)); fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen); TypeFunction tf = fd_aaLen.type.toTypeFunction(); tf.purity = PURE.const_; @@ -3938,6 +3945,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag e.error("no property `%s` for type `%s`", ident.toChars(), mt.toChars()); + errorSupplemental(mt.sym.loc, "%s `%s` defined here", + mt.sym.kind, mt.toChars()); return ErrorExp.get(); } return res; @@ -4791,7 +4800,7 @@ Type stripDefaultArgs(Type t) { Type t = stripDefaultArgs(p.type); return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl) - ? new Parameter(p.storageClass, t, null, null, null) + ? new Parameter(p.loc, p.storageClass, t, null, null, null) : null; } diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d index dfb4cb5ee2d..bb389b65903 100644 --- a/gcc/d/dmd/utils.d +++ b/gcc/d/dmd/utils.d @@ -53,12 +53,6 @@ const(char)* toWinPath(const(char)* src) * loc = The line number information from where the call originates * filename = Path to file */ -Buffer readFile(Loc loc, const(char)* filename) -{ - return readFile(loc, filename.toDString()); -} - -/// Ditto Buffer readFile(Loc loc, const(char)[] filename) { auto result = File.read(filename); @@ -78,15 +72,19 @@ Buffer readFile(Loc loc, const(char)[] filename) * loc = The line number information from where the call originates * filename = Path to file * data = Full content of the file to be written + * Returns: + * false on error */ -extern (D) void writeFile(Loc loc, const(char)[] filename, const void[] data) +extern (D) bool writeFile(Loc loc, const(char)[] filename, const void[] data) { - ensurePathToNameExists(Loc.initial, filename); + if (!ensurePathToNameExists(Loc.initial, filename)) + return false; if (!File.update(filename, data)) { error(loc, "error writing file '%.*s'", cast(int) filename.length, filename.ptr); - fatal(); + return false; } + return true; } @@ -97,8 +95,10 @@ extern (D) void writeFile(Loc loc, const(char)[] filename, const void[] data) * Params: * loc = The line number information from where the call originates * name = a path to check (the name is stripped) + * Returns: + * false on error */ -void ensurePathToNameExists(Loc loc, const(char)[] name) +bool ensurePathToNameExists(Loc loc, const(char)[] name) { const char[] pt = FileName.path(name); if (pt.length) @@ -106,10 +106,12 @@ void ensurePathToNameExists(Loc loc, const(char)[] name) if (!FileName.ensurePathExists(pt)) { error(loc, "cannot create directory %*.s", cast(int) pt.length, pt.ptr); - fatal(); + FileName.free(pt.ptr); + return false; } } FileName.free(pt.ptr); + return true; } diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 551d004c241..cc4aa03dfb9 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -2725,6 +2725,15 @@ public: void visit (AssocArrayLiteralExp *e) final override { + if (e->lowering != NULL) + { + /* When an associative array literal gets lowered, it's converted into a + struct literal suitable for static initialization. */ + gcc_assert (this->constp_); + this->result_ = build_expr (e->lowering, this->constp_, true); + return ; + } + /* Want the mutable type for typeinfo reference. */ Type *tb = e->type->toBasetype ()->mutableOf (); diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d index 2e36c7d02be..f8448d943e9 100644 --- a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d +++ b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d @@ -224,6 +224,15 @@ struct Params final ddocfiles(ddocfiles) {} }; + +struct Loc final +{ + static int32_t showColumns; + void toChars(int32_t showColumns = Loc::showColumns); + Loc() + { + } +}; --- */ @@ -337,3 +346,9 @@ extern (C++) struct Params bool obj = true; Array ddocfiles; } + +extern (C++) struct Loc +{ + __gshared int showColumns; + void toChars(int showColumns = Loc.showColumns) {} +} diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d index 38607f6d4b1..90223cca81e 100644 --- a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d +++ b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d @@ -45,10 +45,10 @@ struct S final int32_t get(int32_t , int32_t ); static int32_t get(); static const int32_t staticVar; - void useVars(int32_t pi = i, int32_t psv = staticVar); + void useVars(int32_t pi = i, int32_t psv = S::staticVar); struct Nested final { - void useStaticVar(int32_t i = staticVar); + void useStaticVar(int32_t i = S::staticVar); Nested() { } diff --git a/gcc/testsuite/gdc.test/compilable/issue22682.d b/gcc/testsuite/gdc.test/compilable/issue22682.d new file mode 100644 index 00000000000..5301a5163cd --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/issue22682.d @@ -0,0 +1,8 @@ +module issue22682; + +void main() +{ + pragma(mangle, "put" ~ "s") + extern(C) static int libcPuts(const char*); + libcPuts("issue 22682"); +} diff --git a/gcc/testsuite/gdc.test/compilable/obsolete_body.d b/gcc/testsuite/gdc.test/compilable/obsolete_body.d new file mode 100644 index 00000000000..71906e8f25e --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/obsolete_body.d @@ -0,0 +1,5 @@ +/* REQUIRED_ARGS: -w +*/ + +void test() +in { } body { } diff --git a/gcc/testsuite/gdc.test/compilable/shortened_methods.d b/gcc/testsuite/gdc.test/compilable/shortened_methods.d index 71350af8739..785cb8e5cd0 100644 --- a/gcc/testsuite/gdc.test/compilable/shortened_methods.d +++ b/gcc/testsuite/gdc.test/compilable/shortened_methods.d @@ -27,7 +27,12 @@ string test() => "hello"; // works at any scope static assert(test() == "hello"); // works normally static assert(is(typeof(&test) == string function())); // same normal type +struct S(T) {} + void func() { int a; int nested() => a; // and at nested scopes too + + // Issue 24088 - https://issues.dlang.org/show_bug.cgi?id=24088 + S!int f() => S!int(); } diff --git a/gcc/testsuite/gdc.test/compilable/test23145.d b/gcc/testsuite/gdc.test/compilable/test23145.d index 18eabfb51b5..c6bb55181b1 100644 --- a/gcc/testsuite/gdc.test/compilable/test23145.d +++ b/gcc/testsuite/gdc.test/compilable/test23145.d @@ -1,11 +1,4 @@ -/* REQUIRED_ARGS: -wo -wi -TEST_OUTPUT: ---- -compilable/test23145.d(117): Warning: `scope` allocation of `c` requires that constructor be annotated with `scope` -compilable/test23145.d(111): is the location of the constructor -compilable/test23145.d(124): Warning: `scope` allocation of `c` requires that constructor be annotated with `scope` -compilable/test23145.d(111): is the location of the constructor ---- +/* REQUIRED_ARGS: -wi */ // https://issues.dlang.org/show_bug.cgi?id=23145 @@ -28,14 +21,14 @@ class C C foo(D d) @nogc @safe { scope e = new C(1); // ok - scope c = new C(d); // deprecation + scope c = new C(d); // obsolete return c.d.c; } C bax(D d) @safe { scope e = new C(1); // ok - scope c = new C(d); // deprecation + scope c = new C(d); // obsolete return c.d.c; } diff --git a/gcc/testsuite/gdc.test/compilable/test24066.d b/gcc/testsuite/gdc.test/compilable/test24066.d new file mode 100644 index 00000000000..4b8a0b345bc --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24066.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=24066 + +/* +TEST_OUTPUT: +--- +false +--- +*/ + +class C; +pragma(msg, __traits(isAbstractClass, C)); diff --git a/gcc/testsuite/gdc.test/compilable/test24107.d b/gcc/testsuite/gdc.test/compilable/test24107.d new file mode 100644 index 00000000000..d16c259f16c --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24107.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=24107 + +/* +TEST_OUTPUT: +--- +This should not output an error message: false +--- +*/ + +bool recurse () +{ + return recurse(); +} + +pragma(msg, + "This should not output an error message: ", + __traits(compiles, {enum bool r = recurse();})); diff --git a/gcc/testsuite/gdc.test/compilable/test24109.d b/gcc/testsuite/gdc.test/compilable/test24109.d new file mode 100644 index 00000000000..67d03b58b06 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24109.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=24109 + +struct Outer +{ + void method1() {} + + void method2() + { + class Inner + { + void innerMethod() + { + method1(); + } + } + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test24118.d b/gcc/testsuite/gdc.test/compilable/test24118.d new file mode 100644 index 00000000000..25376b73b18 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24118.d @@ -0,0 +1,15 @@ +// https://issues.dlang.org/show_bug.cgi?id=24118 + +void map(alias fun, T)(T[] arr) +{ + fun(arr); +} + + +void foo() +{ + if( __ctfe ) + { + ["a", "b", "c"].map!( a => " " ~ a[0] ); + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/aa_init.d b/gcc/testsuite/gdc.test/fail_compilation/aa_init.d new file mode 100644 index 00000000000..b1473c136da --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/aa_init.d @@ -0,0 +1,16 @@ +/* +REQUIRED_ARGS: -vcolumns +TEST_OUTPUT: +--- +fail_compilation/aa_init.d(13,18): Error: invalid associative array initializer `[]`, use `null` instead +fail_compilation/aa_init.d(14,24): Error: missing key for value `4` in initializer +fail_compilation/aa_init.d(15,9): Error: cannot implicitly convert expression `[]` of type `void[]` to `int[int]` +--- +*/ + +void main() +{ + int[int] a = []; + int[int] b = [2:3, 4]; + a = []; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/body.d b/gcc/testsuite/gdc.test/fail_compilation/body.d deleted file mode 100644 index 7b718c25060..00000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/body.d +++ /dev/null @@ -1,11 +0,0 @@ -/* REQUIRED_ARGS: -wo -w -TEST_OUTPUT: ---- -fail_compilation/body.d(11): Warning: usage of identifer `body` as a keyword is obsolete. Use `do` instead. -Error: warnings are treated as errors - Use -wi if you wish to treat warnings only as informational. ---- -*/ - -void test() -in { } body { } diff --git a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d index eb75f4267b9..bd924665e3a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d +++ b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d @@ -24,6 +24,7 @@ fail_compilation/chkformat.d(122): Deprecation: argument `0LU` for format specif fail_compilation/chkformat.d(122): C `long` is 4 bytes on your system|32= fail_compilation/chkformat.d(122): Deprecation: argument `0LU` for format specification `"%lu"` must be `uint`, not `ulong` fail_compilation/chkformat.d(122): C `long` is 4 bytes on your system$ +fail_compilation/chkformat.d(123): Deprecation: argument `p` for format specification `"%n"` must be `int*`, not `const(int)*` fail_compilation/chkformat.d(201): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long` fail_compilation/chkformat.d(202): Deprecation: more format specifiers than 1 arguments fail_compilation/chkformat.d(203): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long` @@ -86,6 +87,7 @@ void test19() { int u; printf("%ls\n", &u); } //void test20() { int u; char[] s; sprintf(&s[0], "%d\n", &u); } //void test21() { int u; fprintf(null, "%d\n", &u); } void test20() { printf("%lu", ulong.init); } +void test22() { int i; const(int)* p = &i; printf("%n", p); } #line 200 diff --git a/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d b/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d deleted file mode 100644 index 553a0c64a20..00000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d +++ /dev/null @@ -1,9 +0,0 @@ -// REQUIRED_ARGS: -de -/* -TEST_OUTPUT: ---- -fail_compilation/dephexstrings.d(9): Error: semicolon expected following auto declaration, not `"60"` -fail_compilation/dephexstrings.d(9): Error: declaration expected, not `"60"` ---- -*/ -enum xstr = x"60"; diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d index 84d0ad4696b..e21a334548d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d @@ -2,7 +2,8 @@ EXTRA_FILES: imports/a10169.d TEST_OUTPUT: --- -fail_compilation/diag10169.d(12): Error: no property `x` for `B(0)` of type `imports.a10169.B` +fail_compilation/diag10169.d(13): Error: no property `x` for `B(0)` of type `imports.a10169.B` +fail_compilation/imports/a10169.d(3): struct `B` defined here --- */ import imports.a10169; diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d index 80c7f5e56ea..e69eddbec03 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/diag10783.d(14): Error: no property `type` for `event` of type `diag10783.Event` -fail_compilation/diag10783.d(14): Error: undefined identifier `En` +fail_compilation/diag10783.d(15): Error: no property `type` for `event` of type `diag10783.Event` +fail_compilation/diag10783.d(10): struct `Event` defined here +fail_compilation/diag10783.d(15): Error: undefined identifier `En` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag12063.d b/gcc/testsuite/gdc.test/fail_compilation/diag12063.d index 882a8091076..3e9535ab421 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag12063.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag12063.d @@ -1,8 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/diag12063.d(11): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed? -fail_compilation/diag12063.d(14): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int` +fail_compilation/diag12063.d(19): Error: cannot check `diag12063.Bar.b` value for overflow +fail_compilation/diag12063.d(16): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed? +fail_compilation/diag12063.d(19): Error: cannot generate value for `diag12063.Bar.b` +fail_compilation/diag12063.d(19): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int` +fail_compilation/diag12063.d(29): Error: cannot check `diag12063.b` value for overflow +fail_compilation/diag12063.d(29): Error: incompatible types for `(S()) == (1)`: `S` and `int` +fail_compilation/diag12063.d(38): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q` --- */ @@ -11,5 +16,36 @@ struct Foo {} enum Bar : Foo { a = Foo(), - b + b // no max, can't +1 +} + +struct S { + S opBinary(string s: "+")(int) => this; + enum max = 1; // wrong type +} + +enum { + a = S(), + b // can't do S() == 1 +} + +struct Q { + enum max = Q(); +} + +enum { + c = Q(), + d // overflow detected +} + +struct R { + int i; + R opBinary(string s: "+")(int) => this; + enum max = R(1); +} + +enum ER +{ + e = R(), + f // OK } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d index 1d37a1ecbfe..aaedd0f7217 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d @@ -1,11 +1,14 @@ /* TEST_OUTPUT: --- -fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC -fail_compilation/diag12829.d(15): `diag12829.test1.__lambda2` closes over variable `x` at fail_compilation/diag12829.d(14) -fail_compilation/diag12829.d(19): `diag12829.test1.bar` closes over variable `x` at fail_compilation/diag12829.d(14) -fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC -fail_compilation/diag12829.d(31): `diag12829.test2.S.foo` closes over variable `x` at fail_compilation/diag12829.d(28) +fail_compilation/diag12829.d(15): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC +fail_compilation/diag12829.d(18): delegate `diag12829.test1.__lambda2` closes over variable `x` +fail_compilation/diag12829.d(17): `x` declared here +fail_compilation/diag12829.d(22): function `diag12829.test1.bar` closes over variable `x` +fail_compilation/diag12829.d(17): `x` declared here +fail_compilation/diag12829.d(29): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC +fail_compilation/diag12829.d(34): function `diag12829.test2.S.foo` closes over variable `x` +fail_compilation/diag12829.d(31): `x` declared here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d b/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d index 039129e770f..7d0e259e41b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d @@ -1,10 +1,15 @@ /* TEST_OUTPUT: --- -fail_compilation/diag13609a.d(11): Error: `}` expected following members in `class` declaration at fail_compilation/diag13609a.d(8) +fail_compilation/diag13609a.d(16): Error: `}` expected following members in `struct` declaration +fail_compilation/diag13609a.d(15): struct starts here +fail_compilation/diag13609a.d(16): Error: `}` expected following members in `class` declaration +fail_compilation/diag13609a.d(11): class `C` starts here --- */ class C { void foo() {} + + struct { diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d index fa7c6114ad6..fee73078e30 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d @@ -1,10 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/diag14145.d(15): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)` -fail_compilation/diag14145.d(15): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message -fail_compilation/diag14145.d(34): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int` -fail_compilation/diag14145.d(16): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating +fail_compilation/diag14145.d(16): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)` +fail_compilation/diag14145.d(16): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/diag14145.d(26): struct `Capture` defined here +fail_compilation/diag14145.d(35): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int` +fail_compilation/diag14145.d(17): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d index e4cb2a7603a..00713449a5f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d @@ -1,10 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/diag15713.d(19): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data` -fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating -fail_compilation/diag15713.d(44): instantiated from here: `conwritefImpl!("main", "\n", Data(null))` -fail_compilation/diag15713.d(49): instantiated from here: `fdwritef!()` +fail_compilation/diag15713.d(20): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data` +fail_compilation/diag15713.d(16): struct `Data` defined here +fail_compilation/diag15713.d(40): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating +fail_compilation/diag15713.d(45): instantiated from here: `conwritefImpl!("main", "\n", Data(null))` +fail_compilation/diag15713.d(50): instantiated from here: `fdwritef!()` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3913.d b/gcc/testsuite/gdc.test/fail_compilation/diag3913.d index abf70b84ce7..41c08b0a76e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag3913.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag3913.d @@ -1,8 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/diag3913.d(12): Error: no property `foobardoo` for type `Foo` -fail_compilation/diag3913.d(13): Error: no property `secon` for type `Foo`. Did you mean `Foo.second` ? +fail_compilation/diag3913.d(14): Error: no property `foobardoo` for type `Foo` +fail_compilation/diag3913.d(13): enum `Foo` defined here +fail_compilation/diag3913.d(15): Error: no property `secon` for type `Foo`. Did you mean `Foo.second` ? +fail_compilation/diag3913.d(13): enum `Foo` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag5385.d b/gcc/testsuite/gdc.test/fail_compilation/diag5385.d index 60455eca206..368fdfff529 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag5385.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag5385.d @@ -2,14 +2,22 @@ EXTRA_FILES: imports/fail5385.d TEST_OUTPUT: --- -fail_compilation/diag5385.d(20): Error: no property `privX` for type `imports.fail5385.C` -fail_compilation/diag5385.d(21): Error: no property `packX` for type `imports.fail5385.C` -fail_compilation/diag5385.d(22): Error: no property `privX2` for type `imports.fail5385.C` -fail_compilation/diag5385.d(23): Error: no property `packX2` for type `imports.fail5385.C` -fail_compilation/diag5385.d(24): Error: no property `privX` for type `imports.fail5385.S` -fail_compilation/diag5385.d(25): Error: no property `packX` for type `imports.fail5385.S` -fail_compilation/diag5385.d(26): Error: no property `privX2` for type `imports.fail5385.S` -fail_compilation/diag5385.d(27): Error: no property `packX2` for type `imports.fail5385.S` +fail_compilation/diag5385.d(28): Error: no property `privX` for type `imports.fail5385.C` +fail_compilation/imports/fail5385.d(3): class `C` defined here +fail_compilation/diag5385.d(29): Error: no property `packX` for type `imports.fail5385.C` +fail_compilation/imports/fail5385.d(3): class `C` defined here +fail_compilation/diag5385.d(30): Error: no property `privX2` for type `imports.fail5385.C` +fail_compilation/imports/fail5385.d(3): class `C` defined here +fail_compilation/diag5385.d(31): Error: no property `packX2` for type `imports.fail5385.C` +fail_compilation/imports/fail5385.d(3): class `C` defined here +fail_compilation/diag5385.d(32): Error: no property `privX` for type `imports.fail5385.S` +fail_compilation/imports/fail5385.d(11): struct `S` defined here +fail_compilation/diag5385.d(33): Error: no property `packX` for type `imports.fail5385.S` +fail_compilation/imports/fail5385.d(11): struct `S` defined here +fail_compilation/diag5385.d(34): Error: no property `privX2` for type `imports.fail5385.S` +fail_compilation/imports/fail5385.d(11): struct `S` defined here +fail_compilation/diag5385.d(35): Error: no property `packX2` for type `imports.fail5385.S` +fail_compilation/imports/fail5385.d(11): struct `S` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag7477.d b/gcc/testsuite/gdc.test/fail_compilation/diag7477.d index b82b33de946..b14a3c5df65 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag7477.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag7477.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag7477.d(13): Error: integral constant must be scalar type, not `Foo` -fail_compilation/diag7477.d(20): Error: integral constant must be scalar type, not `string` +fail_compilation/diag7477.d(13): Error: cannot generate 0 value of type `Foo` for `a` +fail_compilation/diag7477.d(20): Error: cannot generate 0 value of type `string` for `a` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8697.d b/gcc/testsuite/gdc.test/fail_compilation/diag8697.d index a2abad58764..bcc0be09897 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag8697.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag8697.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag8697.d(10): Error: no property `Invalid` for type `diag8697.Base` +fail_compilation/diag8697.d(11): Error: no property `Invalid` for type `diag8697.Base` +fail_compilation/diag8697.d(9): class `Base` defined here --- */ interface InterBase : InterRoot { } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d index 7cf3023aedb..e8e0c74cc32 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d @@ -1,10 +1,14 @@ /* TEST_OUTPUT: --- -fail_compilation/diag8894.d(16): Error: no property `x` for `f` of type `diag8894.Foo` -fail_compilation/diag8894.d(17): Error: no property `y` for `f` of type `diag8894.Foo` -fail_compilation/diag8894.d(18): Error: no property `x` for `f` of type `diag8894.Foo` -fail_compilation/diag8894.d(19): Error: no property `x` for `f` of type `diag8894.Foo` +fail_compilation/diag8894.d(20): Error: no property `x` for `f` of type `diag8894.Foo` +fail_compilation/diag8894.d(15): struct `Foo` defined here +fail_compilation/diag8894.d(21): Error: no property `y` for `f` of type `diag8894.Foo` +fail_compilation/diag8894.d(15): struct `Foo` defined here +fail_compilation/diag8894.d(22): Error: no property `x` for `f` of type `diag8894.Foo` +fail_compilation/diag8894.d(15): struct `Foo` defined here +fail_compilation/diag8894.d(23): Error: no property `x` for `f` of type `diag8894.Foo` +fail_compilation/diag8894.d(15): struct `Foo` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d index e591a1428a5..77ab52046fc 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d @@ -1,17 +1,14 @@ /* -REQUIRED_ARGS: -de -wo +REQUIRED_ARGS: -de TEST_OUTPUT: --- -fail_compilation/dip1000_deprecation.d(20): Deprecation: `@safe` function `main` calling `inferred` -fail_compilation/dip1000_deprecation.d(28): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(28): scope variable `x0` may not be returned -fail_compilation/dip1000_deprecation.d(22): Deprecation: `@safe` function `main` calling `inferredC` -fail_compilation/dip1000_deprecation.d(39): which calls `dip1000_deprecation.inferred` -fail_compilation/dip1000_deprecation.d(28): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(28): scope variable `x0` may not be returned -fail_compilation/dip1000_deprecation.d(54): Warning: escaping reference to stack allocated value returned by `S(null)` -fail_compilation/dip1000_deprecation.d(55): Warning: escaping reference to stack allocated value returned by `createS()` -fail_compilation/dip1000_deprecation.d(58): Warning: returning `s.incorrectReturnRef()` escapes a reference to local variable `s` +fail_compilation/dip1000_deprecation.d(17): Deprecation: `@safe` function `main` calling `inferred` +fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: +fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned +fail_compilation/dip1000_deprecation.d(19): Deprecation: `@safe` function `main` calling `inferredC` +fail_compilation/dip1000_deprecation.d(36): which calls `dip1000_deprecation.inferred` +fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: +fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d index 324d21733af..661ebc33fa6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d @@ -2,11 +2,13 @@ EXTRA_FILES: imports/dip22a.d TEST_OUTPUT: --- -fail_compilation/dip22a.d(16): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass` -fail_compilation/dip22a.d(17): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct` -fail_compilation/dip22a.d(18): Error: undefined identifier `bar` in module `imports.dip22a` -fail_compilation/dip22a.d(19): Error: no property `bar` for `Template!int` of type `void` -fail_compilation/dip22a.d(20): Error: no property `bar` for `12` of type `int` +fail_compilation/dip22a.d(18): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass` +fail_compilation/imports/dip22a.d(3): class `Klass` defined here +fail_compilation/dip22a.d(19): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct` +fail_compilation/imports/dip22a.d(8): struct `Struct` defined here +fail_compilation/dip22a.d(20): Error: undefined identifier `bar` in module `imports.dip22a` +fail_compilation/dip22a.d(21): Error: no property `bar` for `Template!int` of type `void` +fail_compilation/dip22a.d(22): Error: no property `bar` for `12` of type `int` --- */ import imports.dip22a; diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_function.d b/gcc/testsuite/gdc.test/fail_compilation/enum_function.d index b22f2ceccef..52b71d12f5d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/enum_function.d +++ b/gcc/testsuite/gdc.test/fail_compilation/enum_function.d @@ -1,10 +1,11 @@ /* +REQUIRED_ARGS: -de TEST_OUTPUT: --- -fail_compilation/enum_function.d(10): Error: function cannot have enum storage class -fail_compilation/enum_function.d(11): Error: function cannot have enum storage class -fail_compilation/enum_function.d(12): Error: function cannot have enum storage class -fail_compilation/enum_function.d(13): Error: function cannot have enum storage class +fail_compilation/enum_function.d(11): Deprecation: function cannot have enum storage class +fail_compilation/enum_function.d(12): Deprecation: function cannot have enum storage class +fail_compilation/enum_function.d(13): Deprecation: function cannot have enum storage class +fail_compilation/enum_function.d(14): Deprecation: function cannot have enum storage class --- */ enum void f1() { return; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10528.d b/gcc/testsuite/gdc.test/fail_compilation/fail10528.d index 38c5a23a529..3b3f5bb7f79 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10528.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10528.d @@ -2,14 +2,18 @@ EXTRA_FILES: imports/a10528.d TEST_OUTPUT: --- -fail_compilation/fail10528.d(20): Error: undefined identifier `a` -fail_compilation/fail10528.d(21): Error: undefined identifier `a` in module `a10528` -fail_compilation/fail10528.d(23): Error: undefined identifier `b` -fail_compilation/fail10528.d(24): Error: undefined identifier `b` in module `a10528` -fail_compilation/fail10528.d(26): Error: no property `c` for type `a10528.S` -fail_compilation/fail10528.d(27): Error: no property `c` for type `a10528.S` -fail_compilation/fail10528.d(29): Error: no property `d` for type `a10528.C` -fail_compilation/fail10528.d(30): Error: no property `d` for type `a10528.C` +fail_compilation/fail10528.d(24): Error: undefined identifier `a` +fail_compilation/fail10528.d(25): Error: undefined identifier `a` in module `a10528` +fail_compilation/fail10528.d(27): Error: undefined identifier `b` +fail_compilation/fail10528.d(28): Error: undefined identifier `b` in module `a10528` +fail_compilation/fail10528.d(30): Error: no property `c` for type `a10528.S` +fail_compilation/imports/a10528.d(4): struct `S` defined here +fail_compilation/fail10528.d(31): Error: no property `c` for type `a10528.S` +fail_compilation/imports/a10528.d(4): struct `S` defined here +fail_compilation/fail10528.d(33): Error: no property `d` for type `a10528.C` +fail_compilation/imports/a10528.d(5): class `C` defined here +fail_compilation/fail10528.d(34): Error: no property `d` for type `a10528.C` +fail_compilation/imports/a10528.d(5): class `C` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d index fac37f444e3..b5bb67c2678 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d @@ -1,22 +1,22 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10534.d(28): Error: `a` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(28): Error: `b` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(29): Error: `a` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(29): Error: `b` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(30): Error: `a` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(30): Error: `b` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(31): Error: `a` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(31): Error: `b` is not of arithmetic type, it is a `int delegate()` -fail_compilation/fail10534.d(36): Error: `a` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(36): Error: `b` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(37): Error: `a` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(37): Error: `b` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(38): Error: `a` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(38): Error: `b` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(39): Error: `a` is not of arithmetic type, it is a `int function()` -fail_compilation/fail10534.d(39): Error: `b` is not of arithmetic type, it is a `int function()` +fail_compilation/fail10534.d(28): Error: illegal operator `+` for `a` of type `int delegate()` +fail_compilation/fail10534.d(28): Error: illegal operator `+` for `b` of type `int delegate()` +fail_compilation/fail10534.d(29): Error: illegal operator `-` for `a` of type `int delegate()` +fail_compilation/fail10534.d(29): Error: illegal operator `-` for `b` of type `int delegate()` +fail_compilation/fail10534.d(30): Error: illegal operator `/` for `a` of type `int delegate()` +fail_compilation/fail10534.d(30): Error: illegal operator `/` for `b` of type `int delegate()` +fail_compilation/fail10534.d(31): Error: illegal operator `*` for `a` of type `int delegate()` +fail_compilation/fail10534.d(31): Error: illegal operator `*` for `b` of type `int delegate()` +fail_compilation/fail10534.d(36): Error: illegal operator `+` for `a` of type `int function()` +fail_compilation/fail10534.d(36): Error: illegal operator `+` for `b` of type `int function()` +fail_compilation/fail10534.d(37): Error: illegal operator `-` for `a` of type `int function()` +fail_compilation/fail10534.d(37): Error: illegal operator `-` for `b` of type `int function()` +fail_compilation/fail10534.d(38): Error: illegal operator `/` for `a` of type `int function()` +fail_compilation/fail10534.d(38): Error: illegal operator `/` for `b` of type `int function()` +fail_compilation/fail10534.d(39): Error: illegal operator `*` for `a` of type `int function()` +fail_compilation/fail10534.d(39): Error: illegal operator `*` for `b` of type `int function()` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail109.d b/gcc/testsuite/gdc.test/fail_compilation/fail109.d index 87297dbacd7..003e65f9b80 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail109.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail109.d @@ -34,6 +34,7 @@ enum E1 : short /* https://issues.dlang.org/show_bug.cgi?id=14950 TEST_OUTPUT: --- +fail_compilation/fail109.d(50): Error: cannot check `fail109.B.end` value for overflow fail_compilation/fail109.d(50): Error: comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType` fail_compilation/fail109.d(50): Error: enum member `fail109.B.end` initialization with `B.start+1` causes overflow for type `C` --- @@ -43,7 +44,6 @@ enum C start, end } - enum B { start = C.end, diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail121.d b/gcc/testsuite/gdc.test/fail_compilation/fail121.d index 8d5af747ce1..110547be7ca 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail121.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail121.d @@ -3,8 +3,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail121.d(23): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject` -fail_compilation/fail121.d(23): Error: no property `typeinfo` for `i` of type `int` +fail_compilation/fail121.d(24): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject` +fail_compilation/fail121.d(12): struct `myobject` defined here +fail_compilation/fail121.d(24): Error: no property `typeinfo` for `i` of type `int` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail136.d b/gcc/testsuite/gdc.test/fail_compilation/fail136.d index 16659b5fdc1..3bc86537ed6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail136.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail136.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail136.d(10): Error: found `"EF BB BF"` when expecting `;` following statement +fail_compilation\fail136.d(10): Error: `"\xef\xbb\xbf"` has no effect --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17570.d b/gcc/testsuite/gdc.test/fail_compilation/fail17570.d index bee61cf0b22..9be7cd4b05f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17570.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail17570.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail17570.d(11): Error: cannot use function constraints for non-template functions. Use `static if` instead -fail_compilation/fail17570.d(11): Error: declaration expected, not `if` -fail_compilation/fail17570.d(14): Error: `}` expected following members in `struct` declaration at fail_compilation/fail17570.d(10) +fail_compilation/fail17570.d(12): Error: cannot use function constraints for non-template functions. Use `static if` instead +fail_compilation/fail17570.d(12): Error: declaration expected, not `if` +fail_compilation/fail17570.d(15): Error: `}` expected following members in `struct` declaration +fail_compilation/fail17570.d(11): struct `S` starts here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d index e6b95564b44..29bc3f448d8 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d @@ -1,6 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail17969.d(9): Error: no property `sum` for type `fail17969.__lambda6!(int[]).__lambda6.MapResult2!((b) => b)` +fail_compilation/fail17969.d(10): Error: no property `sum` for type `fail17969.__lambda6!(int[]).__lambda6.MapResult2!((b) => b)` +fail_compilation/fail17969.d(16): struct `MapResult2` defined here --- * https://issues.dlang.org/show_bug.cgi?id=17969 */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d index f3ec6806f6b..bf4b189f6eb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d @@ -3,10 +3,11 @@ /* TEST_OUTPUT: --- -fail_compilation/fail18219.d(16): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? -fail_compilation/fail18219.d(17): Error: no property `Bar` for type `a18219.AST` -fail_compilation/fail18219.d(18): Error: no property `fun` for type `AST`, did you mean `b18219.fun`? -fail_compilation/fail18219.d(19): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? +fail_compilation/fail18219.d(17): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? +fail_compilation/fail18219.d(18): Error: no property `Bar` for type `a18219.AST` +fail_compilation/imports/a18219.d(3): struct `AST` defined here +fail_compilation/fail18219.d(19): Error: no property `fun` for type `AST`, did you mean `b18219.fun`? +fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? --- */ import imports.a18219; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d index 0fb56d315e9..381ef3c7ef5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d @@ -1,8 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail18892.d(20): Error: no property `foo` for `a` of type `fail18892.MT` -fail_compilation/fail18892.d(21): Error: no property `foo` for `MT` of type `fail18892.MT` +fail_compilation/fail18892.d(22): Error: no property `foo` for `a` of type `fail18892.MT` +fail_compilation/fail18892.d(13): struct `MT` defined here +fail_compilation/fail18892.d(23): Error: no property `foo` for `MT` of type `fail18892.MT` +fail_compilation/fail18892.d(13): struct `MT` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d index a8156fe7d1e..9b1ec1d4589 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d @@ -1,10 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail18970.d(24): Error: no property `y` for `S()` of type `fail18970.S` -fail_compilation/fail18970.d(24): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message -fail_compilation/fail18970.d(31): Error: no property `yyy` for `this` of type `fail18970.S2` -fail_compilation/fail18970.d(31): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/fail18970.d(26): Error: no property `y` for `S()` of type `fail18970.S` +fail_compilation/fail18970.d(26): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/fail18970.d(15): struct `S` defined here +fail_compilation/fail18970.d(33): Error: no property `yyy` for `this` of type `fail18970.S2` +fail_compilation/fail18970.d(33): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/fail18970.d(29): struct `S2` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d index 04e36f623ff..9b7c59acd5b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d @@ -2,7 +2,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail18979.d(13): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo` +fail_compilation/fail18979.d(14): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo` +fail_compilation/imports/imp18979.d(3): struct `Foo` defined here ---- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail1900.d b/gcc/testsuite/gdc.test/fail_compilation/fail1900.d index edc463018db..7e5f05692b5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail1900.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail1900.d @@ -3,9 +3,9 @@ EXTRA_FILES: imports/fail1900a.d imports/fail1900b.d TEST_OUTPUT: --- fail_compilation/fail1900.d(27): Error: template `fail1900.Mix1a!().Foo` matches more than one template declaration: -fail_compilation/fail1900.d(14): `Foo(ubyte x)` -and -fail_compilation/fail1900.d(15): `Foo(byte x)` +fail_compilation/fail1900.d(14): `Foo(ubyte x)` +and: +fail_compilation/fail1900.d(15): `Foo(byte x)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19076.d b/gcc/testsuite/gdc.test/fail_compilation/fail19076.d index 2441d6f3cae..05ae21bf613 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19076.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19076.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail19076.d(11): Error: no property `V` for type `fail19076.I` -fail_compilation/fail19076.d(11): Error: `(I).V` cannot be resolved +fail_compilation/fail19076.d(12): Error: no property `V` for type `fail19076.I` +fail_compilation/fail19076.d(11): interface `I` defined here +fail_compilation/fail19076.d(12): Error: `(I).V` cannot be resolved --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d index 40fafcdc1ae..c1abd0df90a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d @@ -1,9 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/fail19103.d(12): Error: no property `puts` for `new C` of type `fail19103.C` -fail_compilation/fail19103.d(14): Error: no property `puts` for `s1` of type `fail19103.S1` -fail_compilation/fail19103.d(16): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`? +fail_compilation/fail19103.d(14): Error: no property `puts` for `new C` of type `fail19103.C` +fail_compilation/fail19103.d(26): class `C` defined here +fail_compilation/fail19103.d(16): Error: no property `puts` for `s1` of type `fail19103.S1` +fail_compilation/fail19103.d(30): struct `S1` defined here +fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`? --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d index cdad5c491db..78c596390b5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d @@ -1,26 +1,35 @@ /* TEST_OUTPUT: --- -fail_compilation/fail196.d(29): Error: delimited string must end in `)"` -fail_compilation/fail196.d(29): Error: implicit string concatenation is error-prone and disallowed in D -fail_compilation/fail196.d(29): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == " -fail_compilation/fail196.d(30): Error: semicolon needed to end declaration of `s`, instead of `foo` -fail_compilation/fail196.d(29): `s` declared here -fail_compilation/fail196.d(30): Error: found `");\n\n s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(30) -fail_compilation/fail196.d(32): Error: found `";\n assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(32) -fail_compilation/fail196.d(33): Error: found `");\n\n s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(33) -fail_compilation/fail196.d(35): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(35) -fail_compilation/fail196.d(35): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(35) -fail_compilation/fail196.d(36): Error: found `foo` when expecting `;` following statement `";\n assert(s == "` on line fail_compilation/fail196.d(35) -fail_compilation/fail196.d(36): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(36) -fail_compilation/fail196.d(38): Error: found `<` when expecting `;` following statement `");\n\n s = q" < foo` on line fail_compilation/fail196.d(36) -fail_compilation/fail196.d(39): Error: found `foo` when expecting `;` following statement `xxx >> ";\n assert(s == "` on line fail_compilation/fail196.d(38) -fail_compilation/fail196.d(39): Error: found `<` instead of statement -fail_compilation/fail196.d(45): Error: unterminated string constant starting at fail_compilation/fail196.d(45) -fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File` -fail_compilation/fail196.d(36): unmatched `{` -fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File` -fail_compilation/fail196.d(28): unmatched `{` +fail_compilation/fail196.d(38): Error: delimited string must end in `)"` +fail_compilation/fail196.d(38): Error: implicit string concatenation is error-prone and disallowed in D +fail_compilation/fail196.d(38): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == " +fail_compilation/fail196.d(39): Error: semicolon needed to end declaration of `s`, instead of `foo` +fail_compilation/fail196.d(38): `s` declared here +fail_compilation/fail196.d(39): Error: found `");\n\n s = q"` when expecting `;` following expression +fail_compilation/fail196.d(39): expression: `foo(xxx)` +fail_compilation/fail196.d(41): Error: found `";\n assert(s == "` when expecting `;` following expression +fail_compilation/fail196.d(41): expression: `[foo[xxx]]` +fail_compilation/fail196.d(42): Error: found `");\n\n s = q"` when expecting `;` following expression +fail_compilation/fail196.d(42): expression: `foo[xxx]` +fail_compilation/fail196.d(44): Error: found `{` when expecting `;` following expression +fail_compilation/fail196.d(44): expression: `foo` +fail_compilation/fail196.d(44): Error: found `}` when expecting `;` following expression +fail_compilation/fail196.d(44): expression: `xxx` +fail_compilation/fail196.d(45): Error: found `foo` when expecting `;` following expression +fail_compilation/fail196.d(44): expression: `";\n assert(s == "` +fail_compilation/fail196.d(45): Error: found `}` when expecting `;` following expression +fail_compilation/fail196.d(45): expression: `xxx` +fail_compilation/fail196.d(47): Error: found `<` when expecting `;` following expression +fail_compilation/fail196.d(45): expression: `");\n\n s = q" < foo` +fail_compilation/fail196.d(48): Error: found `foo` when expecting `;` following expression +fail_compilation/fail196.d(47): expression: `xxx >> ";\n assert(s == "` +fail_compilation/fail196.d(48): Error: found `<` instead of statement +fail_compilation/fail196.d(54): Error: unterminated string constant starting at fail_compilation/fail196.d(54) +fail_compilation/fail196.d(56): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/fail196.d(45): unmatched `{` +fail_compilation/fail196.d(56): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/fail196.d(37): unmatched `{` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20637.d b/gcc/testsuite/gdc.test/fail_compilation/fail20637.d index 77c69eaa6e6..dd0a5f52b87 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail20637.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail20637.d @@ -2,7 +2,8 @@ EXTRA_FILES: imports/fail20637b.d TEST_OUTPUT: --- -fail_compilation/fail20637.d(12): Error: no property `foo` for type `imports.fail20637b.A` +fail_compilation/fail20637.d(13): Error: no property `foo` for type `imports.fail20637b.A` +fail_compilation/imports/fail20637b.d(3): class `A` defined here --- */ module fail20637; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22054.d b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d index c172f089d9c..8b525d85fb2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail22054.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d @@ -3,10 +3,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22054.d(21): Error: no property `what` for type `fail22054.exception` -fail_compilation/fail22054.d(16): `class fail22054.exception` is opaque and has no members. -fail_compilation/fail22054.d(22): Error: no property `what` for type `fail22054.exception2` -fail_compilation/fail22054.d(17): `struct fail22054.exception2` is opaque and has no members. +fail_compilation/fail22054.d(23): Error: no property `what` for type `fail22054.exception` +fail_compilation/fail22054.d(18): `class fail22054.exception` is opaque and has no members. +fail_compilation/fail22054.d(18): class `exception` defined here +fail_compilation/fail22054.d(24): Error: no property `what` for type `fail22054.exception2` +fail_compilation/fail22054.d(19): `struct fail22054.exception2` is opaque and has no members. +fail_compilation/fail22054.d(19): struct `exception2` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22529.d b/gcc/testsuite/gdc.test/fail_compilation/fail22529.d index 3bec3c0f7d3..62eac25680d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail22529.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail22529.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22529.d(13): Error: found `return` when expecting `;` following statement +fail_compilation/fail22529.d(13): Error: found `return` when expecting `;` following expression --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d index 5c5c11b7195..ee560759e41 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d @@ -5,7 +5,9 @@ EXTRA_SOURCES: extra-files/test23109/object.d TEST_OUTPUT: --- Error: no property `getHash` for `typeid(const(Ensure[]))` of type `object.TypeInfo_Const` +fail_compilation/extra-files/test23109/object.d(7): class `TypeInfo_Const` defined here Error: no property `getHash` for `typeid(const(Ensure[1]))` of type `object.TypeInfo_Const` +fail_compilation/extra-files/test23109/object.d(7): class `TypeInfo_Const` defined here fail_compilation/imports/test23109a.d(10): Error: template instance `imports.test23109a.Array!(Ensure)` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail61.d b/gcc/testsuite/gdc.test/fail_compilation/fail61.d index a2f01d7e3ef..e7175b44245 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail61.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail61.d @@ -1,10 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/fail61.d(22): Error: no property `B` for type `fail61.A.B` -fail_compilation/fail61.d(23): Error: no property `B` for type `fail61.A.B` -fail_compilation/fail61.d(32): Error: no property `A2` for type `fail61.B2` -fail_compilation/fail61.d(41): Error: calling non-static function `foo` requires an instance of type `B3` +fail_compilation/fail61.d(25): Error: no property `B` for type `fail61.A.B` +fail_compilation/fail61.d(16): class `B` defined here +fail_compilation/fail61.d(26): Error: no property `B` for type `fail61.A.B` +fail_compilation/fail61.d(16): class `B` defined here +fail_compilation/fail61.d(35): Error: no property `A2` for type `fail61.B2` +fail_compilation/fail61.d(30): class `B2` defined here +fail_compilation/fail61.d(44): Error: calling non-static function `foo` requires an instance of type `B3` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7861.d b/gcc/testsuite/gdc.test/fail_compilation/fail7861.d index c7018c95762..a24eb95fbdf 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7861.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7861.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7861.d(17): Error: no property `nonexistent` for type `test.B` +fail_compilation/fail7861.d(18): Error: no property `nonexistent` for type `test.B` +fail_compilation/fail7861.d(14): struct `B` defined here --- */ module test; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9.d b/gcc/testsuite/gdc.test/fail_compilation/fail9.d index 08789954bb1..080ac1e5ebe 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail9.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail9.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9.d(23): Error: no property `Vector` for type `fail9.Vector!int` +fail_compilation/fail9.d(24): Error: no property `Vector` for type `fail9.Vector!int` +fail_compilation/fail9.d(13): class `Vector` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d index 8508b27d164..a9e5429366a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d @@ -1,23 +1,21 @@ /* -REQUIRED_ARGS: -wo TEST_OUTPUT: --- -fail_compilation/fail_scope.d(30): Deprecation: scope parameter `da` may not be returned -fail_compilation/fail_scope.d(32): Deprecation: scope parameter `o` may not be returned -fail_compilation/fail_scope.d(33): Deprecation: scope parameter `dg` may not be returned -fail_compilation/fail_scope.d(40): Deprecation: scope parameter `p` may not be returned -fail_compilation/fail_scope.d(45): Error: returning `cast(char[])string` escapes a reference to local variable `string` -fail_compilation/fail_scope.d(63): Error: returning `s.bar()` escapes a reference to local variable `s` -fail_compilation/fail_scope.d(74): Error: `fail_scope.foo8` called with argument types `(int)` matches both: -fail_compilation/fail_scope.d(68): `fail_scope.foo8(ref int x)` +fail_compilation/fail_scope.d(28): Deprecation: scope parameter `da` may not be returned +fail_compilation/fail_scope.d(30): Deprecation: scope parameter `o` may not be returned +fail_compilation/fail_scope.d(31): Deprecation: scope parameter `dg` may not be returned +fail_compilation/fail_scope.d(38): Deprecation: scope parameter `p` may not be returned +fail_compilation/fail_scope.d(43): Error: returning `cast(char[])string` escapes a reference to local variable `string` +fail_compilation/fail_scope.d(61): Error: returning `s.bar()` escapes a reference to local variable `s` +fail_compilation/fail_scope.d(72): Error: `fail_scope.foo8` called with argument types `(int)` matches both: +fail_compilation/fail_scope.d(66): `fail_scope.foo8(ref int x)` and: -fail_compilation/fail_scope.d(69): `fail_scope.foo8(return ref int x)` -fail_compilation/fail_scope.d(82): Error: returning `& string` escapes a reference to local variable `string` -fail_compilation/fail_scope.d(92): Error: returning `cast(int[])a` escapes a reference to local variable `a` -fail_compilation/fail_scope.d(100): Error: returning `cast(int[])a` escapes a reference to local variable `a` -fail_compilation/fail_scope.d(108): Error: escaping reference to outer local variable `x` -fail_compilation/fail_scope.d(127): Warning: returning `s.bar()` escapes a reference to local variable `s` -fail_compilation/fail_scope.d(137): Error: returning `foo16226(i)` escapes a reference to local variable `i` +fail_compilation/fail_scope.d(67): `fail_scope.foo8(return ref int x)` +fail_compilation/fail_scope.d(80): Error: returning `& string` escapes a reference to local variable `string` +fail_compilation/fail_scope.d(90): Error: returning `cast(int[])a` escapes a reference to local variable `a` +fail_compilation/fail_scope.d(98): Error: returning `cast(int[])a` escapes a reference to local variable `a` +fail_compilation/fail_scope.d(106): Error: escaping reference to outer local variable `x` +fail_compilation/fail_scope.d(135): Error: returning `foo16226(i)` escapes a reference to local variable `i` --- //fail_compilation/fail_scope.d(35): Error: scope variable `da` may not be returned //fail_compilation/fail_scope.d(37): Error: scope variable `o` may not be returned diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d index c44b289ccec..9b62c26edd0 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d +++ b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for `0` of type `int` -fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for type `object.Object` +fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for `0` of type `int` +fail_compilation/faildottypeinfo.d(13): Error: no property `typeinfo` for type `object.Object` +$p:druntime/import/object.d$($n$): class `Object` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d b/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d index 5862f7a8c88..21603f725f6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d @@ -1,11 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fnconstraint.d(13): Error: template constraint must follow parameter lists and attributes -fail_compilation/fnconstraint.d(13): Error: declaration expected, not `if` -fail_compilation/fnconstraint.d(22): Error: template constraint must follow parameter lists and attributes -fail_compilation/fnconstraint.d(22): Error: declaration expected, not `if` -fail_compilation/fnconstraint.d(26): Error: `}` expected following members in `struct` declaration at fail_compilation/fnconstraint.d(18) +fail_compilation/fnconstraint.d(14): Error: template constraint must follow parameter lists and attributes +fail_compilation/fnconstraint.d(14): Error: declaration expected, not `if` +fail_compilation/fnconstraint.d(23): Error: template constraint must follow parameter lists and attributes +fail_compilation/fnconstraint.d(23): Error: declaration expected, not `if` +fail_compilation/fnconstraint.d(27): Error: `}` expected following members in `struct` declaration +fail_compilation/fnconstraint.d(19): struct `S` starts here --- */ void foo()() diff --git a/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d b/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d new file mode 100644 index 00000000000..21bce5d2ec2 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d @@ -0,0 +1,57 @@ +/* +REQUIRED_ARGS: -verrors=context +TEST_OUTPUT: +--- +fail_compilation/goto_skip.d(28): Error: `goto` skips declaration of variable `goto_skip.skip.ch` + goto Lskip; + ^ +fail_compilation/goto_skip.d(29): declared here + char ch = '!'; + ^ +fail_compilation/goto_skip.d(36): Error: `goto` skips declaration of `with` temporary + goto L1; + ^ +fail_compilation/goto_skip.d(38): declared here + with (S()) { + ^ +fail_compilation/goto_skip.d(46): Error: `goto` skips declaration of variable `goto_skip.test8.e` + goto L2; + ^ +fail_compilation/goto_skip.d(51): declared here + catch (Exception e) { + ^ +--- +*/ +char skip(bool b) +{ + if (b) + goto Lskip; + char ch = '!'; +Lskip: + return ch; +} + +int f() +{ + goto L1; + struct S { int e = 5; } + with (S()) { +L1: + return e; + } +} + +void test8(int a) +{ + goto L2; + + try { + a += 2; + } + catch (Exception e) { + a += 3; +L2: ; + a += 100; + } + assert(a == 100); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10713.d b/gcc/testsuite/gdc.test/fail_compilation/ice10713.d index f3680329941..e59a594da8a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice10713.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice10713.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice10713.d(10): Error: no property `nonExistingField` for type `ice10713.S` +fail_compilation/ice10713.d(11): Error: no property `nonExistingField` for type `ice10713.S` +fail_compilation/ice10713.d(9): struct `S` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d index d21ee47dec7..4d107c9e7b2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/ice10938.d(13): Error: no property `opts` for `this` of type `ice10938.C` -fail_compilation/ice10938.d(13): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/ice10938.d(14): Error: no property `opts` for `this` of type `ice10938.C` +fail_compilation/ice10938.d(14): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/ice10938.d(10): class `C` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11518.d b/gcc/testsuite/gdc.test/fail_compilation/ice11518.d index c8542f77252..4e4f6170a61 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11518.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice11518.d @@ -2,9 +2,9 @@ TEST_OUTPUT: --- fail_compilation/ice11518.d(17): Error: class `ice11518.B` matches more than one template declaration: -fail_compilation/ice11518.d(12): `B(T : A!T)` -and -fail_compilation/ice11518.d(13): `B(T : A!T)` +fail_compilation/ice11518.d(12): `B(T : A!T)` +and: +fail_compilation/ice11518.d(13): `B(T : A!T)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d index 0886df61678..f500700f674 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d @@ -1,20 +1,22 @@ /* TEST_OUTPUT: --- -fail_compilation/ice11982.d(20): Error: basic type expected, not `scope` -fail_compilation/ice11982.d(20): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(20) -fail_compilation/ice11982.d(20): Error: basic type expected, not `}` -fail_compilation/ice11982.d(20): Error: missing `{ ... }` for function literal -fail_compilation/ice11982.d(20): Error: C style cast illegal, use `cast(funk)function _error_() +fail_compilation/ice11982.d(22): Error: basic type expected, not `scope` +fail_compilation/ice11982.d(22): Error: found `scope` when expecting `;` following expression +fail_compilation/ice11982.d(22): expression: `new _error_` +fail_compilation/ice11982.d(22): Error: basic type expected, not `}` +fail_compilation/ice11982.d(22): Error: missing `{ ... }` for function literal +fail_compilation/ice11982.d(22): Error: C style cast illegal, use `cast(funk)function _error_() { } ` -fail_compilation/ice11982.d(20): Error: found `}` when expecting `;` following statement `cast(funk)function _error_() +fail_compilation/ice11982.d(22): Error: found `}` when expecting `;` following expression +fail_compilation/ice11982.d(22): expression: `cast(funk)function _error_() { } -` on line fail_compilation/ice11982.d(20) -fail_compilation/ice11982.d(21): Error: matching `}` expected following compound statement, not `End of File` -fail_compilation/ice11982.d(20): unmatched `{` +` +fail_compilation/ice11982.d(23): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/ice11982.d(22): unmatched `{` --- */ void main() { new scope ( funk ) function } diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice8100.d b/gcc/testsuite/gdc.test/fail_compilation/ice8100.d index dc68cfcce2b..b8b3155b688 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice8100.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice8100.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/ice8100.d(10): Error: no property `Q` for type `ice8100.Bar!bool` -fail_compilation/ice8100.d(11): Error: template instance `ice8100.Foo!(Bar!bool)` error instantiating -fail_compilation/ice8100.d(12): instantiated from here: `Bar!bool` +fail_compilation/ice8100.d(11): Error: no property `Q` for type `ice8100.Bar!bool` +fail_compilation/ice8100.d(12): class `Bar` defined here +fail_compilation/ice8100.d(12): Error: template instance `ice8100.Foo!(Bar!bool)` error instantiating +fail_compilation/ice8100.d(13): instantiated from here: `Bar!bool` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue12652.d b/gcc/testsuite/gdc.test/fail_compilation/issue12652.d deleted file mode 100644 index 0ddd6b48b53..00000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/issue12652.d +++ /dev/null @@ -1,24 +0,0 @@ -/* -TEST_OUTPUT: ----- -fail_compilation/issue12652.d(18): Error: static initializations of associative arrays is not allowed. -fail_compilation/issue12652.d(18): associative arrays must be initialized at runtime: https://dlang.org/spec/hash-map.html#runtime_initialization ---- -*/ - -enum A -{ - x, - y, - z -} - -struct S -{ - string[A] t = [A.x : "aaa", A.y : "bbb"]; -} - -void main () -{ - S s; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue22682.d b/gcc/testsuite/gdc.test/fail_compilation/issue22682.d new file mode 100644 index 00000000000..80e8311b3a7 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/issue22682.d @@ -0,0 +1,18 @@ +/* TEST_OUTPUT: +--- +fail_compilation/issue22682.d(14): Error: `pragma(mangle)` must be attached to a declaration +fail_compilation/issue22682.d(15): Error: `pragma(mangle)` takes a single argument that must be a string literal +fail_compilation/issue22682.d(16): Error: `string` expected for pragma mangle argument, not `(0)` of type `int` +fail_compilation/issue22682.d(16): Error: `pragma(mangle)` takes a single argument that must be a string literal +fail_compilation/issue22682.d(17): Error: `pragma(mangle)` must be attached to a declaration +--- + */ +module issue22682; + +void main() +{ + pragma(mangle) {} + pragma(mangle) static int i0; + pragma(mangle, 0) static int i1; + pragma(mangle); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d index 0ad3f01156a..7fe2a537481 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d @@ -1,8 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/lexer1.d(30): Error: no identifier for declarator `x` -fail_compilation/lexer1.d(30): Error: declaration expected, not `"01 02 03"w` +fail_compilation/lexer1.d(30): Error: declaration expected, not `x"01 02 03"w` fail_compilation/lexer1.d(31): Error: declaration expected, not `2147483649U` fail_compilation/lexer1.d(32): Error: declaration expected, not `0.1` fail_compilation/lexer1.d(33): Error: declaration expected, not `0.1f` @@ -26,6 +25,7 @@ fail_compilation/lexer1.d(52): Error: escape octal sequence \400 is larger than fail_compilation/lexer1.d(53): Error: html entity requires 2 code units, use a string instead of a character --- */ + // https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html x"01 02 03"w; 0x80000001; diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer2.d b/gcc/testsuite/gdc.test/fail_compilation/lexer2.d index f895e644c44..f8fae85c9b3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lexer2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lexer2.d @@ -1,16 +1,16 @@ /* TEST_OUTPUT: --- -fail_compilation/lexer2.d(16): Error: semicolon expected following auto declaration, not `"123"` -fail_compilation/lexer2.d(16): Error: declaration expected, not `"123"` -fail_compilation/lexer2.d(17): Error: semicolon expected following auto declaration, not `"123G"` -fail_compilation/lexer2.d(17): Error: declaration expected, not `"123G"` +fail_compilation/lexer2.d(16): Error: odd number (3) of hex characters in hex string +fail_compilation/lexer2.d(17): Error: non-hex character 'G' in hex string fail_compilation/lexer2.d(18): Error: heredoc rest of line should be blank fail_compilation/lexer2.d(20): Error: unterminated delimited string constant starting at fail_compilation/lexer2.d(20) fail_compilation/lexer2.d(22): Error: semicolon expected following auto declaration, not `End of File` --- */ + + // https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html static s1 = x"123"; diff --git a/gcc/testsuite/gdc.test/fail_compilation/main.d b/gcc/testsuite/gdc.test/fail_compilation/main.d new file mode 100644 index 00000000000..42a8a43062f --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/main.d @@ -0,0 +1,9 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/main.d(9): Error: only one entry point `main`$?:windows=, `WinMain` or `DllMain`$ is allowed +fail_compilation/main.d(8): previously found `void main()` here +--- +*/ +void main() {} +void main(string[] args) {} diff --git a/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d b/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d new file mode 100644 index 00000000000..7f59183f2ce --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d @@ -0,0 +1,17 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/match_func_ptr.d(13): Error: cannot match delegate literal to function pointer type `void function()` +fail_compilation/match_func_ptr.d(14): Error: cannot match function literal to delegate type `void delegate()` +fail_compilation/match_func_ptr.d(15): Error: cannot infer parameter types from `int function()` +fail_compilation/match_func_ptr.d(16): Error: cannot infer parameter types from `int delegate(int, int)` +--- +*/ + +void main() +{ + void function() f = delegate {}; + void delegate() d = function {}; + int function() f2 = i => 2; + int delegate(int, int) d2 = i => 2; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d index 57706b59e41..9de436b0119 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d @@ -23,7 +23,8 @@ fail_compilation/misc_parser_err_cov1.d(40): Error: semicolon expected following fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected following `.`, not `+` fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`. fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;` -fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement `(__error) + 0` on line fail_compilation/misc_parser_err_cov1.d(41) +fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following expression +fail_compilation/misc_parser_err_cov1.d(41): expression: `(__error) + 0` fail_compilation/misc_parser_err_cov1.d(43): Error: matching `}` expected following compound statement, not `End of File` fail_compilation/misc_parser_err_cov1.d(33): unmatched `{` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d index 3bd7167acba..b53903ffbc0 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d @@ -43,10 +43,12 @@ fail_compilation/nogc3.d(35): Error: `@nogc` function `nogc3.testCall` cannot ca /* TEST_OUTPUT: --- -fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC -fail_compilation/nogc3.d(55): `nogc3.testClosure1.bar` closes over variable `x` at fail_compilation/nogc3.d(54) -fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC -fail_compilation/nogc3.d(67): `nogc3.testClosure3.bar` closes over variable `x` at fail_compilation/nogc3.d(66) +fail_compilation/nogc3.d(54): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC +fail_compilation/nogc3.d(57): function `nogc3.testClosure1.bar` closes over variable `x` +fail_compilation/nogc3.d(56): `x` declared here +fail_compilation/nogc3.d(66): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC +fail_compilation/nogc3.d(69): function `nogc3.testClosure3.bar` closes over variable `x` +fail_compilation/nogc3.d(68): `x` declared here --- */ @nogc auto testClosure1() @@ -73,10 +75,10 @@ fail_compilation/nogc3.d(67): `nogc3.testClosure3.bar` closes over variab /* TEST_OUTPUT: --- -fail_compilation/nogc3.d(85): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation -fail_compilation/nogc3.d(86): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation -fail_compilation/nogc3.d(92): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation -fail_compilation/nogc3.d(91): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation +fail_compilation/nogc3.d(87): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation +fail_compilation/nogc3.d(88): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation +fail_compilation/nogc3.d(94): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation +fail_compilation/nogc3.d(93): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation --- */ int[] foo13702(bool b) @nogc diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d new file mode 100644 index 00000000000..c72bade8fa5 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d @@ -0,0 +1,16 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/noreturn_expr.d(10): Error: type `noreturn` is not an expression +--- +*/ + +int v(e)() +{ + return e + 0; +} + +int main() +{ + return v!(noreturn)(); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d new file mode 100644 index 00000000000..f5e0054823b --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d @@ -0,0 +1,14 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/noreturn_expr2.d(8): Error: cannot cast `noreturn` to `int` at compile time +--- +*/ + +enum E {e1 = 1, e2 = 2, illegal = noreturn} + +void main() +{ + E e; + e = E.illegal; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d b/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d new file mode 100644 index 00000000000..3065bdb8e79 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d @@ -0,0 +1,20 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/operator_undefined.d(19): Error: operator `-` is not defined for `toJson(2)` of type `Json` +--- +*/ + +import std.stdio; + +struct Json +{ + //int opUnary(string op : "-")(); +} + +Json toJson(int); + +void main() +{ + auto x = -2.toJson; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/parseStc.d b/gcc/testsuite/gdc.test/fail_compilation/parseStc.d index d13006db0ab..9a24741689e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/parseStc.d +++ b/gcc/testsuite/gdc.test/fail_compilation/parseStc.d @@ -3,12 +3,12 @@ TEST_OUTPUT: --- fail_compilation/parseStc.d(12): Error: missing closing `)` after `if (x` fail_compilation/parseStc.d(12): Error: use `{ }` for an empty statement, not `;` -fail_compilation/parseStc.d(12): Error: found `)` when expecting `;` following statement `1` on line fail_compilation/parseStc.d(12) +fail_compilation/parseStc.d(12): Error: found `)` when expecting `;` following expression +fail_compilation/parseStc.d(12): expression: `1` fail_compilation/parseStc.d(13): Error: redundant attribute `const` --- */ -void test1() -{ +void test1() { if (x; 1) {} if (const const auto x = 1) {} } diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d index c08747fa7e3..ce983c01fc6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d @@ -55,7 +55,7 @@ void test2(scope int* p, int[] a ...) @safe TEST_OUTPUT: --- fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closure for `onReceive()` with the GC -fail_compilation/retscope.d(77): `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this` at fail_compilation/retscope.d(75) +fail_compilation/retscope.d(77): delegate `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/skip.d b/gcc/testsuite/gdc.test/fail_compilation/skip.d index 0f3a9ec7e56..6207a106ddb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/skip.d +++ b/gcc/testsuite/gdc.test/fail_compilation/skip.d @@ -2,8 +2,10 @@ * REQUIRED_ARGS: -de * TEST_OUTPUT: --- -fail_compilation/skip.d(21): Error: `switch` skips declaration of `with` temporary at fail_compilation/skip.d(26) -fail_compilation/skip.d(43): Error: `switch` skips declaration of variable `skip.test14532.n` at fail_compilation/skip.d(45) +fail_compilation/skip.d(23): Error: `switch` skips declaration of `with` temporary +fail_compilation/skip.d(28): declared here +fail_compilation/skip.d(45): Error: `switch` skips declaration of variable `skip.test14532.n` +fail_compilation/skip.d(47): declared here --- */ // https://issues.dlang.org/show_bug.cgi?id=10524 diff --git a/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d b/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d new file mode 100644 index 00000000000..7141fb16ba8 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d @@ -0,0 +1,48 @@ +/* +REQUIRED_ARGS: -verrors=context +TEST_OUTPUT: +--- +fail_compilation/switch_skip.d(22): Error: `switch` skips declaration of variable `switch_skip.test3.j` + switch (i) + ^ +fail_compilation/switch_skip.d(26): declared here + int j; + ^ +fail_compilation/switch_skip.d(39): Error: `switch` skips declaration of variable `switch_skip.test.z` + final switch(n) + ^ +fail_compilation/switch_skip.d(41): declared here + int z = 5; + ^ +--- +*/ + +void test3(int i) +{ + switch (i) + { + case 1: + { + int j; + case 2: + ++j; + break; + } + default: + break; + } +} + +// https://issues.dlang.org/show_bug.cgi?id=18858 +int test(int n) +{ + final switch(n) + { + int z = 5; + enum e = 6; + + case 1: + int y = 2; + return y; + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/switches.d b/gcc/testsuite/gdc.test/fail_compilation/switches.d index b53fb4c6375..06652c8cf34 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/switches.d +++ b/gcc/testsuite/gdc.test/fail_compilation/switches.d @@ -1,13 +1,11 @@ -/************************************************************/ - /* TEST_OUTPUT: --- -fail_compilation/switches.d(105): Error: `case 2` not found +fail_compilation/switches.d(14): Error: `case 2` not found +fail_compilation/switches.d(25): Error: no `case` statement following `goto case;` --- */ -#line 100 void test1(int i) { switch (i) @@ -19,16 +17,6 @@ void test1(int i) } } -/************************************************************/ - -/* -TEST_OUTPUT: ---- -fail_compilation/switches.d(205): Error: no `case` statement following `goto case;` ---- -*/ - -#line 200 void test2(int i) { switch (i) @@ -39,55 +27,3 @@ void test2(int i) break; } } - -/************************************************************/ - -/* -TEST_OUTPUT: ---- -fail_compilation/switches.d(302): Error: `switch` skips declaration of variable `switches.test3.j` at fail_compilation/switches.d(306) ---- -*/ - -#line 300 -void test3(int i) -{ - switch (i) - { - case 1: - { - int j; - case 2: - ++j; - break; - } - default: - break; - } -} - - -/************************************************************/ - -/* -TEST_OUTPUT: ---- -fail_compilation/switches.d(404): Error: `switch` skips declaration of variable `switches.test.z` at fail_compilation/switches.d(406) ---- -*/ - -#line 400 -// https://issues.dlang.org/show_bug.cgi?id=18858 - -int test(int n) -{ - final switch(n) - { - int z = 5; - enum e = 6; - - case 1: - int y = 2; - return y; - } -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test13536.d b/gcc/testsuite/gdc.test/fail_compilation/test13536.d index 4a4bb2672be..eff807ab5a3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test13536.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test13536.d @@ -1,9 +1,8 @@ -/* REQUIRED_ARGS: -wo +/* TEST_OUTPUT: --- -fail_compilation/test13536.d(23): Error: field `U.sysDg` cannot access pointers in `@safe` code that overlap other fields -fail_compilation/test13536.d(23): Warning: address of variable `s` assigned to `u` with longer lifetime -fail_compilation/test13536.d(24): Error: field `U.safeDg` cannot access pointers in `@safe` code that overlap other fields +fail_compilation/test13536.d(22): Error: field `U.sysDg` cannot access pointers in `@safe` code that overlap other fields +fail_compilation/test13536.d(23): Error: field `U.safeDg` cannot access pointers in `@safe` code that overlap other fields --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15785.d b/gcc/testsuite/gdc.test/fail_compilation/test15785.d index 594b5d35e75..fc61e3db070 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15785.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15785.d @@ -2,8 +2,9 @@ /* TEST_OUTPUT: --- -fail_compilation/test15785.d(16): Error: no property `foo` for `super` of type `imports.test15785.Base` -fail_compilation/test15785.d(17): Error: undefined identifier `bar` +fail_compilation/test15785.d(17): Error: no property `foo` for `super` of type `imports.test15785.Base` +fail_compilation/imports/test15785.d(3): class `Base` defined here +fail_compilation/test15785.d(18): Error: undefined identifier `bar` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15897.d b/gcc/testsuite/gdc.test/fail_compilation/test15897.d index db554cb9e15..c911263718f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15897.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15897.d @@ -3,7 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/test15897.d(19): Error: no property `create` for `cat` of type `imports.test15897.Cat` +fail_compilation/test15897.d(20): Error: no property `create` for `cat` of type `imports.test15897.Cat` +fail_compilation/imports/test15897.d(4): class `Cat` defined here --- */ module test15897; diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d index bdaae94a6ca..0bd052ca6db 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d @@ -3,6 +3,7 @@ --- fail_compilation/test16188.d(101): Error: no property `name` for `Where()` of type `test16188.Where` fail_compilation/test16188.d(101): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message +fail_compilation/test16188.d(103): struct `Where` defined here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16193.d b/gcc/testsuite/gdc.test/fail_compilation/test16193.d index 6c80471c77b..39399cf01d8 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test16193.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test16193.d @@ -2,8 +2,9 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC -fail_compilation/test16193.d(40): `test16193.abc.__foreachbody2` closes over variable `x` at fail_compilation/test16193.d(39) +fail_compilation/test16193.d(39): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC +fail_compilation/test16193.d(41): delegate `test16193.abc.__foreachbody2` closes over variable `x` +fail_compilation/test16193.d(40): `x` declared here --- */ //fail_compilation/test16193.d(22): To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope` diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16365.d b/gcc/testsuite/gdc.test/fail_compilation/test16365.d index 4d49365659c..5bfa5f8dba6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test16365.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test16365.d @@ -1,10 +1,9 @@ -/* REQUIRED_ARGS: -wo +/* TEST_OUTPUT: --- -fail_compilation/test16365.d(21): Error: `this` reference necessary to take address of member `f1` in `@safe` function `main` -fail_compilation/test16365.d(23): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe` -fail_compilation/test16365.d(27): Warning: address of variable `s` assigned to `dg` with longer lifetime -fail_compilation/test16365.d(28): Error: `dg.funcptr` cannot be used in `@safe` code +fail_compilation/test16365.d(20): Error: `this` reference necessary to take address of member `f1` in `@safe` function `main` +fail_compilation/test16365.d(22): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe` +fail_compilation/test16365.d(27): Error: `dg.funcptr` cannot be used in `@safe` code --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d index f523337037a..8ab8739d978 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d @@ -1,9 +1,10 @@ /* REQUIRED_ARGS: -verrors=spec TEST_OUTPUT: --- -(spec:1) fail_compilation/test17380spec.d(14): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler` -(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128` -fail_compilation/test17380spec.d(14): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler` +(spec:1) fail_compilation/test17380spec.d(15): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler` +(spec:1) fail_compilation/test17380spec.d(15): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128` +(spec:1) fail_compilation/test17380spec.d(20): struct `Uint128` defined here +fail_compilation/test17380spec.d(15): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20655.d b/gcc/testsuite/gdc.test/fail_compilation/test20655.d new file mode 100644 index 00000000000..c3bb70af492 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test20655.d @@ -0,0 +1,32 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/test20655.d(29): Deprecation: `@safe` function `g` calling `f1` +fail_compilation/test20655.d(24): which wouldn't be `@safe` because of: +fail_compilation/test20655.d(24): field `U.s` cannot access pointers in `@safe` code that overlap other fields +fail_compilation/test20655.d(30): Deprecation: `@safe` function `g` calling `f2` +fail_compilation/test20655.d(25): which wouldn't be `@safe` because of: +fail_compilation/test20655.d(25): field `U.s` cannot access pointers in `@safe` code that overlap other fields +fail_compilation/test20655.d(31): Deprecation: `@safe` function `g` calling `f3` +fail_compilation/test20655.d(28): which wouldn't be `@safe` because of: +fail_compilation/test20655.d(28): field `U.s` cannot access pointers in `@safe` code that overlap other fields +--- +*/ + +union U +{ + string s; + int x; +} +U u; + +auto f1() { auto s = u.s; } /* Should be inferred as @system. */ +void f2()() { auto s = u.s; } /* ditto */ +void g() @safe +{ + void f3() { auto s = u.s; } /* ditto */ + f1(); /* Should be rejected with error "cannot call @system function". */ + f2(); /* ditto */ + f3(); /* ditto */ +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21353.d b/gcc/testsuite/gdc.test/fail_compilation/test21353.d index 55c84f996a1..14fa26dcce7 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test21353.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test21353.d @@ -2,11 +2,14 @@ EXTRA_FILES: imports/imp21353.d TEST_OUTPUT: --- -fail_compilation/test21353.d(19): Error: no property `A` for type `imports.imp21353.B` -fail_compilation/test21353.d(20): Error: no property `A` for type `imports.imp21353.B` -fail_compilation/test21353.d(21): Error: no property `A` for type `imports.imp21353.B` -fail_compilation/test21353.d(23): Error: undefined identifier `P` in module `imports.imp21353` -fail_compilation/test21353.d(24): Error: undefined identifier `P` in module `imports.imp21353` +fail_compilation/test21353.d(22): Error: no property `A` for type `imports.imp21353.B` +fail_compilation/imports/imp21353.d(5): struct `B` defined here +fail_compilation/test21353.d(23): Error: no property `A` for type `imports.imp21353.B` +fail_compilation/imports/imp21353.d(5): struct `B` defined here +fail_compilation/test21353.d(24): Error: no property `A` for type `imports.imp21353.B` +fail_compilation/imports/imp21353.d(5): struct `B` defined here +fail_compilation/test21353.d(26): Error: undefined identifier `P` in module `imports.imp21353` +fail_compilation/test21353.d(27): Error: undefined identifier `P` in module `imports.imp21353` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21912.d b/gcc/testsuite/gdc.test/fail_compilation/test21912.d index 9b07eba0df6..f8bcb40b5df 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test21912.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test21912.d @@ -2,14 +2,18 @@ PERMUTE_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC -fail_compilation/test21912.d(26): `test21912.escapeParam.__lambda2` closes over variable `i` at fail_compilation/test21912.d(24) -fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC -fail_compilation/test21912.d(31): `test21912.escapeAssign.__lambda3` closes over variable `i` at fail_compilation/test21912.d(29) -fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC -fail_compilation/test21912.d(42): `test21912.escapeAssignRef.__lambda3` closes over variable `i` at fail_compilation/test21912.d(40) -fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC -fail_compilation/test21912.d(53): `test21912.escapeParamInferred.__lambda2` closes over variable `i` at fail_compilation/test21912.d(51) +fail_compilation/test21912.d(28): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC +fail_compilation/test21912.d(30): delegate `test21912.escapeParam.__lambda2` closes over variable `i` +fail_compilation/test21912.d(28): `i` declared here +fail_compilation/test21912.d(33): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC +fail_compilation/test21912.d(35): delegate `test21912.escapeAssign.__lambda3` closes over variable `i` +fail_compilation/test21912.d(33): `i` declared here +fail_compilation/test21912.d(44): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC +fail_compilation/test21912.d(46): delegate `test21912.escapeAssignRef.__lambda3` closes over variable `i` +fail_compilation/test21912.d(44): `i` declared here +fail_compilation/test21912.d(55): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC +fail_compilation/test21912.d(57): delegate `test21912.escapeParamInferred.__lambda2` closes over variable `i` +fail_compilation/test21912.d(55): `i` declared here --- */ @nogc: diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22329.d b/gcc/testsuite/gdc.test/fail_compilation/test22329.d index 237f9c76667..25c83f5142d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test22329.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test22329.d @@ -4,8 +4,9 @@ TEST_OUTPUT: --- fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo` +fail_compilation/test22329.d(13): struct `Foo` defined here fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int` -fail_compilation/test22329.d(20): Error: template instance `imp22329.func!(Foo)` error instantiating +fail_compilation/test22329.d(21): Error: template instance `imp22329.func!(Foo)` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23112.d b/gcc/testsuite/gdc.test/fail_compilation/test23112.d index 325d89bd6c2..9bbab80e48c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test23112.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test23112.d @@ -2,7 +2,8 @@ TEST_OUTPUT: --- fail_compilation/test23112.d(106): Error: function `test23112.bar` is `@nogc` yet allocates closure for `bar()` with the GC -fail_compilation/test23112.d(108): `test23112.bar.f` closes over variable `a` at fail_compilation/test23112.d(106) +fail_compilation/test23112.d(108): function `test23112.bar.f` closes over variable `a` +fail_compilation/test23112.d(106): `a` declared here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24015.d b/gcc/testsuite/gdc.test/fail_compilation/test24015.d new file mode 100644 index 00000000000..c9bc42e055e --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24015.d @@ -0,0 +1,20 @@ +/* REQUIRED_ARGS: -preview=dip1000 + * TEST_OUTPUT: +--- +fail_compilation/test24015.d(19): Error: scope variable `v` assigned to non-scope parameter `...` calling `jer` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24105 + +@safe: + +extern (C) void ben(int i, scope ...); + +extern (C) void jer(int i, ...); + +void bar(scope const char* v) +{ + ben(3, v); + jer(3, v); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24036.d b/gcc/testsuite/gdc.test/fail_compilation/test24036.d new file mode 100644 index 00000000000..da529f90ee9 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24036.d @@ -0,0 +1,21 @@ +/* +https://issues.dlang.org/show_bug.cgi?id=24036 +Issue 24036 - assert message in CTFE becomes `['m', 'e', 's', 's', 'a', 'g', 'e'][0..7]` if produced using std.format.format + +TEST_OUTPUT: +--- +fail_compilation/test24036.d(19): Error: message +fail_compilation/test24036.d(21): called from here: `(*function () pure nothrow @safe => 42)()` +--- +*/ + +auto format() +{ + return ['m', 'e', 's', 's', 'a', 'g', 'e'][0 .. 7]; +} + +immutable ctfeThing = () +{ + assert(0, format()); + return 42; +}(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24065.d b/gcc/testsuite/gdc.test/fail_compilation/test24065.d new file mode 100644 index 00000000000..9e4ebbf4d16 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24065.d @@ -0,0 +1,18 @@ +// https://issues.dlang.org/show_bug.cgi?id=24065 + +/* +TEST_OUTPUT: +--- +fail_compilation/test24065.d(12): Error: string expected as argument of __traits `getTargetInfo` instead of `int` +fail_compilation/test24065.d(15): Error: string expected as argument of __traits `getTargetInfo` instead of `foo` +fail_compilation/test24065.d(18): Error: string expected as argument of __traits `getTargetInfo` instead of `e` +--- +*/ + +auto s1 = __traits(getTargetInfo, int); + +void foo() {} +auto s2 = __traits(getTargetInfo, foo); + +enum e; +auto s3 = __traits(getTargetInfo, e); diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24084.d b/gcc/testsuite/gdc.test/fail_compilation/test24084.d new file mode 100644 index 00000000000..51de15ea21a --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24084.d @@ -0,0 +1,28 @@ +/* REQUIRED_ARGS: -nothrow + * TEST_OUTPUT: +--- +fail_compilation/test24084.d(110): Error: cannot use `throw` statements with -nothrow +fail_compilation/test24084.d(112): Error: cannot use try-catch statements with -nothrow +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=24084 + +#line 100 + +struct S +{ + int x; + ~this() { } +} + +void xyzzy() +{ + S s; + throw new Exception("xx"); + + try + { + int y; + } catch (Exception) { } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24110.d b/gcc/testsuite/gdc.test/fail_compilation/test24110.d new file mode 100644 index 00000000000..acf7788c6e0 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24110.d @@ -0,0 +1,12 @@ +// https://issues.dlang.org/show_bug.cgi?id=24110 + +/* +TEST_OUTPUT: +--- +fail_compilation/test24110.d(12): Error: static assert: `__traits(compiles, __error)` is false +--- +*/ + +struct S { int x; } +alias T = shared S; +static assert(__traits(compiles, (T[] a, T[] b) => a < b)); diff --git a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d index 9203685fdc8..8d6c736e5af 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d +++ b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d @@ -48,9 +48,9 @@ void testSameAttr() @system TEST_OUTPUT: --- fail_compilation/testOpApply.d(217): Error: `sa.opApply` matches more than one declaration: -`fail_compilation/testOpApply.d(203)`: `int(int delegate(int) dg)` +fail_compilation/testOpApply.d(203): `int(int delegate(int) dg)` and: -`fail_compilation/testOpApply.d(208)`: `int(int delegate(string) dg)` +fail_compilation/testOpApply.d(208): `int(int delegate(string) dg)` fail_compilation/testOpApply.d(217): Error: cannot uniquely infer `foreach` argument types --- +/ @@ -79,9 +79,9 @@ void testDifferentTypes() TEST_OUTPUT: --- fail_compilation/testOpApply.d(317): Error: `sa.opApply` matches more than one declaration: -`fail_compilation/testOpApply.d(303)`: `int(int delegate(int) dg)` +fail_compilation/testOpApply.d(303): `int(int delegate(int) dg)` and: -`fail_compilation/testOpApply.d(308)`: `int(int delegate(long) dg)` +fail_compilation/testOpApply.d(308): `int(int delegate(long) dg)` fail_compilation/testOpApply.d(317): Error: cannot uniquely infer `foreach` argument types --- +/ @@ -112,9 +112,9 @@ See https://issues.dlang.org/show_bug.cgi?id=21683 TEST_OUTPUT: --- fail_compilation/testOpApply.d(420): Error: `sa.opApply` matches more than one declaration: -`fail_compilation/testOpApply.d(404)`: `int(int delegate(int) dg)` +fail_compilation/testOpApply.d(404): `int(int delegate(int) dg)` and: -`fail_compilation/testOpApply.d(410)`: `int(int delegate(ref int) dg)` +fail_compilation/testOpApply.d(410): `int(int delegate(ref int) dg)` fail_compilation/testOpApply.d(420): Error: cannot uniquely infer `foreach` argument types --- +/ @@ -146,9 +146,9 @@ void testDifferentQualifiers() TEST_OUTPUT: --- fail_compilation/testOpApply.d(504): Error: `sa.opApply` matches more than one declaration: -`fail_compilation/testOpApply.d(404)`: `int(int delegate(int) dg)` +fail_compilation/testOpApply.d(404): `int(int delegate(int) dg)` and: -`fail_compilation/testOpApply.d(410)`: `int(int delegate(ref int) dg)` +fail_compilation/testOpApply.d(410): `int(int delegate(ref int) dg)` fail_compilation/testOpApply.d(504): Error: cannot uniquely infer `foreach` argument types --- +/ diff --git a/gcc/testsuite/gdc.test/fail_compilation/testsemi.d b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d index fc9bc651070..77601a5e446 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/testsemi.d +++ b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d @@ -8,7 +8,8 @@ fail_compilation/testsemi.d(117): Error: found `int` when expecting `;` followin fail_compilation/testsemi.d(117): Error: no identifier for declarator `x` fail_compilation/testsemi.d(123): Error: found `int` when expecting `;` following mixin fail_compilation/testsemi.d(129): Error: found `int` when expecting `;` following `import` Expression -fail_compilation/testsemi.d(131): Error: `}` expected following members in `class` declaration at fail_compilation/testsemi.d(112) +fail_compilation/testsemi.d(131): Error: `}` expected following members in `class` declaration +fail_compilation/testsemi.d(112): class `C` starts here --- */ diff --git a/gcc/testsuite/gdc.test/runnable/staticaa.d b/gcc/testsuite/gdc.test/runnable/staticaa.d new file mode 100644 index 00000000000..38678c92901 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/staticaa.d @@ -0,0 +1,126 @@ +// https://issues.dlang.org/show_bug.cgi?id=23103 +// Issue 23103 - static initialization of associative arrays is not implemented + +nothrow @safe: + +///////////////////////////////////////////// + +int[int] globalAA = [1: 10, 2: 20]; + +void testSimple() +{ + assert(globalAA[1] == 10); + assert(globalAA[2] == 20); + assert(!(30 in globalAA)); + + foreach (i; 0 .. 1000) + { + globalAA[i] = i * 10; + assert(globalAA[i] == i * 10); + } +} + +///////////////////////////////////////////// + +struct Composit +{ + string[string][] aa; +} + +auto getAA() { return ["a": "A"]; } + +immutable Composit compositAA = Composit([getAA(), ["b": "B"]]); + +void testComposit() pure +{ + assert(compositAA.aa[0]["a"] == "A"); + assert(compositAA.aa[1]["b"] == "B"); +} + +///////////////////////////////////////////// + +struct Destructing +{ + int v; + static int destructorsCalled = 0; + + ~this() nothrow + { + // FIXME: the lowering to newaa calls the destructor at CTFE, so we can't modify globals in it + if (!__ctfe) + destructorsCalled++; + } +} + +struct Key +{ + int v; + bool opEquals(ref const Key o) const { return v == o.v; } + size_t toHash() const { return v; } +} + +Destructing[Key] dAa = [Key(1): Destructing(10), Key(2): Destructing(20)]; + +void testDestructor() +{ + assert(dAa[Key(1)].v == 10); + assert(dAa[Key(2)].v == 20); + assert(Destructing.destructorsCalled == 0); + dAa[Key(1)] = Destructing(100); + assert(dAa[Key(1)].v == 100); + assert(Destructing.destructorsCalled == 1); +} + +///////////////////////////////////////////// + +enum A +{ + x, y, z +} + +struct S +{ + string[A] t = [A.x : "A.x", A.y : "A.y"]; +} + +void testStructInit() +{ + S s; + assert(s.t[A.x] == "A.x"); + assert(s.t[A.y] == "A.y"); +} + +///////////////////////////////////////////// + +class C +{ + string[int] t = [0 : "zero"]; +} + +void testClassInit() +{ + C c = new C(); + assert(c.t[0] == "zero"); +} + +///////////////////////////////////////////// + +immutable(string)[immutable(int)] immutableAA = [1: "one", 2: "two"]; + +void testImmutable() +{ + assert(immutableAA[1] == "one"); + assert(immutableAA[2] == "two"); +} + +///////////////////////////////////////////// + +void main() +{ + testSimple(); + testComposit(); + testDestructor(); + testStructInit(); + testClassInit(); + testImmutable(); +} diff --git a/gcc/testsuite/gdc.test/runnable/test24078.d b/gcc/testsuite/gdc.test/runnable/test24078.d new file mode 100644 index 00000000000..99d74400cf8 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test24078.d @@ -0,0 +1,6 @@ +//https://issues.dlang.org/show_bug.cgi?id=24078 + +void main() +{ + assert(["c"] ~ "a" ~ "b" == ["c", "a", "b"]); +} diff --git a/gcc/testsuite/gdc.test/runnable/test24139.d b/gcc/testsuite/gdc.test/runnable/test24139.d new file mode 100644 index 00000000000..af6215dd2ac --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test24139.d @@ -0,0 +1,25 @@ +// https://issues.dlang.org/show_bug.cgi?id=24139 + +struct S1 +{ + int x; + extern(C++) ~this() { assert(&this == s1); } +} + +extern(C++) struct S2 +{ + int x; + ~this() { assert(&this == s2); } +} + +S1* s1; +S2* s2; + +void main() +{ + s1 = new S1; + s2 = new S2; + + typeid(S1).destroy(s1); + typeid(S2).destroy(s2); +} diff --git a/gcc/testsuite/lib/gdc-utils.exp b/gcc/testsuite/lib/gdc-utils.exp index 25574cb8ec7..cbd25e9b9e3 100644 --- a/gcc/testsuite/lib/gdc-utils.exp +++ b/gcc/testsuite/lib/gdc-utils.exp @@ -163,6 +163,9 @@ proc gdc-convert-args { args } { upvar 2 compilable_do_what compilable_do_what set compilable_do_what "compile" + } elseif [string match "-nothrow" $arg] { + lappend out "-fno-exceptions" + } elseif [string match "-vgc" $arg] { lappend out "-ftransition=nogc" diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index dc267787cab..d5dfe0d0edd 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -4574d1728d1f7e52ff40e6733b8c39889d128349 +f9efc98fd7954741333f72c6a50af273f3863a1a The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index 832a0524ab3..0aefbf22ca6 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -186,9 +186,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \ core/internal/gc/os.d core/internal/gc/pooltable.d \ core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \ - core/internal/moving.d core/internal/parseoptions.d \ - core/internal/postblit.d core/internal/qsort.d \ - core/internal/spinlock.d core/internal/string.d \ + core/internal/moving.d core/internal/newaa.d \ + core/internal/parseoptions.d core/internal/postblit.d \ + core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \ core/internal/switch_.d core/internal/traits.d core/internal/utf.d \ core/internal/util/array.d core/internal/util/math.d core/lifetime.d \ core/math.d core/memory.d core/runtime.d core/simd.d \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 61a2a770888..39066dd33cc 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -213,21 +213,21 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ core/internal/gc/impl/proto/gc.lo core/internal/gc/os.lo \ core/internal/gc/pooltable.lo core/internal/gc/proxy.lo \ core/internal/hash.lo core/internal/lifetime.lo \ - core/internal/moving.lo core/internal/parseoptions.lo \ - core/internal/postblit.lo core/internal/qsort.lo \ - core/internal/spinlock.lo core/internal/string.lo \ - core/internal/switch_.lo core/internal/traits.lo \ - core/internal/utf.lo core/internal/util/array.lo \ - core/internal/util/math.lo core/lifetime.lo core/math.lo \ - core/memory.lo core/runtime.lo core/simd.lo \ - core/stdc/assert_.lo core/stdc/complex.lo core/stdc/config.lo \ - core/stdc/ctype.lo core/stdc/errno.lo core/stdc/fenv.lo \ - core/stdc/float_.lo core/stdc/inttypes.lo core/stdc/limits.lo \ - core/stdc/locale.lo core/stdc/math.lo core/stdc/signal.lo \ - core/stdc/stdarg.lo core/stdc/stddef.lo core/stdc/stdint.lo \ - core/stdc/stdio.lo core/stdc/stdlib.lo core/stdc/string.lo \ - core/stdc/tgmath.lo core/stdc/time.lo core/stdc/wchar_.lo \ - core/stdc/wctype.lo core/sync/barrier.lo \ + core/internal/moving.lo core/internal/newaa.lo \ + core/internal/parseoptions.lo core/internal/postblit.lo \ + core/internal/qsort.lo core/internal/spinlock.lo \ + core/internal/string.lo core/internal/switch_.lo \ + core/internal/traits.lo core/internal/utf.lo \ + core/internal/util/array.lo core/internal/util/math.lo \ + core/lifetime.lo core/math.lo core/memory.lo core/runtime.lo \ + core/simd.lo core/stdc/assert_.lo core/stdc/complex.lo \ + core/stdc/config.lo core/stdc/ctype.lo core/stdc/errno.lo \ + core/stdc/fenv.lo core/stdc/float_.lo core/stdc/inttypes.lo \ + core/stdc/limits.lo core/stdc/locale.lo core/stdc/math.lo \ + core/stdc/signal.lo core/stdc/stdarg.lo core/stdc/stddef.lo \ + core/stdc/stdint.lo core/stdc/stdio.lo core/stdc/stdlib.lo \ + core/stdc/string.lo core/stdc/tgmath.lo core/stdc/time.lo \ + core/stdc/wchar_.lo core/stdc/wctype.lo core/sync/barrier.lo \ core/sync/condition.lo core/sync/config.lo core/sync/event.lo \ core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \ core/sync/rwmutex.lo core/sync/semaphore.lo \ @@ -859,9 +859,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \ core/internal/gc/os.d core/internal/gc/pooltable.d \ core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \ - core/internal/moving.d core/internal/parseoptions.d \ - core/internal/postblit.d core/internal/qsort.d \ - core/internal/spinlock.d core/internal/string.d \ + core/internal/moving.d core/internal/newaa.d \ + core/internal/parseoptions.d core/internal/postblit.d \ + core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \ core/internal/switch_.d core/internal/traits.d core/internal/utf.d \ core/internal/util/array.d core/internal/util/math.d core/lifetime.d \ core/math.d core/memory.d core/runtime.d core/simd.d \ @@ -1268,6 +1268,7 @@ core/internal/gc/proxy.lo: core/internal/gc/$(am__dirstamp) core/internal/hash.lo: core/internal/$(am__dirstamp) core/internal/lifetime.lo: core/internal/$(am__dirstamp) core/internal/moving.lo: core/internal/$(am__dirstamp) +core/internal/newaa.lo: core/internal/$(am__dirstamp) core/internal/parseoptions.lo: core/internal/$(am__dirstamp) core/internal/postblit.lo: core/internal/$(am__dirstamp) core/internal/qsort.lo: core/internal/$(am__dirstamp) diff --git a/libphobos/libdruntime/core/internal/newaa.d b/libphobos/libdruntime/core/internal/newaa.d new file mode 100644 index 00000000000..314f2554103 --- /dev/null +++ b/libphobos/libdruntime/core/internal/newaa.d @@ -0,0 +1,144 @@ +/** + Turn an Associative Array into a binary compatible struct for static initialization. + + This does not implement all the pieces of + the associative array type in druntime, just enough to create an AA from an + existing range of key/value pairs. + + Copyright: Copyright Digital Mars 2000 - 2015, Steven Schveighoffer 2022. + License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). + Authors: Martin Nowak, Steven Schveighoffer +*/ +module core.internal.newaa; + +import core.memory; + +// grow threshold +private enum GROW_NUM = 4; +private enum GROW_DEN = 5; +// shrink threshold +private enum SHRINK_NUM = 1; +private enum SHRINK_DEN = 8; +// grow factor +private enum GROW_FAC = 4; +// growing the AA doubles it's size, so the shrink threshold must be +// smaller than half the grow threshold to have a hysteresis +static assert(GROW_FAC * SHRINK_NUM * GROW_DEN < GROW_NUM * SHRINK_DEN); +// initial load factor (for literals), mean of both thresholds +private enum INIT_NUM = (GROW_DEN * SHRINK_NUM + GROW_NUM * SHRINK_DEN) / 2; +private enum INIT_DEN = SHRINK_DEN * GROW_DEN; + +private enum INIT_NUM_BUCKETS = 8; +// magic hash constants to distinguish empty, deleted, and filled buckets +private enum HASH_EMPTY = 0; +private enum HASH_FILLED_MARK = size_t(1) << 8 * size_t.sizeof - 1; + +private struct Bucket +{ + size_t hash; + void *entry; +} + +struct Impl +{ + Bucket[] buckets; + uint used; + uint deleted; + TypeInfo_Struct entryTI; + uint firstUsed; + immutable uint keysz; + immutable uint valsz; + immutable uint valoff; + Flags flags; + + enum Flags : ubyte + { + none = 0x0, + keyHasPostblit = 0x1, + hasPointers = 0x2, + } +} + +private struct AAShell +{ + Impl *impl; +} + +private size_t mix(size_t h) @safe pure nothrow @nogc +{ + // final mix function of MurmurHash2 + enum m = 0x5bd1e995; + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} + +struct Entry(K, V) +{ + /*const*/ K key; // this really should be const, but legacy issues. + V value; +} + + +// create a binary-compatible AA structure that can be used directly as an +// associative array. +AAShell makeAA(K, V)(V[K] src) +{ + immutable srclen = src.length; + assert(srclen <= uint.max); + alias E = Entry!(K, V); + if (srclen == 0) + return AAShell.init; + // first, determine the size that would be used if we grew the bucket list + // one element at a time using the standard AA algorithm. + size_t dim = INIT_NUM_BUCKETS; + while (srclen * GROW_DEN > dim * GROW_NUM) + dim = dim * GROW_FAC; + + Bucket[] buckets; + // Allocate and fill the buckets + if (__ctfe) + buckets = new Bucket[dim]; + else + assert(0); + + assert(buckets.length >= dim); + + immutable mask = dim - 1; + assert((dim & mask) == 0); // must be a power of 2 + + Bucket* findSlotInsert(immutable size_t hash) + { + for (size_t i = hash & mask, j = 1;; ++j) + { + if (buckets[i].hash == HASH_EMPTY) + return &buckets[i]; + i = (i + j) & mask; + } + } + + uint firstUsed = cast(uint) buckets.length; + foreach (k, v; src) + { + immutable h = hashOf(k).mix | HASH_FILLED_MARK; + auto location = findSlotInsert(h); + immutable nfu = cast(uint) (location - &buckets[0]); + if (nfu < firstUsed) + firstUsed = nfu; + *location = Bucket(h, new E(k, v)); + } + + enum flags = () { + import core.internal.traits; + Impl.Flags flags; + static if (__traits(hasPostblit, K)) + flags |= flags.keyHasPostblit; + static if (hasIndirections!E) + flags |= flags.hasPointers; + return flags; + } (); + // return the new implementation + return AAShell(new Impl(buckets, cast(uint)srclen, 0, typeid(E), firstUsed, + K.sizeof, V.sizeof, E.value.offsetof, flags)); +} diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d index 2666c952992..76b32b44de1 100644 --- a/libphobos/libdruntime/core/stdc/math.d +++ b/libphobos/libdruntime/core/stdc/math.d @@ -4129,7 +4129,18 @@ else version (CRuntime_UClibc) /// pure float modff(float value, float* iptr); /// - extern(D) pure real modfl(real value, real *iptr) { return modf(cast(double) value, cast(double*) iptr); } + extern(D) pure real modfl(real value, real *iptr) + { + static if (double.sizeof == real.sizeof) + return modf(cast(double) value, cast(double*) iptr); + else + { + double i; + double r = modf(cast(double) value, &i); + *iptr = i; + return r; + } + } /// double scalbn(double x, int n); diff --git a/libphobos/libdruntime/core/stdcpp/string.d b/libphobos/libdruntime/core/stdcpp/string.d index defbd8330eb..722b82fe418 100644 --- a/libphobos/libdruntime/core/stdcpp/string.d +++ b/libphobos/libdruntime/core/stdcpp/string.d @@ -155,7 +155,7 @@ extern(D): /// alias opDollar = length; /// - bool empty() const nothrow @safe { return size() == 0; } + bool empty() const nothrow @trusted { return size() == 0; } /// size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const pure nothrow @safe @nogc { return [start, end]; } @@ -1918,7 +1918,7 @@ extern(D): /// size_type capacity() const nothrow { return (__is_long() ? __get_long_cap() : __min_cap) - 1; } /// - inout(T)* data() inout @safe { return __get_pointer(); } + inout(T)* data() inout @trusted { return __get_pointer(); } /// inout(T)[] as_array() scope return inout nothrow @trusted { return __get_pointer()[0 .. size()]; } /// @@ -2355,7 +2355,7 @@ extern(D): } } void __set_long_size(size_type __s) nothrow { __r_.first().__l.__size_ = __s; } - size_type __get_long_size() const nothrow { return __r_.first().__l.__size_; } + size_type __get_long_size() const nothrow @trusted { return __r_.first().__l.__size_; } void __set_size(size_type __s) nothrow { if (__is_long()) __set_long_size(__s); else __set_short_size(__s); } void __set_long_cap(size_type __s) nothrow { __r_.first().__l.__cap_ = __long_mask | __s; } diff --git a/libphobos/libdruntime/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d index 0a58034087d..df66b27f723 100644 --- a/libphobos/libdruntime/core/sys/posix/fcntl.d +++ b/libphobos/libdruntime/core/sys/posix/fcntl.d @@ -135,6 +135,27 @@ version (linux) enum F_SETLK = 6; enum F_SETLKW = 7; } + else version (MIPS_N64) + { + enum F_GETLK = 14; + enum F_SETLK = 6; + enum F_SETLKW = 7; + } + else version (MIPS_Any) + { + static if ( __USE_FILE_OFFSET64 ) + { + enum F_GETLK = 33; + enum F_SETLK = 34; + enum F_SETLKW = 35; + } + else + { + enum F_GETLK = 14; + enum F_SETLK = 6; + enum F_SETLKW = 7; + } + } else static if ( __USE_FILE_OFFSET64 ) { diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d index f722bc4df62..a2e229f6018 100644 --- a/libphobos/libdruntime/core/sys/posix/signal.d +++ b/libphobos/libdruntime/core/sys/posix/signal.d @@ -2390,11 +2390,23 @@ version (CRuntime_Glibc) //ucontext_t (defined in core.sys.posix.ucontext) //mcontext_t (defined in core.sys.posix.ucontext) - struct stack_t + version (MIPS_Any) { - void* ss_sp; - int ss_flags; - size_t ss_size; + struct stack_t + { + void* ss_sp; + size_t ss_size; + int ss_flags; + } + } + else + { + struct stack_t + { + void* ss_sp; + int ss_flags; + size_t ss_size; + } } struct sigstack @@ -2760,7 +2772,7 @@ else version (CRuntime_UClibc) enum MINSIGSTKSZ = 2048; enum SIGSTKSZ = 8192; - version (MIPS32) + version (MIPS_Any) { struct stack_t { diff --git a/libphobos/libdruntime/core/sys/posix/sys/resource.d b/libphobos/libdruntime/core/sys/posix/sys/resource.d index b997f112e4d..3a9a1876393 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/resource.d +++ b/libphobos/libdruntime/core/sys/posix/sys/resource.d @@ -22,6 +22,9 @@ else version (TVOS) else version (WatchOS) version = Darwin; +version (MIPS32) version = MIPS_Any; +version (MIPS64) version = MIPS_Any; + nothrow @nogc extern(C): // @@ -120,15 +123,31 @@ version (linux) c_long[16] __reserved; } - enum + version (MIPS_Any) { - RLIMIT_CORE = 4, - RLIMIT_CPU = 0, - RLIMIT_DATA = 2, - RLIMIT_FSIZE = 1, - RLIMIT_NOFILE = 7, - RLIMIT_STACK = 3, - RLIMIT_AS = 9, + enum + { + RLIMIT_CORE = 4, + RLIMIT_CPU = 0, + RLIMIT_DATA = 2, + RLIMIT_FSIZE = 1, + RLIMIT_NOFILE = 5, + RLIMIT_STACK = 3, + RLIMIT_AS = 6, + } + } + else + { + enum + { + RLIMIT_CORE = 4, + RLIMIT_CPU = 0, + RLIMIT_DATA = 2, + RLIMIT_FSIZE = 1, + RLIMIT_NOFILE = 7, + RLIMIT_STACK = 3, + RLIMIT_AS = 9, + } } } else version (Darwin) diff --git a/libphobos/libdruntime/core/sys/windows/sql.d b/libphobos/libdruntime/core/sys/windows/sql.d index 58c6d42bd04..9054ce589e8 100644 --- a/libphobos/libdruntime/core/sys/windows/sql.d +++ b/libphobos/libdruntime/core/sys/windows/sql.d @@ -1,4 +1,7 @@ /** +$(RED Warning: + This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sql` instead.) + * Windows API header module * * Translated from MinGW Windows headers @@ -6,6 +9,7 @@ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(DRUNTIMESRC core/sys/windows/_sql.d) */ + module core.sys.windows.sql; version (Windows): diff --git a/libphobos/libdruntime/core/sys/windows/sqlext.d b/libphobos/libdruntime/core/sys/windows/sqlext.d index 8702cda3359..b871fbbbb84 100644 --- a/libphobos/libdruntime/core/sys/windows/sqlext.d +++ b/libphobos/libdruntime/core/sys/windows/sqlext.d @@ -1,4 +1,7 @@ /** +$(RED Warning: + This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqlext` instead.) + * Windows API header module * * Translated from MinGW Windows headers @@ -6,6 +9,7 @@ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(DRUNTIMESRC core/sys/windows/_sqlext.d) */ + module core.sys.windows.sqlext; version (Windows): diff --git a/libphobos/libdruntime/core/sys/windows/sqltypes.d b/libphobos/libdruntime/core/sys/windows/sqltypes.d index e86834faa6d..04fac6bac6a 100644 --- a/libphobos/libdruntime/core/sys/windows/sqltypes.d +++ b/libphobos/libdruntime/core/sys/windows/sqltypes.d @@ -1,4 +1,7 @@ /** +$(RED Warning: + This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqltypes` instead.) + * Windows API header module * * Translated from MinGW Windows headers @@ -6,6 +9,7 @@ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(DRUNTIMESRC core/sys/windows/_sqltypes.d) */ + module core.sys.windows.sqltypes; version (Windows): diff --git a/libphobos/libdruntime/core/sys/windows/sqlucode.d b/libphobos/libdruntime/core/sys/windows/sqlucode.d index d4f03f62d94..e7ae1d276be 100644 --- a/libphobos/libdruntime/core/sys/windows/sqlucode.d +++ b/libphobos/libdruntime/core/sys/windows/sqlucode.d @@ -1,4 +1,7 @@ /** +$(RED Warning: + This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqlucode` instead.) + * Windows API header module * * Translated from MinGW Windows headers @@ -6,6 +9,7 @@ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(DRUNTIMESRC core/sys/windows/_sqlucode.d) */ + module core.sys.windows.sqlucode; version (Windows): diff --git a/libphobos/libdruntime/core/sys/windows/winnt.d b/libphobos/libdruntime/core/sys/windows/winnt.d index 3bd9966e33e..ca4a903fb6a 100644 --- a/libphobos/libdruntime/core/sys/windows/winnt.d +++ b/libphobos/libdruntime/core/sys/windows/winnt.d @@ -1199,7 +1199,7 @@ enum size_t PIMAGE_SECTION_HEADER IMAGE_FIRST_SECTION(PIMAGE_NT_HEADERS h) { return cast(PIMAGE_SECTION_HEADER) - (&h.OptionalHeader + h.FileHeader.SizeOfOptionalHeader); + (cast(ubyte*) &h.OptionalHeader + h.FileHeader.SizeOfOptionalHeader); } // ImageDirectoryEntryToDataEx() diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index f3af2097b39..294d34dbe35 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -2903,6 +2903,14 @@ void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values); } +// Lower an Associative Array to a newaa struct for static initialization. +auto _aaAsStruct(K, V)(V[K] aa) @safe +{ + import core.internal.newaa : makeAA; + assert(__ctfe); + return makeAA!(K, V)(aa); +} + alias AssociativeArray(Key, Value) = Value[Key]; /*********************************** diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d index f264b014789..4014862b4e4 100644 --- a/libphobos/libdruntime/rt/aaA.d +++ b/libphobos/libdruntime/rt/aaA.d @@ -974,3 +974,22 @@ unittest GC.runFinalizers((cast(char*)(&entryDtor))[0 .. 1]); assert(T.dtor == 6 && T.postblit == 2); } + +// Ensure the newaa struct layout (used for static initialization) is in sync +unittest +{ + import newaa = core.internal.newaa; + static assert(newaa.Impl.sizeof == Impl.sizeof); + // ensure compatible types and offsets + static foreach (i; 0 .. Impl.tupleof.length) + { + // for bucket array and Flags, we "compatible" types, not exactly the same types. + static if (__traits(identifier, Impl.tupleof[i]) == "buckets" + || __traits(identifier, Impl.tupleof[i]) == "flags") + static assert(Impl.tupleof[i].sizeof == newaa.Impl.tupleof[i].sizeof); + else + static assert(is(typeof(Impl.tupleof[i]) == typeof(newaa.Impl.tupleof[i]))); + + static assert(Impl.tupleof[i].offsetof == newaa.Impl.tupleof[i].offsetof); + } +} diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d index b5c868f70bc..9bc10558981 100644 --- a/libphobos/libdruntime/rt/minfo.d +++ b/libphobos/libdruntime/rt/minfo.d @@ -267,10 +267,16 @@ struct ModuleGroup edge[nEdges++] = *impidx; } } - // trim space to what is needed. - edges[i] = nEdges > 0 - ? (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges] - : null; + if (nEdges > 0) + { + // trim space to what is needed + edges[i] = (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges]; + } + else + { + edges[i] = null; + .free(edge); + } } } diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 0424d7b0cfa..455825b8781 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -d7e79f024606f18e989ae8b5fe298f9d07c7dced +a3f22129dd2a134338ca02b79ff0de242d7f016e The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/int128.d b/libphobos/src/std/int128.d index b20fa1fdddc..92895445aed 100644 --- a/libphobos/src/std/int128.d +++ b/libphobos/src/std/int128.d @@ -147,7 +147,7 @@ public struct Int128 /** Support casting to a bool * Params: T = bool - * Returns: boolean result + * Returns: true if value is not zero */ bool opCast(T : bool)() const { @@ -155,6 +155,50 @@ public struct Int128 } } // @safe pure nothrow @nogc + /** Support casting to an integral type + * Params: T = integral type + * Returns: low bits of value reinterpreted as T + */ + T opCast(T : long)() const + if (is(byte : T)) + { + return cast(T) this.data.lo; + } + + /// + @safe unittest + { + const Int128 a = Int128(0xffff_ffff_ffff_ffffL, 0x0123_4567_89ab_cdefL); + assert(cast(long) a == 0x0123_4567_89ab_cdefL); + assert(cast(int) a == 0x89ab_cdef); + assert(cast(byte) a == cast(byte) 0xef); + } + + /** Support casting to floating point type + * Params: T = floating point type + * Returns: value cast to floating point with environment-dependent + * rounding if the value is not exactly representable + */ + T opCast(T : real)() const + { + import core.math : ldexp; + if (cast(long) this.data.hi >= 0) + return ldexp(cast(T) this.data.hi, 64) + this.data.lo; + else + { + const absData = neg(this.data); + return -ldexp(cast(T) absData.hi, 64) - absData.lo; + } + } + + /// + @safe unittest + { + const Int128 a = Int128(-1L << 60); + assert(cast(double) a == -(2.0 ^^ 60)); + assert(cast(double) (a * a) == 2.0 ^^ 120); + } + /** Support binary arithmetic operators + - * / % & | ^ << >> >>> * Params: * op = one of the arithmetic binary operators diff --git a/libphobos/src/std/string.d b/libphobos/src/std/string.d index b1063ee0040..ca14c23747e 100644 --- a/libphobos/src/std/string.d +++ b/libphobos/src/std/string.d @@ -3815,6 +3815,7 @@ unittest assert(chomp(" hello world \n\n" ~ [lineSep]) == " hello world \n\n"); assert(chomp(" hello world \n\n" ~ [paraSep]) == " hello world \n\n"); assert(chomp(" hello world \n\n" ~ [ nelSep]) == " hello world \n\n"); + assert(chomp(" hello world ") == " hello world "); assert(chomp(" hello world") == " hello world"); assert(chomp("") == ""); diff --git a/libphobos/testsuite/libphobos.hash/test_hash.d b/libphobos/testsuite/libphobos.hash/test_hash.d index a6d7e5a5788..0ad2443c826 100644 --- a/libphobos/testsuite/libphobos.hash/test_hash.d +++ b/libphobos/testsuite/libphobos.hash/test_hash.d @@ -290,14 +290,14 @@ void issue22076() extern(C++) static class C0 { int foo() { return 0; } // Need at least one function in vtable. - S0 a; alias a this; // { dg-warning "is deprecated" } + S0 a; alias a this; } extern(C++) static class C1 { S1 a; inout(S1)* b() inout nothrow { return &a; } - alias b this; // { dg-warning "is deprecated" } + alias b this; } cast(void) hashOf(S0.init); diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp index 374ef491d3c..fdd80ab0f80 100644 --- a/libphobos/testsuite/libphobos.phobos/phobos.exp +++ b/libphobos/testsuite/libphobos.phobos/phobos.exp @@ -46,7 +46,7 @@ dg-init foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]" dg-runtest $test "-static-libphobos" \ - "-fmain -fbuilding-libphobos-tests $version_flags" + "-Wno-deprecated -fmain -fbuilding-libphobos-tests $version_flags" set libphobos_test_name "" } diff --git a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp index 6c67b0828a0..0ea42cbf253 100644 --- a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp +++ b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp @@ -46,7 +46,7 @@ dg-init foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]" dg-runtest $test "-shared-libphobos" \ - "-fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags" + "-Wno-deprecated -fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags" set libphobos_test_name "" }
reply other threads:[~2023-10-15 11:12 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20231015111209.234FB3858D33@sourceware.org \ --to=ibuclaw@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).