diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-07 20:49:06 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-11 19:18:03 +0100 |
commit | c9f7090d930504db772557c18f16599e03d616ea (patch) | |
tree | 0b4658e755356787447f7c721919608e4da0cddc /gcc/d/dmd | |
parent | 292be6817150ed11d599b6ac92269041ed62eb3a (diff) | |
download | gcc-c9f7090d930504db772557c18f16599e03d616ea.zip gcc-c9f7090d930504db772557c18f16599e03d616ea.tar.gz gcc-c9f7090d930504db772557c18f16599e03d616ea.tar.bz2 |
d: Merge upstream dmd, druntime 82a5d2a7c4, phobos dbc09d823
D front-end changes:
- Import latest fixes from dmd v2.110.0-beta.1.
- Added traits `getBitfieldOffset' and `getBitfieldWidth'.
- Added trait `isCOMClass' to detect if a type is a COM class.
- Added `-fpreview=safer` which enables safety checking on
unattributed functions.
D runtime changes:
- Import latest fixes from druntime v2.110.0-beta.1.
Phobos changes:
- Import latest fixes from phobos v2.110.0-beta.1.
- Added `fromHexString' and `fromHexStringAsRange' functions to
`std.digest'.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 82a5d2a7c4.
* d-lang.cc (d_handle_option): Handle new option `-fpreview=safer'.
* expr.cc (ExprVisitor::NewExp): Remove gcc_unreachable for the
generation of `_d_newThrowable'.
* lang.opt: Add -fpreview=safer.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 82a5d2a7c4.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
core/internal/gc/blkcache.d, core/internal/gc/blockmeta.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos dbc09d823.
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/README.md | 2 | ||||
-rw-r--r-- | gcc/d/dmd/canthrow.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dcast.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dinterpret.d | 32 | ||||
-rw-r--r-- | gcc/d/dmd/dscope.d | 10 | ||||
-rw-r--r-- | gcc/d/dmd/enumsem.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/errors.d | 35 | ||||
-rw-r--r-- | gcc/d/dmd/errorsink.d | 117 | ||||
-rw-r--r-- | gcc/d/dmd/escape.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/expression.d | 7 | ||||
-rw-r--r-- | gcc/d/dmd/expressionsem.d | 316 | ||||
-rw-r--r-- | gcc/d/dmd/func.d | 48 | ||||
-rw-r--r-- | gcc/d/dmd/funcsem.d | 10 | ||||
-rw-r--r-- | gcc/d/dmd/globals.d | 13 | ||||
-rw-r--r-- | gcc/d/dmd/globals.h | 10 | ||||
-rw-r--r-- | gcc/d/dmd/id.d | 4 | ||||
-rw-r--r-- | gcc/d/dmd/intrange.d | 22 | ||||
-rw-r--r-- | gcc/d/dmd/lexer.d | 40 | ||||
-rw-r--r-- | gcc/d/dmd/mtype.d | 37 | ||||
-rw-r--r-- | gcc/d/dmd/nogc.d | 10 | ||||
-rw-r--r-- | gcc/d/dmd/parse.d | 17 | ||||
-rw-r--r-- | gcc/d/dmd/root/array.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/safe.d | 124 | ||||
-rw-r--r-- | gcc/d/dmd/statementsem.d | 42 | ||||
-rw-r--r-- | gcc/d/dmd/templatesem.d | 8 | ||||
-rw-r--r-- | gcc/d/dmd/traits.d | 57 | ||||
-rw-r--r-- | gcc/d/dmd/typesem.d | 40 |
28 files changed, 564 insertions, 449 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index f660884..bfdc9ea 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -2b89c2909de239bd603d6f36379658fe902667db +82a5d2a7c4dd3d270537bcede2981e047bfd0e6a The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md index 1e96152..2e93d26 100644 --- a/gcc/d/dmd/README.md +++ b/gcc/d/dmd/README.md @@ -254,7 +254,7 @@ Note that these groups have no strict meaning, the category assignments are a bi | [hdrgen.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/hdrgen.d) | Convert an AST into D source code for `.di` header generation, as well as `-vcg-ast` and error messages | | [json.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/json.d) | Describe the module in a `.json` file for the `-X` flag | | [dtoh.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dtoh.d) | C++ header generation from D source files | -| [disasm86.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/disasm86.d) | x86-64 dissassembly generation +| [disasm86.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/x86/disasm86.d) | x86-64 disassembly generation | [disasmarm.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/arm/disasmarm.d) | AArch64 disassembly generation ### Utility diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index caf58a2..cb3afc6 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -80,7 +80,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink) { eSink.error(e.loc, "%s `%s` is not `nothrow`", f.kind(), f.toPrettyChars()); if (!f.isDtorDeclaration()) - errorSupplementalInferredAttr(f, 10, false, STC.nothrow_); + errorSupplementalInferredAttr(f, 10, false, STC.nothrow_, eSink); import dmd.expressionsem : checkOverriddenDtor; f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isNothrow, "not nothrow"); diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 34b120b..c15322f 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -2335,7 +2335,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) Type tb = t.toBasetype(); Type typeb = e.type.toBasetype(); - if (e.hexString && !e.committed) + if (e.hexString && !e.committed && tb.nextOf().isIntegral) { const szx = cast(ubyte) tb.nextOf().size(); if (szx != se.sz && (e.len % szx) == 0) diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 4e04a27..f219e3f 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -4855,33 +4855,6 @@ public: return; } - else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendTTrace) - { - // In expressionsem.d `ea ~= eb` was lowered to `_d_arrayappendT{,Trace}({file, line, funcname}, ea, eb);`. - // The following code will rewrite it back to `ea ~= eb` and then interpret that expression. - Expression lhs, rhs; - - if (fd.ident == Id._d_arrayappendT) - { - assert(e.arguments.length == 2); - lhs = (*e.arguments)[0]; - rhs = (*e.arguments)[1]; - } - else - { - assert(e.arguments.length == 5); - lhs = (*e.arguments)[3]; - rhs = (*e.arguments)[4]; - } - - auto cae = new CatAssignExp(e.loc, lhs, rhs); - cae.type = e.type; - - result = interpretRegion(cae, istate, CTFEGoal.LValue); - return; - } - else if (fd.ident == Id._d_arrayappendcTX) - assert(0, "CTFE cannot interpret _d_arrayappendcTX!"); } else if (auto soe = ecall.isSymOffExp()) { @@ -6132,7 +6105,7 @@ public: { auto se = e1.isStringExp(); // Allow casting a hex string literal to short[], int[] or long[] - if (se && se.hexString && se.postfix == StringExp.NoPostfix) + if (se && se.hexString && se.postfix == StringExp.NoPostfix && e.to.nextOf().isIntegral) { const sz = cast(size_t) e.to.nextOf().size; if ((se.len % sz) != 0) @@ -6151,8 +6124,7 @@ public: } error(e.loc, "array cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars()); if (se && se.hexString && se.postfix != StringExp.NoPostfix) - errorSupplemental(e.loc, "perhaps remove postfix `%s` from hex string", - (cast(char) se.postfix ~ "\0").ptr); + errorSupplemental(e.loc, "perhaps remove postfix `%.*s` from hex string", 1, &se.postfix); result = CTFEExp.cantexp; return; diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 05cc8f1..aa48d57 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -64,21 +64,11 @@ private extern (D) struct BitFields Contract contract; bool ctfe; /// inside a ctfe-only expression bool traitsCompiles; /// inside __traits(compile) - /// ignore symbol visibility /// https://issues.dlang.org/show_bug.cgi?id=15907 bool ignoresymbolvisibility; - - bool _padding0; // To keep the layout the same as when the old `SCOPE` enum bitflags were used - bool inCfile; /// C semantics apply - - bool _padding1; - bool _padding2; - bool _padding3; - bool canFree; /// is on free list - bool fullinst; /// fully instantiate templates bool ctfeBlock; /// inside a `if (__ctfe)` block bool dip1000; /// dip1000 errors enabled for this scope diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d index 99211e4..e22bdba 100644 --- a/gcc/d/dmd/enumsem.d +++ b/gcc/d/dmd/enumsem.d @@ -185,7 +185,7 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) if (ed.members.length == 0) { - .error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars()); + .error(ed.loc, "%s `%s` enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars()); ed.errors = true; ed.semanticRun = PASS.semanticdone; return; diff --git a/gcc/d/dmd/errors.d b/gcc/d/dmd/errors.d index 79efc6e..1babb18 100644 --- a/gcc/d/dmd/errors.d +++ b/gcc/d/dmd/errors.d @@ -37,60 +37,39 @@ class ErrorSinkCompiler : ErrorSink extern (C++): override: - void error(const ref Loc loc, const(char)* format, ...) + void verror(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReport(loc, format, ap, ErrorKind.error); - va_end(ap); } - void errorSupplemental(const ref Loc loc, const(char)* format, ...) + void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReportSupplemental(loc, format, ap, ErrorKind.error); - va_end(ap); } - void warning(const ref Loc loc, const(char)* format, ...) + void vwarning(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReport(loc, format, ap, ErrorKind.warning); - va_end(ap); } - void warningSupplemental(const ref Loc loc, const(char)* format, ...) + void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReportSupplemental(loc, format, ap, ErrorKind.warning); - va_end(ap); } - void deprecation(const ref Loc loc, const(char)* format, ...) + void vdeprecation(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReport(loc, format, ap, ErrorKind.deprecation); - va_end(ap); } - void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) + void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReportSupplemental(loc, format, ap, ErrorKind.deprecation); - va_end(ap); } - void message(const ref Loc loc, const(char)* format, ...) + void vmessage(const ref Loc loc, const(char)* format, va_list ap) { - va_list ap; - va_start(ap, format); verrorReport(loc, format, ap, ErrorKind.message); - va_end(ap); } } diff --git a/gcc/d/dmd/errorsink.d b/gcc/d/dmd/errorsink.d index afea689..9884112 100644 --- a/gcc/d/dmd/errorsink.d +++ b/gcc/d/dmd/errorsink.d @@ -11,6 +11,8 @@ module dmd.errorsink; +import core.stdc.stdarg; + import dmd.location; /*************************************** @@ -21,19 +23,78 @@ abstract class ErrorSink nothrow: extern (C++): - void error(const ref Loc loc, const(char)* format, ...); + void verror(const ref Loc loc, const(char)* format, va_list ap); + void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap); + void vwarning(const ref Loc loc, const(char)* format, va_list ap); + void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap); + void vmessage(const ref Loc loc, const(char)* format, va_list ap); + void vdeprecation(const ref Loc loc, const(char)* format, va_list ap); + void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap); - void errorSupplemental(const ref Loc loc, const(char)* format, ...); + void error(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); + } - void warning(const ref Loc loc, const(char)* format, ...); + void errorSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + verrorSupplemental(loc, format, ap); + va_end(ap); + } - void warningSupplemental(const ref Loc loc, const(char)* format, ...); + void warning(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vwarning(loc, format, ap); + va_end(ap); + } + + void warningSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vwarningSupplemental(loc, format, ap); + va_end(ap); + } + + void message(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vmessage(loc, format, ap); + va_end(ap); + } - void message(const ref Loc loc, const(char)* format, ...); + void deprecation(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vdeprecation(loc, format, ap); + va_end(ap); + } - void deprecation(const ref Loc loc, const(char)* format, ...); + void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vdeprecationSupplemental(loc, format, ap); + va_end(ap); + } - void deprecationSupplemental(const ref Loc loc, const(char)* format, ...); + /** + * This will be called to indicate compilation has either + * finished or terminated, no more errors are possible - it's + * now the time to print any stored errors. + * + * The default implementation does nothing since most error sinks have no state + */ + void plugSink() {} } /***************************************** @@ -45,19 +106,19 @@ class ErrorSinkNull : ErrorSink extern (C++): override: - void error(const ref Loc loc, const(char)* format, ...) { } + void verror(const ref Loc loc, const(char)* format, va_list ap) { } - void errorSupplemental(const ref Loc loc, const(char)* format, ...) { } + void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } - void warning(const ref Loc loc, const(char)* format, ...) { } + void vwarning(const ref Loc loc, const(char)* format, va_list ap) { } - void warningSupplemental(const ref Loc loc, const(char)* format, ...) { } + void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } - void message(const ref Loc loc, const(char)* format, ...) { } + void vmessage(const ref Loc loc, const(char)* format, va_list ap) { } - void deprecation(const ref Loc loc, const(char)* format, ...) { } + void vdeprecation(const ref Loc loc, const(char)* format, va_list ap) { } - void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) { } + void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } } /***************************************** @@ -71,7 +132,7 @@ class ErrorSinkLatch : ErrorSinkNull bool sawErrors; - void error(const ref Loc loc, const(char)* format, ...) { sawErrors = true; } + void verror(const ref Loc loc, const(char)* format, va_list ap) { sawErrors = true; } } /***************************************** @@ -87,7 +148,7 @@ class ErrorSinkStderr : ErrorSink extern (C++): override: - void error(const ref Loc loc, const(char)* format, ...) + void verror(const ref Loc loc, const(char)* format, va_list ap) { fputs("Error: ", stderr); const p = loc.toChars(); @@ -97,16 +158,13 @@ class ErrorSinkStderr : ErrorSink //mem.xfree(cast(void*)p); // loc should provide the free() } - va_list ap; - va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); - va_end(ap); } - void errorSupplemental(const ref Loc loc, const(char)* format, ...) { } + void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } - void warning(const ref Loc loc, const(char)* format, ...) + void vwarning(const ref Loc loc, const(char)* format, va_list ap) { fputs("Warning: ", stderr); const p = loc.toChars(); @@ -116,16 +174,13 @@ class ErrorSinkStderr : ErrorSink //mem.xfree(cast(void*)p); // loc should provide the free() } - va_list ap; - va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); - va_end(ap); } - void warningSupplemental(const ref Loc loc, const(char)* format, ...) { } + void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } - void deprecation(const ref Loc loc, const(char)* format, ...) + void vdeprecation(const ref Loc loc, const(char)* format, va_list ap) { fputs("Deprecation: ", stderr); const p = loc.toChars(); @@ -135,14 +190,11 @@ class ErrorSinkStderr : ErrorSink //mem.xfree(cast(void*)p); // loc should provide the free() } - va_list ap; - va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); - va_end(ap); } - void message(const ref Loc loc, const(char)* format, ...) + void vmessage(const ref Loc loc, const(char)* format, va_list ap) { const p = loc.toChars(); if (*p) @@ -151,12 +203,9 @@ class ErrorSinkStderr : ErrorSink //mem.xfree(cast(void*)p); // loc should provide the free() } - va_list ap; - va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); - va_end(ap); } - void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) { } + void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) { } } diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index e1b2ef7..3e18051 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -180,7 +180,7 @@ bool checkMutableArguments(ref Scope sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!tf.isLive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) + if (!tf.isLive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && setFunctionToUnsafe(sc.func))) return; if (!gag) diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 3c79b02..dc72b3a 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -4143,10 +4143,9 @@ extern (C++) final class IndexExp : BinExp override bool isLvalue() { - if (e1.op == EXP.assocArrayLiteral) - return false; - if (e1.type.ty == Tsarray || - (e1.op == EXP.index && e1.type.ty != Tarray)) + auto t1b = e1.type.toBasetype(); + if (t1b.isTypeAArray() || t1b.isTypeSArray() || + (e1.isIndexExp() && t1b != t1b.isTypeDArray())) { return e1.isLvalue(); } diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index b26ce23..e1baa48 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -1935,7 +1935,7 @@ private bool checkPurity(FuncDeclaration f, const ref Loc loc, Scope* sc) f.toPrettyChars()); if (!f.isDtorDeclaration()) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_, global.errorSink); f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); return true; @@ -2018,15 +2018,18 @@ void checkOverriddenDtor(FuncDeclaration f, Scope* sc, const ref Loc loc, } } -/// Print the reason why `fd` was inferred `@system` as a supplemental error -/// Params: -/// fd = function to check -/// maxDepth = up to how many functions deep to report errors -/// deprecation = print deprecations instead of errors -/// stc = storage class of attribute to check -public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool deprecation, STC stc) +/******************************************** + * Print the reason why `fd` was inferred `@system` as a supplemental error + * Params: + * fd = function to check + * maxDepth = up to how many functions deep to report errors + * deprecation = print deprecations instead of errors + * stc = storage class of attribute to check + * eSink = where the error messages go + */ +public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool deprecation, STC stc, ErrorSink eSink) { - auto errorFunc = deprecation ? &deprecationSupplemental : &errorSupplemental; + auto errorFunc = deprecation ? &eSink.deprecationSupplemental : &eSink.errorSupplemental; AttributeViolation* s; const(char)* attr; @@ -2054,7 +2057,7 @@ public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool if (!s) return; - if (s.fmtStr) + if (s.format) { errorFunc(s.loc, deprecation ? "which wouldn't be `%s` because of:" : @@ -2062,25 +2065,24 @@ public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool if (stc == STC.nogc || stc == STC.pure_) { auto f = (cast(Dsymbol) s.arg0).isFuncDeclaration(); - errorFunc(s.loc, s.fmtStr, f.kind(), f.toPrettyChars(), s.arg1 ? s.arg1.toChars() : ""); + errorFunc(s.loc, s.format, f.kind(), f.toPrettyChars(), s.arg1 ? s.arg1.toChars() : ""); } else { - errorFunc(s.loc, s.fmtStr, + errorFunc(s.loc, s.format, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : ""); } } - else if (auto sa = s.arg0.isDsymbol()) + else if (s.fd) { - if (FuncDeclaration fd2 = sa.isFuncDeclaration()) + if (maxDepth > 0) { - if (maxDepth > 0) - { - errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars()); - errorSupplementalInferredAttr(fd2, maxDepth - 1, deprecation, stc); - } + errorFunc(s.loc, "which calls `%s`", s.fd.toPrettyChars()); + errorSupplementalInferredAttr(s.fd, maxDepth - 1, deprecation, stc, eSink); } } + else + assert(0); } /******************************************* @@ -2262,7 +2264,7 @@ private bool checkSafety(FuncDeclaration f, ref Loc loc, Scope* sc) sc.func.kind(), sc.func.toPrettyChars(), f.kind(), prettyChars); if (!f.isDtorDeclaration) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe, global.errorSink); .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); @@ -2276,12 +2278,12 @@ private bool checkSafety(FuncDeclaration f, ref Loc loc, Scope* sc) if (sc.func.isSafeBypassingInference()) { .deprecation(loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); - errorSupplementalInferredAttr(f, 10, true, STC.safe); + errorSupplementalInferredAttr(f, 10, true, STC.safe, global.errorSink); } else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(loc, null, f, null, null); + sc.func.safetyViolation = new AttributeViolation(loc, f); } } return false; @@ -2329,7 +2331,7 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc) sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); if (!f.isDtorDeclaration) - f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); + f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc, global.errorSink); } f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().isNogc, "non-@nogc"); @@ -2850,12 +2852,12 @@ private Expression rewriteOpAssign(BinExp exp) * Params: * sc = scope * argumentList = arguments to function - * reportErrors = whether or not to report errors here. Some callers are not + * eSink = if not null, used to report errors. Some callers are not * checking actual function params, so they'll do their own error reporting * Returns: * `true` when a semantic error occurred */ -private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const bool reportErrors = true) +private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, ErrorSink eSink) { Expressions* exps = argumentList.arguments; if (!exps) @@ -2876,9 +2878,9 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const b if (arg.op == EXP.type) { - if (reportErrors) + if (eSink) { - error(arg.loc, "cannot pass type `%s` as a function argument", arg.toChars()); + eSink.error(arg.loc, "cannot pass type `%s` as a function argument", arg.toChars()); arg = ErrorExp.get(); } err = true; @@ -2886,9 +2888,9 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const b } else if (arg.type.toBasetype().ty == Tfunction) { - if (reportErrors) + if (eSink) { - error(arg.loc, "cannot pass function `%s` as a function argument", arg.toChars()); + eSink.error(arg.loc, "cannot pass function `%s` as a function argument", arg.toChars()); arg = ErrorExp.get(); } err = true; @@ -2961,14 +2963,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc, if (argumentList.names) { - const(char)* msg = null; - auto resolvedArgs = tf.resolveNamedArgs(argumentList, &msg); + OutBuffer buf; + auto resolvedArgs = tf.resolveNamedArgs(argumentList, &buf); if (!resolvedArgs) { // while errors are usually already caught by `tf.callMatch`, // this can happen when calling `typeof(freefunc)` - if (msg) - error(loc, "%s", msg); + if (buf.length) + error(loc, "%s", buf.peekChars()); return true; } // note: the argument list should be mutated with named arguments / default arguments, @@ -4974,7 +4976,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { return setError(); } - if (preFunctionParameters(sc, exp.argumentList)) + if (preFunctionParameters(sc, exp.argumentList, global.errorSink)) { return setError(); } @@ -5194,21 +5196,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor auto tiargs = new Objects(); tiargs.push(exp.newtype); - id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs); - id = new CallExp(exp.loc, id).expressionSemantic(sc); - Expression idVal; - Expression tmp = extractSideEffect(sc, "__tmpThrowable", idVal, id, true); - // auto castTmp = new CastExp(exp.loc, tmp, exp.type); + id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs); - auto ctor = new DotIdExp(exp.loc, tmp, Id.ctor).expressionSemantic(sc); - auto ctorCall = new CallExp(exp.loc, ctor, exp.arguments); + id = new CallExp(exp.loc, id).expressionSemantic(sc); - id = Expression.combine(idVal, exp.argprefix).expressionSemantic(sc); - id = Expression.combine(id, ctorCall).expressionSemantic(sc); - // id = Expression.combine(id, castTmp).expressionSemantic(sc); + exp.lowering = id.expressionSemantic(sc); - result = id.expressionSemantic(sc); + result = exp; return; } else if (sc.needsCodegen() && // interpreter doesn't need this lowered @@ -5648,7 +5643,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.fd.ident != Id.empty) return; - const(char)[] s; + string s; if (exp.fd.fes) s = "__foreachbody"; else if (exp.fd.tok == TOK.reserved) @@ -5682,7 +5677,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor symtab = sds.symtab; } assert(symtab); - Identifier id = Identifier.generateId(s, symtab.length() + 1); + Identifier id = Identifier.generateIdWithLoc(s, exp.loc); exp.fd.ident = id; if (exp.td) exp.td.ident = id; @@ -5925,7 +5920,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (FuncExp fe = exp.e1.isFuncExp()) { if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.argumentList)) + preFunctionParameters(sc, exp.argumentList, global.errorSink)) return setError(); // Run e1 semantic even if arguments have any errors @@ -6165,7 +6160,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.argumentList)) + preFunctionParameters(sc, exp.argumentList, global.errorSink)) return setError(); // Check for call operator overload @@ -9334,7 +9329,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to)) { if (msg.length) - errorSupplemental(exp.loc, "%s", (msg ~ '\0').ptr); + errorSupplemental(exp.loc, "%.*s", msg.fTuple.expand); return setError(); } } @@ -9344,7 +9339,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to); // if message was printed if (sc.func && sc.func.isSafeBypassingInference() && !sc.isDeprecated()) - deprecationSupplemental(exp.loc, "%s", (msg ~ '\0').ptr); + deprecationSupplemental(exp.loc, "%.*s", msg.fTuple.expand); if (err) return setError(); } @@ -13083,9 +13078,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } - override void visit(ShlExp exp) + private void visitShift(BinExp exp) { - //printf("ShlExp::semantic(), type = %p\n", type); if (exp.type) { result = exp; @@ -13112,87 +13106,32 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = exp.incompatibleTypes(); return; } + exp.e1 = integralPromotions(exp.e1, sc); if (exp.e2.type.toBasetype().ty != Tvector) - exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); + { + Type tb1 = exp.e1.type.toBasetype(); + exp.e2 = exp.e2.castTo(sc, tb1.ty == Tvector ? tb1 : Type.tshiftcnt); + } exp.type = exp.e1.type; result = exp; } + override void visit(ShlExp exp) + { + visitShift(exp); + } override void visit(ShrExp exp) { - if (exp.type) - { - result = exp; - return; - } - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - - if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) - return setError(); - - if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) - { - result = exp.incompatibleTypes(); - return; - } - exp.e1 = integralPromotions(exp.e1, sc); - if (exp.e2.type.toBasetype().ty != Tvector) - exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); - - exp.type = exp.e1.type; - result = exp; + visitShift(exp); } - override void visit(UshrExp exp) { - if (exp.type) - { - result = exp; - return; - } - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - - if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) - return setError(); - - if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) - { - result = exp.incompatibleTypes(); - return; - } - exp.e1 = integralPromotions(exp.e1, sc); - if (exp.e2.type.toBasetype().ty != Tvector) - exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); - - exp.type = exp.e1.type; - result = exp; + visitShift(exp); } - override void visit(AndExp exp) + private void visitBinaryBitOp(BinExp exp) { if (exp.type) { @@ -13247,114 +13186,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = exp; } + override void visit(AndExp exp) + { + visitBinaryBitOp(exp); + } override void visit(OrExp exp) { - if (exp.type) - { - result = exp; - return; - } - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - - if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) - { - exp.type = exp.e1.type; - result = exp; - return; - } - - if (Expression ex = typeCombine(exp, sc)) - { - result = ex; - return; - } - - Type tb = exp.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!isArrayOpValid(exp)) - { - result = arrayOpInvalidError(exp); - return; - } - result = exp; - return; - } - if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) - { - result = exp.incompatibleTypes(); - return; - } - if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) - return setError(); - - result = exp; + visitBinaryBitOp(exp); } - override void visit(XorExp exp) { - if (exp.type) - { - result = exp; - return; - } - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - - if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) - { - exp.type = exp.e1.type; - result = exp; - return; - } - - if (Expression ex = typeCombine(exp, sc)) - { - result = ex; - return; - } - - Type tb = exp.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!isArrayOpValid(exp)) - { - result = arrayOpInvalidError(exp); - return; - } - result = exp; - return; - } - if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) - { - result = exp.incompatibleTypes(); - return; - } - if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) - return setError(); - - result = exp; + visitBinaryBitOp(exp); } override void visit(LogicalExp exp) @@ -15217,6 +15059,27 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) { return false; } + else if (sc._module.ident == Id.atomic && sc._module.parent !is null) + { + // Allow core.internal.atomic, it is an compiler implementation for a given platform module. + // It is then exposed by other modules such as core.atomic and core.stdc.atomic. + // This is available as long as druntime is on the import path and the platform supports that operation. + + // https://issues.dlang.org/show_bug.cgi?id=24846 + + Package parent = sc._module.parent.isPackage(); + if (parent !is null) + { + // This can be easily converted over to apply to core.atomic and core.internal.atomic + if (parent.ident == Id.internal) + { + parent = parent.parent.isPackage(); + + if (parent !is null && parent.ident == Id.core && parent.parent is null) + return false; + } + } + } //printf("checkSharedAccess() `%s` returnRef: %d\n", e.toChars(), returnRef); @@ -17184,8 +17047,11 @@ void semanticTypeInfo(Scope* sc, Type t) Scope scx; scx.eSink = global.errorSink; scx._module = sd.getModule(); - getTypeInfoType(sd.loc, t, &scx); - sd.requestTypeInfo = true; + if (global.params.useTypeInfo) + { + getTypeInfoType(sd.loc, t, &scx); + sd.requestTypeInfo = true; + } } else if (!sc.minst) { diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index e9b9367..153befd 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -685,14 +685,15 @@ extern (C++) class FuncDeclaration : Declaration * * Params: * loc = location of action - * fmt = format string for error message + * format = format string for error message * arg0 = (optional) argument to format string */ - extern (D) final void setThrow(Loc loc, const(char)* fmt, RootObject arg0 = null) + extern (D) final void setThrow(Loc loc, const(char)* format, RootObject arg0 = null) { if (nothrowInprocess && !nothrowViolation) { - nothrowViolation = new AttributeViolation(loc, fmt, arg0); // action that requires GC + assert(format); + nothrowViolation = new AttributeViolation(loc, format, arg0); // action that requires GC } } @@ -700,11 +701,14 @@ extern (C++) class FuncDeclaration : Declaration * The function calls non-`nothrow` function f, register that in case nothrow is being inferred * Params: * loc = location of call - * f = function being called + * fd = function being called */ - extern (D) final void setThrowCall(Loc loc, FuncDeclaration f) + extern (D) final void setThrowCall(Loc loc, FuncDeclaration fd) { - return setThrow(loc, null, f); + if (nothrowInprocess && !nothrowViolation) + { + nothrowViolation = new AttributeViolation(loc, fd); // action that requires GC + } } /**************************************** @@ -1871,14 +1875,26 @@ extern (C++) final class NewDeclaration : FuncDeclaration /// The `FunctionDeclaration` is then stored in `arg0` and `fmtStr` must be `null`. struct AttributeViolation { - /// location of error - Loc loc = Loc.init; - /// printf-style format string - const(char)* fmtStr = null; - /// Arguments for up to two `%s` format specifiers in format string - RootObject arg0 = null; - /// ditto - RootObject arg1 = null; - /// ditto - RootObject arg2 = null; + Loc loc; /// location of error + + FuncDeclaration fd; /// function is the focus of the violation + + // -- OR -- + + const(char)* format; /// printf-style format string + RootObject arg0; /// Arguments for up to two `%s` format specifiers in format string + RootObject arg1; /// ditto + RootObject arg2; /// ditto + + this(ref Loc loc, FuncDeclaration fd) { this.loc = loc; this.fd = fd; } + + this(ref Loc loc, const(char)* format, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) + { + assert(format); + this.loc = loc; + this.format = format; + this.arg0 = arg0; + this.arg1 = arg1; + this.arg2 = arg2; + } } diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d index c142a16..bfa0fac 100644 --- a/gcc/d/dmd/funcsem.d +++ b/gcc/d/dmd/funcsem.d @@ -3001,7 +3001,15 @@ extern (D) bool setImpure(FuncDeclaration fd, Loc loc = Loc.init, const(char)* f if (fmt) fd.pureViolation = new AttributeViolation(loc, fmt, fd, arg0); // impure action else if (arg0) - fd.pureViolation = new AttributeViolation(loc, fmt, arg0); // call to impure function + { + if (auto sa = arg0.isDsymbol()) + { + if (FuncDeclaration fd2 = sa.isFuncDeclaration()) + { + fd.pureViolation = new AttributeViolation(loc, fd2); // call to impure function + } + } + } if (fd.fes) fd.fes.func.setImpure(loc, fmt, arg0); diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index ccb63e3..88b27d2 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -188,6 +188,8 @@ extern (C++) struct Param // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html // Implementation: https://github.com/dlang/dmd/pull/9817 + FeatureState safer; // safer by default (more @safe checks in unattributed code) + // https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md FeatureState noSharedAccess; // read/write access to shared memory objects bool previewIn; // `in` means `[ref] scope const`, accepts rvalues bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract @@ -468,6 +470,17 @@ extern (C++) struct Global } /** + * Indicate to stateful error sinks that no more errors can be produced. + * This is to support error sinks that collect information to produce a + * single (say) report. + */ + extern(C++) void plugErrorSinks() + { + global.errorSink.plugSink(); + global.errorSinkNull.plugSink(); + } + + /** Returns: the version as the number that would be returned for __VERSION__ */ extern(C++) uint versionNumber() @safe diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 5348d61..c5659ea 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -191,6 +191,9 @@ struct Param // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html // Implementation: https://github.com/dlang/dmd/pull/9817 + FeatureState safer; // safer by default (more @safe checks in unattributed code) + // https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md + FeatureState noSharedAccess; // read/write access to shared memory objects d_bool previewIn; // `in` means `[ref] scope const`, accepts rvalues d_bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract @@ -351,6 +354,13 @@ struct Global void _init(); /** + * Indicate to stateful error sinks that no more errors can be produced. + * This is to support error sinks that collect information to produce a + * single (say) report. + */ + void plugErrorSinks(); + + /** Returns: the version as the number that would be returned for __VERSION__ */ unsigned versionNumber(); diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index f676361..aae07bc 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -389,6 +389,7 @@ immutable Msgtable[] msgtable = // Builtin functions { "std" }, { "core" }, + { "internal" }, { "config" }, { "c_complex_float" }, { "c_complex_double" }, @@ -481,9 +482,12 @@ immutable Msgtable[] msgtable = { "isRef" }, { "isOut" }, { "isLazy" }, + { "isCOMClass" }, { "hasMember" }, { "identifier" }, { "fullyQualifiedName" }, + { "getBitfieldOffset" }, + { "getBitfieldWidth" }, { "getProtection" }, { "getVisibility" }, { "parent" }, diff --git a/gcc/d/dmd/intrange.d b/gcc/d/dmd/intrange.d index 51f2801..d89fbb2 100644 --- a/gcc/d/dmd/intrange.d +++ b/gcc/d/dmd/intrange.d @@ -13,10 +13,9 @@ module dmd.intrange; import core.stdc.stdio; -import dmd.astenums; -import dmd.mtype; -import dmd.expression; -import dmd.globals; +import dmd.astenums : Tdchar; +import dmd.mtype : Type; +import dmd.globals : uinteger_t; private uinteger_t copySign(uinteger_t x, bool sign) @safe { @@ -322,7 +321,7 @@ struct IntRange static IntRange fromType(Type type, bool isUnsigned) { - if (!type.isIntegral() || type.toBasetype().ty == Tvector) + if (!type.isIntegral() || type.toBasetype().isTypeVector()) return widest(); uinteger_t mask = type.sizemask(); @@ -444,7 +443,7 @@ struct IntRange IntRange _cast(Type type) { - if (!type.isIntegral() || type.toBasetype().ty == Tvector) + if (!type.isIntegral() || type.toBasetype().isTypeVector()) return this; else if (!type.isUnsigned()) return castSigned(type.sizemask()); @@ -456,7 +455,7 @@ struct IntRange IntRange castUnsigned(Type type) { - if (!type.isIntegral() || type.toBasetype().ty == Tvector) + if (!type.isIntegral() || type.toBasetype().isTypeVector()) return castUnsigned(ulong.max); else if (type.toBasetype().ty == Tdchar) return castDchar(); @@ -504,7 +503,7 @@ struct IntRange union_ = true; } - ref const(IntRange) dump(const(char)* funcName, Expression e) const return + ref const(IntRange) dump(Exp)(const(char)* funcName, Exp e) const return { printf("[(%c)%#018llx, (%c)%#018llx] @ %s ::: %s\n", imin.negative?'-':'+', cast(ulong)imin.value, @@ -668,7 +667,7 @@ struct IntRange return widest(); // Don't treat the whole range as divide by 0 if only one end of a range is 0. - // Issue 15289 + // https://issues.dlang.org/show_bug.cgi?id=15289 if (rhs.imax.value == 0) { rhs.imax.value--; @@ -682,6 +681,11 @@ struct IntRange { return IntRange(imin / rhs.imax, imax / rhs.imin); } + else if (rhs.imin.negative && !rhs.imax.negative) // divisor spans [-1, 0, 1] + { + SignExtendedNumber[4] bdy = [-imin, imin, -imax, imax]; + return IntRange.fromNumbers4(bdy.ptr); + } else { // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)] diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 476a700..d9f4b1c 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -1555,6 +1555,8 @@ class Lexer if (ndigits != 2 && !utf_isValidDchar(v)) { error(loc, "invalid UTF character \\U%08x", v); + if (v >= 0xD800 && v <= 0xDFFF) + errorSupplemental("The code unit is a UTF-16 surrogate, is the escape UTF-16 not a Unicode code point?"); v = '?'; // recover with valid UTF character } } @@ -3168,6 +3170,11 @@ class Lexer eSink.error(loc, format, args); } + void errorSupplemental(T...)(const(char)* format, T args) + { + eSink.errorSupplemental(token.loc, format, args); + } + void deprecation(T...)(const ref Loc loc, const(char)* format, T args) { eSink.deprecation(loc, format, args); @@ -3434,13 +3441,14 @@ class Lexer if (*q != ct) break; } - /* Remove leading spaces until start of the comment + /* Remove leading line feed or space */ int linestart = 0; if (ct == '/') { - while (q < qend && (*q == ' ' || *q == '\t')) + if (q < qend && *q == ' ') { ++q; + } } else if (q < qend) { @@ -3671,25 +3679,35 @@ unittest import core.stdc.stdarg; string expected; + string expectedSupplemental; bool gotError; - void error(const ref Loc loc, const(char)* format, ...) + void verror(const ref Loc loc, const(char)* format, va_list ap) { gotError = true; char[100] buffer = void; + auto actual = buffer[0 .. vsnprintf(buffer.ptr, buffer.length, format, ap)]; + assert(expected == actual); + } + + void errorSupplemental(const ref Loc loc, const(char)* format, ...) + { + gotError = true; + char[128] buffer = void; va_list ap; va_start(ap, format); auto actual = buffer[0 .. vsnprintf(buffer.ptr, buffer.length, format, ap)]; va_end(ap); - assert(expected == actual); + assert(expectedSupplemental == actual); } } ErrorSinkTest errorSink = new ErrorSinkTest; - void test(string sequence, string expectedError, dchar expectedReturnValue, uint expectedScanLength, bool Ccompile = false) + void test2(string sequence, string[2] expectedError, dchar expectedReturnValue, uint expectedScanLength, bool Ccompile = false) { - errorSink.expected = expectedError; + errorSink.expected = expectedError[0]; + errorSink.expectedSupplemental = expectedError[1]; errorSink.gotError = false; auto p = cast(const(char)*)sequence.ptr; Lexer lexer = new Lexer(errorSink); @@ -3702,6 +3720,11 @@ unittest assert(expectedScanLength == actualScanLength); } + void test(string sequence, string expectedError, dchar expectedReturnValue, uint expectedScanLength, bool Ccompile = false) + { + test2(sequence, [expectedError, null], expectedReturnValue, expectedScanLength, Ccompile); + } + test("c", `undefined escape sequence \c`, 'c', 1); test("!", `undefined escape sequence \!`, '!', 1); test(""", `undefined escape sequence \&`, '&', 1, true); @@ -3720,8 +3743,6 @@ unittest test("U0001f6" , `escape hex sequence has 6 hex digits instead of 8`, 0x0001f6, 7); test("U0001f60", `escape hex sequence has 7 hex digits instead of 8`, 0x0001f60, 8); - test("ud800" , `invalid UTF character \U0000d800`, '?', 5); - test("udfff" , `invalid UTF character \U0000dfff`, '?', 5); test("U00110000", `invalid UTF character \U00110000`, '?', 9); test("xg0" , `undefined escape hex sequence \xg`, 'g', 2); @@ -3733,6 +3754,9 @@ unittest test(""", `unterminated named entity "`, '?', 5); test("400", `escape octal sequence \400 is larger than \377`, 0x100, 3); + + test2("uD800", [`invalid UTF character \U0000d800`, `The code unit is a UTF-16 surrogate, is the escape UTF-16 not a Unicode code point?`], '?', 5); + test2("uDFFF", [`invalid UTF character \U0000dfff`, `The code unit is a UTF-16 surrogate, is the escape UTF-16 not a Unicode code point?`], '?', 5); } unittest diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index be70b02d..6d57467 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -2602,13 +2602,20 @@ extern (C++) final class TypeFunction : TypeNext return linkage == LINK.d && parameterList.varargs == VarArg.variadic; } - extern(D) static const(char)* getMatchError(A...)(const(char)* format, A args) + /********************************* + * Append error message to buf. + * Input: + * buf = message sink + * format = printf format + */ + extern(C) static void getMatchError(ref OutBuffer buf, const(char)* format, ...) { if (global.gag && !global.params.v.showGaggedErrors) - return null; - OutBuffer buf; - buf.printf(format, args); - return buf.extractChars(); + return; + va_list ap; + va_start(ap, format); + buf.vprintf(format, ap); + va_end(ap); } /******************************** @@ -2617,10 +2624,10 @@ extern (C++) final class TypeFunction : TypeNext * * Params: * argumentList = array of function arguments - * pMessage = address to store error message, or `null` + * buf = if not null, append error message to it * Returns: re-ordered argument list, or `null` on error */ - extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, const(char)** pMessage) + extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, OutBuffer* buf) { Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; Identifier[] names = argumentList.names ? (*argumentList.names)[] : null; @@ -2644,8 +2651,8 @@ extern (C++) final class TypeFunction : TypeNext const pi = findParameterIndex(name); if (pi == -1) { - if (pMessage) - *pMessage = getMatchError("no parameter named `%s`", name.toChars()); + if (buf) + getMatchError(*buf, "no parameter named `%s`", name.toChars()); return null; } ci = pi; @@ -2655,8 +2662,8 @@ extern (C++) final class TypeFunction : TypeNext if (!isVariadic) { // Without named args, let the caller diagnose argument overflow - if (hasNamedArgs && pMessage) - *pMessage = getMatchError("argument `%s` goes past end of parameter list", arg.toChars()); + if (hasNamedArgs && buf) + getMatchError(*buf, "argument `%s` goes past end of parameter list", arg.toChars()); return null; } while (ci >= newArgs.length) @@ -2665,8 +2672,8 @@ extern (C++) final class TypeFunction : TypeNext if ((*newArgs)[ci]) { - if (pMessage) - *pMessage = getMatchError("parameter `%s` assigned twice", parameterList[ci].toChars()); + if (buf) + getMatchError(*buf, "parameter `%s` assigned twice", parameterList[ci].toChars()); return null; } (*newArgs)[ci++] = arg; @@ -2684,8 +2691,8 @@ extern (C++) final class TypeFunction : TypeNext if (this.incomplete) continue; - if (pMessage) - *pMessage = getMatchError("missing argument for parameter #%d: `%s`", + if (buf) + getMatchError(*buf, "missing argument for parameter #%d: `%s`", i + 1, parameterToChars(parameterList[i], this, false)); return null; } diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index cedc4a4..4a060c9 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -302,7 +302,15 @@ extern (D) bool setGC(FuncDeclaration fd, Loc loc, const(char)* fmt, RootObject if (fmt) fd.nogcViolation = new AttributeViolation(loc, fmt, fd, arg0); // action that requires GC else if (arg0) - fd.nogcViolation = new AttributeViolation(loc, fmt, arg0); // call to non-@nogc function + { + if (auto sa = arg0.isDsymbol()) + { + if (FuncDeclaration fd2 = sa.isFuncDeclaration()) + { + fd.nogcViolation = new AttributeViolation(loc, fd2); // call to non-@nogc function + } + } + } fd.type.toTypeFunction().isNogc = false; if (fd.fes) diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index e8324eb..3e145be 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -6812,7 +6812,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { case TOK.identifier: { - if (commaExpected) error("comma expected separating field initializers"); const t = peek(&token); @@ -6846,6 +6845,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: if (commaExpected) error("comma expected separating field initializers"); + const t = peek(&token); + if (t.value == TOK.colon) + { + error("incorrect syntax for associative array, expected `[]`, found `{}`"); + while (token.value != TOK.rightCurly && token.value != TOK.endOfFile) + { + nextToken(); + } + if (token.value == TOK.rightCurly) + { + nextToken(); + } + break; + } auto value = parseInitializer(); _is.addInit(null, value); commaExpected = true; @@ -8647,7 +8660,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error("expression expected, not `%s`", token.toChars()); Lerr: // Anything for e, as long as it's not NULL - e = new AST.IntegerExp(loc, 0, AST.Type.tint32); + e = AST.ErrorExp.get(); nextToken(); break; } diff --git a/gcc/d/dmd/root/array.d b/gcc/d/dmd/root/array.d index 8135577..6e7db06 100644 --- a/gcc/d/dmd/root/array.d +++ b/gcc/d/dmd/root/array.d @@ -52,7 +52,7 @@ public: ~this() pure nothrow { debug (stomp) memset(data.ptr, 0xFF, data.length); - if (data.ptr != &smallarray[0]) + if (data.ptr && data.ptr != &smallarray[0]) mem.xfree(data.ptr); } ///returns elements comma separated in [] diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index 24d8745..86dff7b 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -21,12 +21,13 @@ import dmd.dcast : implicitConvTo; import dmd.dclass; import dmd.declaration; import dmd.dscope; +import dmd.dsymbol; import dmd.dsymbolsem : determineSize; import dmd.errors; import dmd.expression; import dmd.func; import dmd.funcsem : isRootTraitsCompilesScope; -import dmd.globals : FeatureState; +import dmd.globals : FeatureState, global; import dmd.id; import dmd.identifier; import dmd.location; @@ -316,10 +317,20 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag) return false; } +/************************************** + * Safer D adds safety checks to functions with the default + * trust setting. + */ +bool isSaferD(FuncDeclaration fd) +{ + return fd.type.toTypeFunction().trust == TRUST.default_ && + global.params.safer == FeatureState.enabled; +} + bool isSafe(FuncDeclaration fd) { if (fd.safetyInprocess) - fd.setUnsafe(); + setFunctionToUnsafe(fd); return fd.type.toTypeFunction().trust == TRUST.safe; } @@ -331,48 +342,73 @@ extern (D) bool isSafeBypassingInference(FuncDeclaration fd) bool isTrusted(FuncDeclaration fd) { if (fd.safetyInprocess) - fd.setUnsafe(); + setFunctionToUnsafe(fd); return fd.type.toTypeFunction().trust == TRUST.trusted; } -/************************************** - * The function is doing something unsafe, so mark it as unsafe. - * +/***************************************************** + * Report safety violation for function `fd`, or squirrel away + * error message in fd.safetyViolation if needed later. + * Call when `fd` was just inferred to be @system OR + * `fd` was @safe and an tried something unsafe. * Params: - * fd = func declaration to set unsafe - * gag = surpress error message (used in escape.d) - * loc = location of error - * fmt = printf-style format string + * fd = function we're gonna rat on + * gag = suppress error message (used in escape.d) + * loc = location of error + * format = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier * arg2 = (optional) argument for third %s format specifier - * Returns: whether there's a safe error */ -extern (D) bool setUnsafe( - FuncDeclaration fd, - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, - RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) +extern (D) void reportSafeError(FuncDeclaration fd, bool gag, Loc loc, + const(char)* format = null, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) +{ + if (fd.type.toTypeFunction().trust == TRUST.system) // function was just inferred to be @system + { + if (format) + fd.safetyViolation = new AttributeViolation(loc, format, arg0, arg1, arg2); + else if (arg0) + { + if (FuncDeclaration fd2 = (cast(Dsymbol) arg0).isFuncDeclaration()) + { + fd.safetyViolation = new AttributeViolation(loc, fd2); // call to non-@nogc function + } + } + } + else if (fd.isSafe() || fd.isSaferD()) + { + if (!gag && format) + .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + } +} + + +/********************************************** + * Function is doing something unsafe. If inference + * is in process, commit the function to be @system. + * Params: + * fd = the naughty function + * Returns: + * true if this is a safe function and so an error OR is inferred to be @system, + * false otherwise. + */ +extern (D) bool setFunctionToUnsafe(FuncDeclaration fd) { if (fd.safetyInprocess) { fd.safetyInprocess = false; fd.type.toTypeFunction().trust = TRUST.system; - if (fmt || arg0) - fd.safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1, arg2); if (fd.fes) - fd.fes.func.setUnsafe(); - } - else if (fd.isSafe()) - { - if (!gag && fmt) - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); - + setFunctionToUnsafe(fd.fes.func); return true; } + else if (fd.isSafe() || fd.isSaferD()) + return true; return false; } + /************************************** * The function is calling `@system` function `f`, so mark it as unsafe. * @@ -383,7 +419,12 @@ extern (D) bool setUnsafe( */ extern (D) bool setUnsafeCall(FuncDeclaration fd, FuncDeclaration f) { - return fd.setUnsafe(false, f.loc, null, f, null); + if (setFunctionToUnsafe(fd)) + { + reportSafeError(fd, false, f.loc, null, f, null); + return fd.isSafe(); + } + return false; } /************************************** @@ -394,14 +435,14 @@ extern (D) bool setUnsafeCall(FuncDeclaration fd, FuncDeclaration f) * sc = scope that the unsafe statement / expression is in * gag = surpress error message (used in escape.d) * loc = location of error - * fmt = printf-style format string + * format = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier * arg2 = (optional) argument for third %s format specifier - * Returns: whether there's a safe error + * Returns: whether there is a safe error */ bool setUnsafe(Scope* sc, - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, + bool gag = false, Loc loc = Loc.init, const(char)* format = null, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { if (sc.intypeof) @@ -416,7 +457,7 @@ bool setUnsafe(Scope* sc, { if (sc.varDecl.storage_class & STC.safe) { - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } else if (!(sc.varDecl.storage_class & STC.trusted)) @@ -435,13 +476,21 @@ bool setUnsafe(Scope* sc, { // Message wil be gagged, but still call error() to update global.errors and for // -verrors=spec - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } return false; } - return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2); + if (setFunctionToUnsafe(sc.func)) + { + if (format || arg0) + { + reportSafeError(sc.func, gag, loc, format, arg0, arg1, arg2); + } + return sc.func.isSafe(); // it is only an error if in an @safe function + } + return false; } /*************************************** @@ -459,23 +508,24 @@ bool setUnsafe(Scope* sc, * fs = feature state from the preview flag * gag = surpress error message * loc = location of error - * msg = printf-style format string + * format = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier * arg2 = (optional) argument for third %s format specifier * Returns: whether an actual safe error (not deprecation) occured */ -bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, +bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* format, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - //printf("setUnsafePreview() fs:%d %s\n", fs, msg); + //printf("setUnsafePreview() fs:%d %s\n", fs, fmt); + assert(format); with (FeatureState) final switch (fs) { case disabled: return false; case enabled: - return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2); + return sc.setUnsafe(gag, loc, format, arg0, arg1, arg2); case default_: if (!sc.func) @@ -484,13 +534,13 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) { if (!gag && !sc.isDeprecated()) { - deprecation(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + deprecation(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); } } else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); + sc.func.safetyViolation = new AttributeViolation(loc, format, arg0, arg1, arg2); } return false; } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index c584b84..8138bd2 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -57,7 +57,7 @@ import dmd.opover; import dmd.parse; import dmd.common.outbuffer; import dmd.root.string; -import dmd.safe : isSafe, setUnsafe; +import dmd.safe : isSafe, isSaferD, setUnsafe; import dmd.semantic2; import dmd.sideeffect; import dmd.statement; @@ -779,14 +779,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Dsymbol sapplyOld = sapply; // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors - /* Check for inference errors - */ + /* Check for inference errors and apply mutability checks inline */ if (!inferApplyArgTypes(fs, sc, sapply)) { - /** - Try and extract the parameter count of the opApply callback function, e.g.: - int opApply(int delegate(int, float)) => 2 args - */ bool foundMismatch = false; size_t foreachParamCount = 0; if (sapplyOld) @@ -806,6 +801,19 @@ Statement statementSemanticVisit(Statement s, Scope* sc) auto tf = fparam.type.nextOf().isTypeFunction(); foreachParamCount = tf.parameterList.length; foundMismatch = true; + + // Mutability check + if (fs.aggr && fs.aggr.type && fd.type && fs.aggr.type.isConst() && !fd.type.isConst()) + { + // First error: The call site + error(fs.loc, "mutable method `%s.%s` is not callable using a `const` object", + fd.parent ? fd.parent.toPrettyChars() : "unknown", fd.toChars()); + + // Second error: Suggest how to fix + errorSupplemental(fd.loc, "Consider adding `const` or `inout` here"); + + return setError(); + } } } } @@ -824,6 +832,24 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return setError(); } + // If inference succeeds, proceed with post-checks + if (sapply && sapply.isFuncDeclaration()) + { + FuncDeclaration fd = sapply.isFuncDeclaration(); + + if (fs.aggr && fs.aggr.type && fd.type && fs.aggr.type.isConst() && !fd.type.isConst()) + { + // First error: The call site + error(fs.loc, "mutable method `%s.%s` is not callable using a `const` object", + fd.parent ? fd.parent.toPrettyChars() : "unknown", fd.toChars()); + + // Second error: Suggest how to fix + errorSupplemental(fd.loc, "Consider adding `const` or `inout` here"); + + return setError(); + } + } + Type tab = fs.aggr.type.toBasetype(); if (tab.ty == Ttuple) // don't generate new scope for tuple loops @@ -1961,7 +1987,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } ss.hasDefault = sc.sw.sdefault || - !(!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on || sc.func.isSafe); + !(!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on || sc.func.isSafe || sc.func.isSaferD); if (!ss.hasDefault) { if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()) && !sc.inCfile) diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d index bd3674a..0e9c433 100644 --- a/gcc/d/dmd/templatesem.d +++ b/gcc/d/dmd/templatesem.d @@ -1252,7 +1252,13 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat //printf("farg = %s %s\n", farg.type.toChars(), farg.toChars()); RootObject oarg = farg; - if ((fparam.storageClass & STC.ref_) && (!(fparam.storageClass & STC.auto_) || farg.isLvalue())) + + if (farg.isFuncExp()) + { + // When assigning an untyped (void) lambda `x => y` to a `(F)(ref F)` parameter, + // we don't want to deduce type void creating a void parameter + } + else if ((fparam.storageClass & STC.ref_) && (!(fparam.storageClass & STC.auto_) || farg.isLvalue())) { /* Allow expressions that have CT-known boundaries and type [] to match with [dim] */ diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index 7b32209..f7f4cd2 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -701,6 +701,26 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return isDeclX(d => (d.storage_class & STC.lazy_) != 0); } + if (e.ident == Id.isCOMClass) + { + if (dim != 1) + return dimError(1); + + auto o = (*e.args)[0]; + auto s = getDsymbol(o); + AggregateDeclaration agg; + + if (!s || ((agg = s.isAggregateDeclaration()) is null)) + { + error(e.loc, "argument to `__traits(isCOMClass, %s)` is not a declaration", o.toChars()); + return ErrorExp.get(); + } + + if (ClassDeclaration cd = agg.isClassDeclaration()) + return cd.com ? True() : False(); + else + return False(); + } if (e.ident == Id.identifier) { // Get identifier for symbol as a string literal @@ -776,6 +796,43 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return se.expressionSemantic(sc); } + if (e.ident == Id.getBitfieldOffset || e.ident == Id.getBitfieldWidth) + { + if (dim != 1) + return dimError(1); + + auto o = (*e.args)[0]; + auto s = getDsymbolWithoutExpCtx(o); + if (!s) + { + error(e.loc, "bitfield symbol expected not `%s`", o.toChars()); + return ErrorExp.get(); + } + + auto vd = s.toAlias.isVarDeclaration(); + if (!vd || !(vd.storage_class & STC.field)) + { + error(e.loc, "bitfield symbol expected not %s `%s`", s.kind, s.toPrettyChars); + return ErrorExp.get(); + } + + uint fieldWidth; + uint bitOffset; + if (auto bf = vd.isBitFieldDeclaration()) + { + fieldWidth = bf.fieldWidth; + bitOffset = bf.bitOffset; + } + else // just a regular field + { + const sz = size(vd.type); + assert(sz < uint.max / 8); // overflow check + fieldWidth = cast(uint)sz * 8; + bitOffset = 0; + } + uint value = e.ident == Id.getBitfieldOffset ? bitOffset : fieldWidth; + return new IntegerExp(e.loc, value, Type.tuns32); + } if (e.ident == Id.getProtection || e.ident == Id.getVisibility) { if (dim != 1) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index eebbf45..aea969a 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -753,13 +753,14 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis } const(char)* failMessage; const(char)** pMessage = errorHelper ? &failMessage : null; - auto resolvedArgs = tf.resolveNamedArgs(argumentList, pMessage); + OutBuffer buf; + auto resolvedArgs = tf.resolveNamedArgs(argumentList, errorHelper ? &buf : null); Expression[] args; if (!resolvedArgs) { - if (failMessage) + if (buf.length) { - errorHelper(failMessage); + errorHelper(buf.peekChars()); return MATCH.nomatch; } @@ -820,6 +821,11 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis if (!arg) continue; // default argument m = argumentMatchParameter(tf, p, arg, wildmatch, flag, sc, pMessage); + if (failMessage) + { + buf.reset(); + buf.writestring(failMessage); + } } else if (p.defaultArg) continue; @@ -846,15 +852,17 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis errorHelper(failMessage); return MATCH.nomatch; } - if (pMessage && u >= args.length) - *pMessage = tf.getMatchError("missing argument for parameter #%d: `%s`", - u + 1, parameterToChars(p, tf, false)); - // If an error happened previously, `pMessage` was already filled - else if (pMessage && !*pMessage) - *pMessage = tf.getParamError(args[u], p); - if (errorHelper) - errorHelper(*pMessage); + { + if (u >= args.length) + TypeFunction.getMatchError(buf, "missing argument for parameter #%d: `%s`", + u + 1, parameterToChars(p, tf, false)); + // If an error happened previously, `pMessage` was already filled + else if (buf.length == 0) + buf.writestring(tf.getParamError(args[u], p)); + + errorHelper(buf.peekChars()); + } return MATCH.nomatch; } if (m < match) @@ -864,7 +872,9 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis if (errorHelper && !parameterList.varargs && args.length > nparams) { // all parameters had a match, but there are surplus args - errorHelper(tf.getMatchError("expected %d argument(s), not %d", nparams, args.length)); + OutBuffer buf2; + TypeFunction.getMatchError(buf2, "expected %d argument(s), not %d", nparams, args.length); + errorHelper(buf2.extractChars()); return MATCH.nomatch; } //printf("match = %d\n", match); @@ -1174,8 +1184,12 @@ private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p, if (sz != trailingArgs.length) { if (pMessage) - *pMessage = tf.getMatchError("expected %llu variadic argument(s), not %zu", + { + OutBuffer buf; + TypeFunction.getMatchError(buf, "expected %llu variadic argument(s), not %zu", sz, trailingArgs.length); + *pMessage = buf.extractChars(); + } return MATCH.nomatch; } goto case Tarray; |