aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-07 20:49:06 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-11 19:18:03 +0100
commitc9f7090d930504db772557c18f16599e03d616ea (patch)
tree0b4658e755356787447f7c721919608e4da0cddc /gcc/d/dmd
parent292be6817150ed11d599b6ac92269041ed62eb3a (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/d/dmd/README.md2
-rw-r--r--gcc/d/dmd/canthrow.d2
-rw-r--r--gcc/d/dmd/dcast.d2
-rw-r--r--gcc/d/dmd/dinterpret.d32
-rw-r--r--gcc/d/dmd/dscope.d10
-rw-r--r--gcc/d/dmd/enumsem.d2
-rw-r--r--gcc/d/dmd/errors.d35
-rw-r--r--gcc/d/dmd/errorsink.d117
-rw-r--r--gcc/d/dmd/escape.d2
-rw-r--r--gcc/d/dmd/expression.d7
-rw-r--r--gcc/d/dmd/expressionsem.d316
-rw-r--r--gcc/d/dmd/func.d48
-rw-r--r--gcc/d/dmd/funcsem.d10
-rw-r--r--gcc/d/dmd/globals.d13
-rw-r--r--gcc/d/dmd/globals.h10
-rw-r--r--gcc/d/dmd/id.d4
-rw-r--r--gcc/d/dmd/intrange.d22
-rw-r--r--gcc/d/dmd/lexer.d40
-rw-r--r--gcc/d/dmd/mtype.d37
-rw-r--r--gcc/d/dmd/nogc.d10
-rw-r--r--gcc/d/dmd/parse.d17
-rw-r--r--gcc/d/dmd/root/array.d2
-rw-r--r--gcc/d/dmd/safe.d124
-rw-r--r--gcc/d/dmd/statementsem.d42
-rw-r--r--gcc/d/dmd/templatesem.d8
-rw-r--r--gcc/d/dmd/traits.d57
-rw-r--r--gcc/d/dmd/typesem.d40
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("&quot;", `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("&quot", `unterminated named entity &quot;`, '?', 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;