[gcc r16-7181] d: Merge upstream dmd, druntime 1017635a96, phobos 5a142da0a
Iain Buclaw
ibuclaw@gcc.gnu.org
Fri Jan 30 10:26:17 GMT 2026
https://gcc.gnu.org/g:919b6fa6adcc102f95b17c13e8bdc26fd4ec1394
commit r16-7181-g919b6fa6adcc102f95b17c13e8bdc26fd4ec1394
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date: Fri Jan 30 10:25:49 2026 +0100
d: Merge upstream dmd, druntime 1017635a96, phobos 5a142da0a
D front-end changes:
- Import dmd v2.112.0-beta.1.
D runtime changes:
- Import druntime v2.112.0-beta.1.
- Added 64-bit `mul' and `udivmod' overloads to `core.int128'.
Phobos changes:
- Added `lazyCache' to `std.algorithm.iteration'.
- Added `writeText', `writeWText', and `writeDText' to
`std.conv'.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 1017635a96.
* dmd/VERSION: Bump version to v2.112.0-beta.1.
* decl.cc (DeclVisitor::finish_vtable): Update for new front-end
interface.
(DeclVisitor::visit): Likewise.
* typeinfo.cc (TypeInfoVisitor::visit): Likewise.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 1017635a96.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES_LINUX): Add
core/sys/linux/sys/syscall.d, core/sys/linux/syscall.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 5a142da0a.
* src/Makefile.am (PHOBOS_DSOURCES): Remove
std/internal/windows/bcrypt.d.
* src/Makefile.in: Regenerate.
gcc/testsuite/ChangeLog:
* gdc.dg/asm1.d: Adjust test.
Diff:
---
gcc/d/decl.cc | 4 +-
gcc/d/dmd/MERGE | 2 +-
gcc/d/dmd/VERSION | 2 +-
gcc/d/dmd/aggregate.d | 2 -
gcc/d/dmd/aggregate.h | 6 +-
gcc/d/dmd/arraytypes.d | 1 +
gcc/d/dmd/arraytypes.h | 2 +
gcc/d/dmd/attrib.d | 5 -
gcc/d/dmd/attrib.h | 1 -
gcc/d/dmd/cond.d | 116 +-
gcc/d/dmd/cond.h | 4 -
gcc/d/dmd/cparse.d | 332 +++---
gcc/d/dmd/cxxfrontend.d | 27 +-
gcc/d/dmd/dcast.d | 44 +-
gcc/d/dmd/dclass.d | 212 ----
gcc/d/dmd/declaration.d | 103 --
gcc/d/dmd/declaration.h | 4 +-
gcc/d/dmd/delegatize.d | 1 +
gcc/d/dmd/dinterpret.d | 64 +-
gcc/d/dmd/dmodule.d | 99 +-
gcc/d/dmd/dscope.d | 2 +-
gcc/d/dmd/dstruct.d | 223 +---
gcc/d/dmd/dsymbol.d | 79 +-
gcc/d/dmd/dsymbol.h | 5 +-
gcc/d/dmd/dsymbolsem.d | 893 +++++++++++++-
gcc/d/dmd/dtemplate.d | 17 +-
gcc/d/dmd/enumsem.d | 140 +--
gcc/d/dmd/expression.d | 43 +-
gcc/d/dmd/expression.h | 29 +-
gcc/d/dmd/expressionsem.d | 364 ++++--
gcc/d/dmd/func.d | 6 +-
gcc/d/dmd/funcsem.d | 1252 ++++++++++++--------
gcc/d/dmd/hdrgen.d | 14 +-
gcc/d/dmd/iasmgcc.d | 53 +-
gcc/d/dmd/id.d | 1 -
gcc/d/dmd/imphint.d | 24 +
gcc/d/dmd/importc.d | 132 ++-
gcc/d/dmd/initsem.d | 47 +-
gcc/d/dmd/location.d | 127 +-
gcc/d/dmd/mangle/package.d | 6 +-
gcc/d/dmd/mtype.d | 10 +-
gcc/d/dmd/mtype.h | 2 +
gcc/d/dmd/nogc.d | 57 +-
gcc/d/dmd/nspace.d | 6 -
gcc/d/dmd/nspace.h | 1 -
gcc/d/dmd/optimize.d | 3 +-
gcc/d/dmd/parse.d | 81 +-
gcc/d/dmd/semantic2.d | 16 +-
gcc/d/dmd/semantic3.d | 4 +-
gcc/d/dmd/statementsem.d | 32 +-
gcc/d/dmd/template.h | 2 +-
gcc/d/dmd/templatesem.d | 13 +-
gcc/d/dmd/traits.d | 2 +-
gcc/d/dmd/typesem.d | 95 +-
gcc/d/typeinfo.cc | 4 +-
gcc/testsuite/gdc.dg/asm1.d | 12 +-
.../gdc.test/compilable/imports/cstuff3.c | 13 +
.../gdc.test/compilable/imports/imp18127a.c | 74 ++
.../gdc.test/compilable/imports/imp18127b.c | 74 ++
.../gdc.test/compilable/imports/imp20344.c | 2 +
.../gdc.test/compilable/imports/imp20499.c | 8 +
gcc/testsuite/gdc.test/compilable/test18127.d | 5 +
gcc/testsuite/gdc.test/compilable/test20344.d | 14 +
gcc/testsuite/gdc.test/compilable/test20499.d | 3 +
gcc/testsuite/gdc.test/compilable/test3004.d | 2 +-
gcc/testsuite/gdc.test/compilable/testcstuff3.d | 19 +
gcc/testsuite/gdc.test/compilable/uda_lambda.d | 3 +
gcc/testsuite/gdc.test/compilable/vcg-ast.d | 11 +
gcc/testsuite/gdc.test/fail_compilation/b23686.d | 2 +-
.../gdc.test/fail_compilation/checkimports2.d | 10 +-
.../gdc.test/fail_compilation/diag10405.d | 11 -
.../gdc.test/fail_compilation/diag20888.d | 10 +-
.../gdc.test/fail_compilation/diag23384.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/diag9679.d | 19 +-
.../fail_compilation/diag_ptr_conversion.d | 17 +
.../fail_compilation/enum_auto_increment.d | 18 +
gcc/testsuite/gdc.test/fail_compilation/fail109.d | 14 +-
.../gdc.test/fail_compilation/fail11714.d | 6 +-
.../gdc.test/fail_compilation/fail15361.d | 3 +-
.../gdc.test/fail_compilation/fail15616b.d | 2 +-
gcc/testsuite/gdc.test/fail_compilation/fail16.d | 5 +-
gcc/testsuite/gdc.test/fail_compilation/fail163.d | 16 +-
.../gdc.test/fail_compilation/fail18219.d | 11 +-
.../gdc.test/fail_compilation/fail19103.d | 4 +-
gcc/testsuite/gdc.test/fail_compilation/fail196.d | 2 +-
.../gdc.test/fail_compilation/fail21547.d | 6 +-
.../gdc.test/fail_compilation/fail23439.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/fail305.d | 11 -
gcc/testsuite/gdc.test/fail_compilation/fail336.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/fail347.d | 8 +-
gcc/testsuite/gdc.test/fail_compilation/fail41.d | 18 -
gcc/testsuite/gdc.test/fail_compilation/fail98.d | 5 +-
.../gdc.test/fail_compilation/fail_pretty_errors.d | 2 +-
.../gdc.test/fail_compilation/failcontracts.d | 17 +-
gcc/testsuite/gdc.test/fail_compilation/fix19613.d | 16 +
gcc/testsuite/gdc.test/fail_compilation/fix20075.d | 21 +
gcc/testsuite/gdc.test/fail_compilation/fix20318.d | 46 +
gcc/testsuite/gdc.test/fail_compilation/fix20867.d | 20 +
gcc/testsuite/gdc.test/fail_compilation/fix21042.d | 15 +
gcc/testsuite/gdc.test/fail_compilation/fix21165.d | 30 +
gcc/testsuite/gdc.test/fail_compilation/fix21166.d | 13 +
.../gdc.test/fail_compilation/hidden_ctor.d | 27 +
gcc/testsuite/gdc.test/fail_compilation/ice11153.d | 5 +-
gcc/testsuite/gdc.test/fail_compilation/ice19755.d | 5 +-
.../gdc.test/fail_compilation/imports/imp18127a.c | 83 ++
.../gdc.test/fail_compilation/imports/imp18127b.c | 80 ++
gcc/testsuite/gdc.test/fail_compilation/lookup.d | 10 +-
.../gdc.test/fail_compilation/mixinprop.d | 4 +-
.../fail_compilation/named_arguments_error.d | 35 +-
.../fail_compilation/named_arguments_ifti_error.d | 15 +-
gcc/testsuite/gdc.test/fail_compilation/nogc3.d | 30 +
.../gdc.test/fail_compilation/nonvoid_return.d | 37 +
.../gdc.test/fail_compilation/noreturn2.d | 2 +-
.../gdc.test/fail_compilation/powinline.d | 38 +
.../gdc.test/fail_compilation/retscope3.d | 10 +
.../gdc.test/fail_compilation/seq_assign.d | 43 +
.../gdc.test/fail_compilation/test15989.d | 8 +-
.../gdc.test/fail_compilation/test18127.d | 106 ++
.../gdc.test/fail_compilation/test19661.d | 3 +-
.../gdc.test/fail_compilation/test20489.d | 20 +
.../gdc.test/fail_compilation/test21215.d | 35 +
.../gdc.test/fail_compilation/test21304.d | 6 +
.../gdc.test/fail_compilation/test21317.d | 39 +
.../gdc.test/fail_compilation/testrvaluecpctor.d | 2 +-
.../gdc.test/fail_compilation/uda_lambda.d | 7 +
.../gdc.test/fail_compilation/union_conv.d | 2 +-
gcc/testsuite/gdc.test/runnable/placenew.d | 43 +
gcc/testsuite/gdc.test/runnable/powinline.d | 64 +
gcc/testsuite/gdc.test/runnable/testaa2.d | 21 +
gcc/testsuite/gdc.test/runnable/testinvariant.d | 47 +-
libphobos/libdruntime/MERGE | 2 +-
libphobos/libdruntime/Makefile.am | 5 +-
libphobos/libdruntime/Makefile.in | 12 +-
libphobos/libdruntime/core/int128.d | 245 ++--
.../libdruntime/core/internal/array/capacity.d | 344 +++++-
.../core/internal/array/concatenation.d | 47 +-
.../libdruntime/core/internal/array/construction.d | 6 +-
libphobos/libdruntime/core/internal/array/utils.d | 25 +
libphobos/libdruntime/core/internal/lifetime.d | 19 +
libphobos/libdruntime/core/stdc/fenv.d | 5 +
libphobos/libdruntime/core/stdc/math.d | 36 +-
libphobos/libdruntime/core/stdc/stdarg.d | 2 +-
libphobos/libdruntime/core/sys/bionic/err.d | 2 +-
libphobos/libdruntime/core/sys/bionic/string.d | 2 +-
libphobos/libdruntime/core/sys/darwin/err.d | 2 +-
libphobos/libdruntime/core/sys/darwin/string.d | 2 +-
libphobos/libdruntime/core/sys/dragonflybsd/err.d | 2 +-
.../libdruntime/core/sys/dragonflybsd/string.d | 2 +-
libphobos/libdruntime/core/sys/freebsd/err.d | 2 +-
libphobos/libdruntime/core/sys/freebsd/string.d | 2 +-
libphobos/libdruntime/core/sys/linux/err.d | 2 +-
.../libdruntime/core/sys/linux/linux/if_packet.d | 2 +-
libphobos/libdruntime/core/sys/linux/netinet/in_.d | 14 +-
libphobos/libdruntime/core/sys/linux/perf_event.d | 77 +-
libphobos/libdruntime/core/sys/linux/sched.d | 30 +-
libphobos/libdruntime/core/sys/linux/string.d | 2 +-
libphobos/libdruntime/core/sys/linux/sys/syscall.d | 127 ++
libphobos/libdruntime/core/sys/linux/sys/time.d | 8 +-
libphobos/libdruntime/core/sys/linux/syscall.d | 14 +
libphobos/libdruntime/core/sys/linux/unistd.d | 5 +
libphobos/libdruntime/core/sys/netbsd/err.d | 2 +-
libphobos/libdruntime/core/sys/netbsd/string.d | 2 +-
.../libdruntime/core/sys/netbsd/sys/featuretest.d | 2 +-
libphobos/libdruntime/core/sys/openbsd/err.d | 2 +-
libphobos/libdruntime/core/sys/openbsd/string.d | 2 +-
libphobos/libdruntime/core/sys/posix/netdb.d | 20 +-
libphobos/libdruntime/core/sys/posix/netinet/in_.d | 202 ++--
libphobos/libdruntime/core/sys/posix/signal.d | 21 +-
libphobos/libdruntime/core/sys/posix/sys/ioctl.d | 10 +-
libphobos/libdruntime/core/sys/posix/sys/select.d | 104 +-
libphobos/libdruntime/core/sys/posix/sys/socket.d | 14 +-
libphobos/libdruntime/core/sys/posix/sys/stat.d | 162 +--
libphobos/libdruntime/core/sys/posix/sys/wait.d | 152 +--
libphobos/libdruntime/core/sys/solaris/err.d | 2 +-
libphobos/libdruntime/core/sys/windows/basetsd.d | 38 +-
libphobos/libdruntime/core/sys/windows/commctrl.d | 4 +-
libphobos/libdruntime/core/sys/windows/dde.d | 60 +-
libphobos/libdruntime/core/sys/windows/mmsystem.d | 26 +-
libphobos/libdruntime/core/sys/windows/ntdef.d | 8 +-
libphobos/libdruntime/core/sys/windows/ntsecapi.d | 2 +-
libphobos/libdruntime/core/sys/windows/oleauto.d | 2 +-
libphobos/libdruntime/core/sys/windows/shlobj.d | 146 +--
libphobos/libdruntime/core/sys/windows/stat.d | 10 +-
libphobos/libdruntime/core/sys/windows/threadaux.d | 4 +-
libphobos/libdruntime/core/sys/windows/vfw.d | 138 +--
libphobos/libdruntime/core/sys/windows/winbase.d | 16 +-
libphobos/libdruntime/core/sys/windows/wincrypt.d | 10 +-
libphobos/libdruntime/core/sys/windows/winnt.d | 46 +-
libphobos/libdruntime/core/sys/windows/winuser.d | 12 +-
libphobos/libdruntime/core/volatile.d | 2 +-
libphobos/libdruntime/object.d | 19 +-
libphobos/libdruntime/rt/lifetime.d | 366 ------
libphobos/libdruntime/rt/minfo.d | 3 +
libphobos/src/MERGE | 2 +-
libphobos/src/Makefile.am | 17 +-
libphobos/src/Makefile.in | 19 +-
libphobos/src/std/algorithm/iteration.d | 361 ++++--
libphobos/src/std/algorithm/searching.d | 75 +-
libphobos/src/std/complex.d | 41 +-
libphobos/src/std/container/rbtree.d | 25 +
libphobos/src/std/conv.d | 533 +++++++--
libphobos/src/std/encoding.d | 2 +-
libphobos/src/std/file.d | 27 +-
libphobos/src/std/format/internal/write.d | 20 +-
libphobos/src/std/format/write.d | 11 +-
libphobos/src/std/functional.d | 1 -
libphobos/src/std/internal/math/biguintcore.d | 83 +-
libphobos/src/std/internal/windows/bcrypt.d | 65 -
libphobos/src/std/json.d | 47 +
libphobos/src/std/math/algebraic.d | 48 +-
libphobos/src/std/math/exponential.d | 43 +-
libphobos/src/std/net/curl.d | 3 +-
libphobos/src/std/path.d | 7 +-
libphobos/src/std/random.d | 84 +-
libphobos/src/std/sumtype.d | 26 +-
libphobos/src/std/traits.d | 9 +-
libphobos/src/std/uuid.d | 60 +-
libphobos/src/std/variant.d | 52 +-
218 files changed, 6741 insertions(+), 3845 deletions(-)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index c43270c61e2c..0b915b5632a4 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -534,7 +534,7 @@ public:
{
FuncDeclaration *fd = d->vtbl[i]->isFuncDeclaration ();
- if (!fd || (!fd->fbody && d->isAbstract ()))
+ if (!fd || (!fd->fbody && dmd::isAbstract (d)))
continue;
/* Ensure function has a return value. */
@@ -643,7 +643,7 @@ public:
{
FuncDeclaration *fd = d->vtbl[i]->isFuncDeclaration ();
- if (fd && (fd->fbody || !d->isAbstract ()))
+ if (fd && (fd->fbody || !dmd::isAbstract (d)))
{
CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
build_address (get_symbol_decl (fd)));
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 58d19b4e951d..62d90e5770b5 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-956e73d64e532a68213970316c2590c572ec03f3
+1017635a9636ef6a7a4bda35b1e091875d829871
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index e972d6e93a4d..67e32f8d7ef1 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.111.0
+v2.112.0-beta.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 51d6fc459539..6359674d4471 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -187,8 +187,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
return fields.length - isNested() - (vthis2 !is null);
}
- abstract void finalizeSize();
-
override final uinteger_t size(Loc loc)
{
//printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 82f8aeca0808..d89755cea27c 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -120,7 +120,6 @@ public:
Sizeok sizeok; // set when structsize contains valid data
virtual Scope *newScope(Scope *sc);
- virtual void finalizeSize() = 0;
uinteger_t size(Loc loc) override final;
Type *getType() override final;
bool isDeprecated() const override final; // is aggregate deprecated?
@@ -172,7 +171,6 @@ public:
static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s) override;
const char *kind() const override;
- void finalizeSize() override final;
bool isPOD();
bool zeroInit() const; // !=0 if initialize with 0 fill
bool zeroInit(bool v);
@@ -196,7 +194,7 @@ public:
unsigned numArgTypes() const;
Type *argType(unsigned index);
- bool hasRegularCtor(bool checkDisabled = false);
+ bool hasRegularCtor(bool ignoreDisabled = false);
};
class UnionDeclaration final : public StructDeclaration
@@ -287,13 +285,11 @@ public:
virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
bool isBaseInfoComplete();
- void finalizeSize() override;
bool hasMonitor();
bool isCOMclass() const;
virtual bool isCOMinterface() const;
bool isCPPclass() const;
virtual bool isCPPinterface() const;
- bool isAbstract();
virtual int vtblOffset() const;
const char *kind() const override;
diff --git a/gcc/d/dmd/arraytypes.d b/gcc/d/dmd/arraytypes.d
index 2cd446ea5ed7..bed684b3a425 100644
--- a/gcc/d/dmd/arraytypes.d
+++ b/gcc/d/dmd/arraytypes.d
@@ -29,6 +29,7 @@ alias Strings = Array!(const(char)*);
alias Identifiers = Array!(Identifier);
alias TemplateParameters = Array!(TemplateParameter);
alias Expressions = Array!(Expression);
+alias ArgumentLabels = Array!(ArgumentLabel);
alias Statements = Array!(Statement);
alias BaseClasses = Array!(BaseClass*);
alias ClassDeclarations = Array!(ClassDeclaration);
diff --git a/gcc/d/dmd/arraytypes.h b/gcc/d/dmd/arraytypes.h
index 28165f3ed8ea..a06144332db5 100644
--- a/gcc/d/dmd/arraytypes.h
+++ b/gcc/d/dmd/arraytypes.h
@@ -17,6 +17,8 @@ typedef Array<class TemplateParameter *> TemplateParameters;
typedef Array<class Expression *> Expressions;
+typedef Array<struct ArgumentLabel> ArgumentLabels;
+
typedef Array<class Statement *> Statements;
typedef Array<struct BaseClass *> BaseClasses;
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 1bfe7902a920..a03e7bbdc0e5 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -110,11 +110,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
return "attribute";
}
- override final bool hasPointers()
- {
- return this.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
- }
-
/****************************************
*/
override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index ef37e0adece1..24d91abc6275 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -29,7 +29,6 @@ class AttribDeclaration : public Dsymbol
public:
Dsymbols *decl; // array of Dsymbol's
const char *kind() const override;
- bool hasPointers() override final;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 1b11a9f1803b..31c01f1853e6 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -24,7 +24,6 @@ import dmd.dscope;
import dmd.dsymbol;
import dmd.errors;
import dmd.expression;
-import dmd.expressionsem : evalStaticCondition;
import dmd.globals;
import dmd.identifier;
import dmd.location;
@@ -71,8 +70,6 @@ extern (C++) abstract class Condition : ASTNode
abstract Condition syntaxCopy();
- abstract int include(Scope* sc);
-
inout(DebugCondition) isDebugCondition() inout
{
return null;
@@ -324,39 +321,6 @@ extern (C++) final class DebugCondition : DVCondition
super(loc, mod, ident);
}
- override int include(Scope* sc)
- {
- //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
- if (inc != Include.notComputed)
- {
- return inc == Include.yes;
- }
- inc = Include.no;
- bool definedInModule = false;
- if (ident)
- {
- if (mod.debugids && findCondition(*mod.debugids, ident))
- {
- inc = Include.yes;
- definedInModule = true;
- }
- else if (findCondition(global.debugids, ident))
- inc = Include.yes;
- else
- {
- if (!mod.debugidsNot)
- mod.debugidsNot = new Identifiers();
- mod.debugidsNot.push(ident);
- }
- }
- else if (global.params.debugEnabled)
- inc = Include.yes;
-
- if (!definedInModule)
- printDepsConditional(sc, this, "depsDebug ");
- return (inc == Include.yes);
- }
-
override inout(DebugCondition) isDebugCondition() inout
{
return this;
@@ -390,7 +354,7 @@ extern (C++) final class VersionCondition : DVCondition
* Returns:
* `true` if it is reserved, `false` otherwise
*/
- extern(D) private static bool isReserved(const(char)[] ident) @safe
+ extern(D) public static bool isReserved(const(char)[] ident) @safe
{
// This list doesn't include "D_*" versions, see the last return
switch (ident)
@@ -599,41 +563,6 @@ extern (C++) final class VersionCondition : DVCondition
super(loc, mod, ident);
}
- override int include(Scope* sc)
- {
- //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
- //if (ident) printf("\tident = '%s'\n", ident.toChars());
- if (inc != Include.notComputed)
- {
- return inc == Include.yes;
- }
-
- inc = Include.no;
- bool definedInModule = false;
- if (ident)
- {
- if (mod.versionids && findCondition(*mod.versionids, ident))
- {
- inc = Include.yes;
- definedInModule = true;
- }
- else if (findCondition(global.versionids, ident))
- inc = Include.yes;
- else
- {
- if (!mod.versionidsNot)
- mod.versionidsNot = new Identifiers();
- mod.versionidsNot.push(ident);
- }
- }
- if (!definedInModule &&
- (!ident || (!isReserved(ident.toString()) && ident != Id._unittest && ident != Id._assert)))
- {
- printDepsConditional(sc, this, "depsVersion ");
- }
- return (inc == Include.yes);
- }
-
override inout(VersionCondition) isVersionCondition() inout
{
return this;
@@ -662,47 +591,6 @@ extern (C++) final class StaticIfCondition : Condition
return new StaticIfCondition(loc, exp.syntaxCopy());
}
- override int include(Scope* sc)
- {
- // printf("StaticIfCondition::include(sc = %p) this=%p inc = %d\n", sc, this, inc);
-
- int errorReturn()
- {
- if (!global.gag)
- inc = Include.no; // so we don't see the error message again
- return 0;
- }
-
- if (inc != Include.notComputed)
- {
- return inc == Include.yes;
- }
-
- if (!sc)
- {
- error(loc, "`static if` conditional cannot be at global scope");
- inc = Include.no;
- return 0;
- }
-
- import dmd.staticcond;
- bool errors;
-
- bool result = evalStaticCondition(sc, exp, exp, errors);
-
- // Prevent repeated condition evaluation.
- // See: fail_compilation/fail7815.d
- if (inc != Include.notComputed)
- return (inc == Include.yes);
- if (errors)
- return errorReturn();
- if (result)
- inc = Include.yes;
- else
- inc = Include.no;
- return (inc == Include.yes);
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -734,7 +622,7 @@ bool findCondition(ref Identifiers ids, Identifier ident) @safe nothrow pure
}
// Helper for printing dependency information
-private void printDepsConditional(Scope* sc, DVCondition condition, const(char)[] depType)
+public void printDepsConditional(Scope* sc, DVCondition condition, const(char)[] depType)
{
if (!global.params.moduleDeps.buffer || global.params.moduleDeps.name)
return;
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index 174a8fb9aafc..0afa042f9daa 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -38,7 +38,6 @@ public:
DYNCAST dyncast() const override final { return DYNCAST_CONDITION; }
virtual Condition *syntaxCopy() = 0;
- virtual int include(Scope *sc) = 0;
virtual DebugCondition *isDebugCondition() { return nullptr; }
virtual VersionCondition *isVersionCondition() { return nullptr; }
void accept(Visitor *v) override { v->visit(this); }
@@ -70,7 +69,6 @@ class DebugCondition final : public DVCondition
public:
static void addGlobalIdent(const char *ident);
- int include(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -80,7 +78,6 @@ public:
static void addGlobalIdent(const char *ident);
static void addPredefinedGlobalIdent(const char *ident);
- int include(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -90,6 +87,5 @@ public:
Expression *exp;
StaticIfCondition *syntaxCopy() override;
- int include(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 1a2a1e9470ea..70369ba20c7a 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -832,8 +832,8 @@ final class CParser(AST) : Parser!AST
const len2 = token.len;
len = len1 + len2;
auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof);
- memcpy(s2, s, len1 * char.sizeof);
- memcpy(s2 + len1, token.ustring, len2 * char.sizeof);
+ s2[0 .. len1] = s[0 .. len1];
+ s2[len1 .. len1 + len2] = token.ustring[0 .. len2];
s = s2;
}
else
@@ -982,6 +982,7 @@ final class CParser(AST) : Parser!AST
* sizeof unary-expression
* sizeof ( type-name )
* _Alignof ( type-name )
+ * _Alignof unary-expression // gcc extension
*
* unary-operator:
* & * + - ~ !
@@ -1044,8 +1045,10 @@ final class CParser(AST) : Parser!AST
e = new AST.ComExp(loc, e);
break;
+ case TOK._Alignof:
case TOK.sizeof_:
{
+ Identifier id = token.value == TOK.sizeof_? Id.__sizeof : Id.__xalignof;
nextToken();
if (token.value == TOK.leftParenthesis)
{
@@ -1084,7 +1087,7 @@ final class CParser(AST) : Parser!AST
e = cparseUnaryExp();
}
- e = new AST.DotIdExp(loc, e, Id.__sizeof);
+ e = new AST.DotIdExp(loc, e, id);
break;
}
@@ -1096,17 +1099,6 @@ final class CParser(AST) : Parser!AST
e = cparseCastExp();
break;
- case TOK._Alignof:
- {
- nextToken();
- check(TOK.leftParenthesis);
- auto t = cparseTypeName();
- check(TOK.rightParenthesis);
- e = new AST.TypeExp(loc, t);
- e = new AST.DotIdExp(loc, e, Id.__xalignof);
- break;
- }
-
default:
e = cparsePostfixExp(e);
break;
@@ -1728,6 +1720,34 @@ final class CParser(AST) : Parser!AST
/********************************* Declaration Parser ***************************/
//{
+ void declareTag(AST.TypeTag tt, ref Specifier specifier, bool generate_enum_id = false)
+ {
+ if (!tt.id && (generate_enum_id || tt.tok != TOK.enum_)) tt.id = Identifier.generateId("__tag");
+ /* `struct tag;` and `struct tag { ... };`
+ * always result in a declaration in the current scope
+ */
+ auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
+ (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) :
+ new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
+ if (!tt.alignExps && !tt.packalign.isUnknown())
+ {
+ // saw `struct __declspec(align(N)) Tag ...`
+ auto st = stag.isStructDeclaration();
+ st.alignment = tt.packalign;
+ }
+ stag.members = tt.members;
+ tt.members = null;
+ if (!symbols)
+ symbols = new AST.Dsymbols();
+ AST.Dsymbol stags = stag;
+ if (tt.alignExps)
+ {
+ auto decls = new AST.Dsymbols(1);
+ (*decls)[0] = stags;
+ stags = new AST.AlignDeclaration(stags.loc, tt.alignExps, decls);
+ }
+ symbols.push(stags);
+ }
/*************************************
* C11 6.7
* declaration:
@@ -1775,28 +1795,9 @@ final class CParser(AST) : Parser!AST
specifier.packalign = this.packalign;
auto tspec = cparseDeclarationSpecifiers(level, specifier);
- AST.Dsymbol declareTag(AST.TypeTag tt, ref Specifier specifier)
- {
- /* `struct tag;` and `struct tag { ... };`
- * always result in a declaration in the current scope
- */
- auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
- (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) :
- new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
- if (!tt.packalign.isUnknown())
- {
- // saw `struct __declspec(align(N)) Tag ...`
- auto st = stag.isStructDeclaration();
- st.alignment = tt.packalign;
- }
- stag.members = tt.members;
- tt.members = null;
- if (!symbols)
- symbols = new AST.Dsymbols();
- auto stags = applySpecifier(stag, specifier);
- symbols.push(stags);
- return stags;
- }
+ // Defer declaring a tagged type (struct/union/enum) so
+ // that anonymous types can use a typedef as their id.
+
/* If a declarator does not follow, it is unnamed
*/
@@ -1822,12 +1823,13 @@ final class CParser(AST) : Parser!AST
!tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
return; // legal but meaningless empty declaration, ignore it
- auto stags = declareTag(tt, specifier);
+ if (tt.members || tt.tok != TOK.enum_)
+ declareTag(tt, specifier);
if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it
{
if (!tt.members)
- error(tt.loc, "`enum %s` has no members", stags.toChars());
+ error(tt.loc, "`enum %s` has no members", tt.toChars());
}
return;
}
@@ -1840,6 +1842,15 @@ final class CParser(AST) : Parser!AST
return;
}
+ if (auto tt = tspec.isTypeTag())
+ {
+ if (tt.id && tt.members)
+ {
+ // Valid tag decl with name and members, go ahead and declare it now.
+ declareTag(tt, specifier);
+ }
+ }
+
if (tspec && specifier.mod & MOD.xconst)
{
tspec = toConst(tspec);
@@ -1867,7 +1878,7 @@ final class CParser(AST) : Parser!AST
{
Identifier id;
AST.StringExp asmName;
- auto dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier);
+ auto dt = cparseDeclarator(DTR.xdirect_fd, tspec, id, specifier);
if (!dt)
{
panic();
@@ -1913,10 +1924,14 @@ final class CParser(AST) : Parser!AST
break;
}
- if (specifier.alignExps && dt.isTypeFunction())
- error("no alignment-specifier for function declaration"); // C11 6.7.5-2
- if (specifier.alignExps && specifier.scw == SCW.xregister)
- error("no alignment-specifier for `register` storage class"); // C11 6.7.5-2
+
+ // Check alignasExp and not alignExps so that gnu
+ // __atribute__((aligned())) is silently allowed, matching the
+ // behavior of other compilers.
+ if (specifier.alignasExp && dt.isTypeFunction())
+ error(specifier.alignasExp.loc, "no alignment-specifier for function declaration"); // C11 6.7.5-2
+ if (specifier.alignasExp && specifier.scw == SCW.xregister)
+ error(specifier.alignasExp.loc, "no alignment-specifier for `register` storage class"); // C11 6.7.5-2
/* C11 6.9.1 Function Definitions
* function-definition:
@@ -1952,7 +1967,7 @@ final class CParser(AST) : Parser!AST
typedefTab.setDim(typedefTabLengthSave);
symbols = symbolsSave;
if (!symbols)
- symbols = new AST.Dsymbols; // lazilly create it
+ symbols = new AST.Dsymbols; // lazily create it
if (level != LVL.global && !tspec && !specifier.scw && !specifier.mod)
error("declaration-specifier-seq required");
@@ -1960,8 +1975,8 @@ final class CParser(AST) : Parser!AST
{
if (token.value == TOK.assign)
error("no initializer for typedef declaration");
- if (specifier.alignExps)
- error("no alignment-specifier for typedef declaration"); // C11 6.7.5-2
+ if (specifier.alignasExp)
+ error(specifier.alignasExp.loc, "no alignment-specifier for typedef declaration"); // C11 6.7.5-2
if (specifier.vector_size)
{
@@ -1973,38 +1988,33 @@ final class CParser(AST) : Parser!AST
bool isalias = true;
Identifier idt;
- if (auto ts = dt.isTypeStruct())
- {
- if (ts.sym.isAnonymous())
- {
- // This is a typedef for an anonymous struct-or-union.
- // Directly set the ident for the struct-or-union.
- ts.sym.ident = id;
- isalias = false;
- }
- idt = ts.sym.ident;
- }
- else if (auto te = dt.isTypeEnum())
- {
- if (te.sym.isAnonymous())
- {
- // This is a typedef for an anonymous enum.
- te.sym.ident = id;
- isalias = false;
- }
- idt = te.sym.ident;
- }
- else if (auto tt = dt.isTypeTag())
+ if (auto tt = dt.isTypeTag())
{
if (!tt.id && id)
/* This applies for enums declared as
* typedef enum {A} E;
+ * Or for similar structs and unions.
*/
tt.id = id;
- Specifier spec;
- declareTag(tt, spec);
+ if (tt.members)
+ {
+ Specifier spec;
+ declareTag(tt, spec);
+ }
idt = tt.id;
}
+ else if (auto tt = tspec.isTypeTag())
+ {
+ // The unusual situation of an anonymous typedef struct where the
+ // first typedef can't be used as its name.
+ // Just declare it now so we can get a valid id.
+ if (!tt.id && tt.members)
+ {
+ Specifier spec;
+ declareTag(tt, spec, true);
+ idt = tt.id;
+ }
+ }
if (isalias)
{
//printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars());
@@ -2033,6 +2043,16 @@ final class CParser(AST) : Parser!AST
if (dt.ty == AST.Tvoid)
error("`void` has no value");
+ if (auto tt = tspec.isTypeTag())
+ {
+ // Anonymous struct being used as a var decl type
+ if (!tt.id && tt.members && tt.tok != TOK.enum_)
+ {
+ Specifier spec;
+ declareTag(tt, spec);
+ }
+ }
+
AST.Initializer initializer;
bool hasInitializer;
if (token.value == TOK.assign)
@@ -2456,25 +2476,7 @@ final class CParser(AST) : Parser!AST
const sloc = token.loc;
nextToken();
- Specifier tagSpecifier;
-
- /* GNU Extensions
- * struct-or-union-specifier:
- * struct-or-union gnu-attributes (opt) identifier (opt) { struct-declaration-list } gnu-attributes (opt)
- * struct-or-union gnu-attribute (opt) identifier
- */
- while (1)
- {
- if (token.value == TOK.__attribute__)
- cparseGnuAttributes(tagSpecifier);
- else if (token.value == TOK.__declspec)
- cparseDeclspec(tagSpecifier);
- else if (token.value == TOK.__pragma)
- uupragmaDirective(sloc);
- else
- break;
- }
- t = cparseStruct(sloc, structOrUnion, tagSpecifier.packalign, symbols);
+ t = cparseStruct(sloc, structOrUnion, symbols);
tkwx = TKW.xtag;
break;
}
@@ -2536,6 +2538,7 @@ final class CParser(AST) : Parser!AST
if (!specifier.alignExps)
specifier.alignExps = new AST.Expressions(0);
specifier.alignExps.push(exp);
+ specifier.alignasExp = exp;
check(TOK.rightParenthesis);
break;
@@ -2839,6 +2842,18 @@ final class CParser(AST) : Parser!AST
//printf("cparseDeclarator(%d, %s)\n", declarator, tbase.toChars());
AST.Types constTypes; // all the Types that will need `const` applied to them
+ // this.symbols can get changed to the symbol table for the
+ // parameter-type-list if we parse a function type.
+ // Callers are only ready to handle this if they pass DTR.xdirect_fd,
+ // so remember to restore this.symbols.
+ bool restore_symbols = true;
+ if (declarator == DTR.xdirect_fd)
+ {
+ declarator = DTR.xdirect;
+ restore_symbols = false;
+ }
+
+
/* Insert tx -> t into
* ts -> ... -> t
* so that
@@ -3030,7 +3045,7 @@ final class CParser(AST) : Parser!AST
//tf = tf.addSTC(storageClass); // TODO
insertTx(ts, tf, t); // ts -> ... -> tf -> t
- if (ts != tf)
+ if (ts != tf || restore_symbols)
this.symbols = symbolsSave;
break;
}
@@ -3511,12 +3526,12 @@ final class CParser(AST) : Parser!AST
case TOK.colonColon: // treat as two separate : tokens for iasmgcc
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
(*ptoklist).value = TOK.colon;
ptoklist = &(*ptoklist).next;
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
(*ptoklist).value = TOK.colon;
ptoklist = &(*ptoklist).next;
@@ -3526,7 +3541,7 @@ final class CParser(AST) : Parser!AST
default:
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
ptoklist = &(*ptoklist).next;
*ptoklist = null;
nextToken();
@@ -3620,26 +3635,18 @@ final class CParser(AST) : Parser!AST
if (token.value == TOK.leftParenthesis)
{
nextToken();
- if (token.value == TOK.int32Literal)
- {
- const n = token.unsvalue;
- if (n < 1 || n & (n - 1) || ushort.max < n)
- error("__attribute__((aligned(%lld))) must be an integer positive power of 2 and be <= 32,768", cast(ulong)n);
- specifier.packalign.set(cast(uint)n);
- specifier.packalign.setPack(true);
- nextToken();
- }
- else
- {
- error("alignment value expected, not `%s`", token.toChars());
- nextToken();
- }
-
+ AST.Expression exp = cparseConstantExp();
+ if (!specifier.alignExps)
+ specifier.alignExps = new AST.Expressions(0);
+ specifier.alignExps.push(exp);
check(TOK.rightParenthesis);
}
- /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data
- * type on the target machine. It's the opposite of __attribute__((packed))
- */
+ else
+ {
+ /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data
+ * type on the target machine. It's the opposite of __attribute__((packed))
+ */
+ }
}
else if (token.ident == Id.packed)
{
@@ -3951,7 +3958,7 @@ final class CParser(AST) : Parser!AST
* redeclaration, or reference to existing declaration.
* Defer to the semantic() pass with a TypeTag.
*/
- return new AST.TypeTag(loc, TOK.enum_, tag, structalign_t.init, base, members);
+ return new AST.TypeTag(loc, TOK.enum_, tag, structalign_t.init, null, base, members);
}
/*************************************
@@ -3978,8 +3985,25 @@ final class CParser(AST) : Parser!AST
* Returns:
* type of the struct
*/
- private AST.Type cparseStruct(Loc loc, TOK structOrUnion, structalign_t packalign, ref AST.Dsymbols* symbols)
+ private AST.Type cparseStruct(Loc loc, TOK structOrUnion, ref AST.Dsymbols* symbols)
{
+ /* GNU Extensions
+ * struct-or-union-specifier:
+ * struct-or-union gnu-attributes (opt) identifier (opt) { struct-declaration-list } gnu-attributes (opt)
+ * struct-or-union gnu-attribute (opt) identifier
+ */
+ Specifier tagSpecifier;
+ while (1)
+ {
+ if (token.value == TOK.__attribute__)
+ cparseGnuAttributes(tagSpecifier);
+ else if (token.value == TOK.__declspec)
+ cparseDeclspec(tagSpecifier);
+ else if (token.value == TOK.__pragma)
+ uupragmaDirective(loc);
+ else
+ break;
+ }
Identifier tag;
if (token.value == TOK.identifier)
@@ -3995,7 +4019,7 @@ final class CParser(AST) : Parser!AST
members = new AST.Dsymbols(); // so `members` will be non-null even with 0 members
while (token.value != TOK.rightCurly)
{
- cparseStructDeclaration(members, packalign);
+ cparseStructDeclaration(members, tagSpecifier.packalign);
if (token.value == TOK.endOfFile)
break;
@@ -4013,18 +4037,18 @@ final class CParser(AST) : Parser!AST
/* GNU Extensions
* Parse the postfix gnu-attributes (opt)
*/
- Specifier specifier;
if (token.value == TOK.__attribute__)
- cparseGnuAttributes(specifier);
- if (!specifier.packalign.isUnknown)
+ cparseGnuAttributes(tagSpecifier);
+ if (!tagSpecifier.packalign.isUnknown)
{
- packalign.set(specifier.packalign.get());
- packalign.setPack(specifier.packalign.isPack());
foreach (ref d; (*members)[])
{
+ // skip possible static assert declarations
+ if (d.isStaticAssert()) continue;
+
auto decls = new AST.Dsymbols(1);
(*decls)[0] = d;
- d = new AST.AlignDeclaration(d.loc, specifier.packalign, decls);
+ d = new AST.AlignDeclaration(d.loc, tagSpecifier.packalign, decls);
}
}
}
@@ -4032,14 +4056,14 @@ final class CParser(AST) : Parser!AST
error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
// many ways and places to declare alignment
- if (packalign.isUnknown() && !this.packalign.isUnknown())
- packalign.set(this.packalign.get());
+ if (tagSpecifier.packalign.isUnknown() && !this.packalign.isUnknown())
+ tagSpecifier.packalign.set(this.packalign.get());
/* Need semantic information to determine if this is a declaration,
* redeclaration, or reference to existing declaration.
* Defer to the semantic() pass with a TypeTag.
*/
- return new AST.TypeTag(loc, structOrUnion, tag, packalign, null, members);
+ return new AST.TypeTag(loc, structOrUnion, tag, tagSpecifier.packalign, tagSpecifier.alignExps, null, members);
}
/*************************************
@@ -4103,7 +4127,7 @@ final class CParser(AST) : Parser!AST
* struct { ... members ... };
* C11 6.7.2.1-13
*/
- if (!tt.id && tt.members)
+ if (!tt.id && tt.members && tt.tok != TOK.enum_)
{
/* members of anonymous struct are considered members of
* the containing struct
@@ -4119,17 +4143,19 @@ final class CParser(AST) : Parser!AST
/* `struct tag;` and `struct tag { ... };`
* always result in a declaration in the current scope
*/
- // TODO: merge in specifier
- auto stag = (tt.tok == TOK.struct_)
- ? new AST.StructDeclaration(tt.loc, tt.id, false)
- : new AST.UnionDeclaration(tt.loc, tt.id);
- stag.members = tt.members;
- if (!symbols)
- symbols = new AST.Dsymbols();
- auto s = applySpecifier(stag, specifier);
- symbols.push(s);
+ Specifier spec;
+ declareTag(tt, spec);
return;
}
+ if (auto tt = tspec.isTypeTag())
+ {
+ // Declare the tagged type at this point.
+ if (tt.members)
+ {
+ Specifier spec;
+ declareTag(tt, spec);
+ }
+ }
while (1)
{
@@ -4178,8 +4204,8 @@ final class CParser(AST) : Parser!AST
error("specifier-qualifier-list required");
else if (width)
{
- if (specifier.alignExps)
- error("no alignment-specifier for bit field declaration"); // C11 6.7.5-2
+ if (specifier.alignasExp)
+ error(specifier.alignasExp.loc, "no alignment-specifier for bit field declaration"); // C11 6.7.5-2
auto s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
members.push(s);
}
@@ -4998,6 +5024,7 @@ final class CParser(AST) : Parser!AST
return false;
break;
+ case TOK._Alignof:
case TOK.sizeof_:
t = peek(t);
if (t.value == TOK.leftParenthesis)
@@ -5015,15 +5042,6 @@ final class CParser(AST) : Parser!AST
return false;
break;
- case TOK._Alignof:
- t = peek(t);
- if (t.value != TOK.leftParenthesis)
- return false;
- t = peek(t);
- if (!isTypeName(t) || t.value != TOK.rightParenthesis)
- return false;
- break;
-
default:
// Compound literals are handled by cast and sizeof expressions,
// so be content with just seeing a primary expression.
@@ -5104,6 +5122,7 @@ final class CParser(AST) : Parser!AST
/// Types of declarator to parse
enum DTR
{
+ xdirect_fd = 0, /// C11 6.7.6 direct-declarator, allow to start function definition
xdirect = 1, /// C11 6.7.6 direct-declarator
xabstract = 2, /// C11 6.7.7 abstract-declarator
xparameter = 3, /// parameter declarator may be either direct or abstract
@@ -5155,6 +5174,7 @@ final class CParser(AST) : Parser!AST
SCW scw; /// storage-class specifiers
MOD mod; /// type qualifiers
AST.Expressions* alignExps; /// alignment
+ AST.Expression alignasExp; /// Last _Alignas() for errors
structalign_t packalign; /// #pragma pack alignment value
}
@@ -6050,6 +6070,8 @@ final class CParser(AST) : Parser!AST
//printf("addSym() %s\n", s.toChars());
if (auto v = s.isVarDeclaration())
v.isCmacro(true); // mark it as coming from a C #define
+ if (auto td = s.isTemplateDeclaration())
+ td.isCmacro = true; // mark as coming from a C #define
/* If it's already defined, replace the earlier
* definition
*/
@@ -6073,6 +6095,14 @@ final class CParser(AST) : Parser!AST
}
}
+ void nextLine()
+ {
+ // scan to end of line
+ while (*p)
+ ++p;
+ ++p; // advance to start of next line
+ }
+
while (p < endp)
{
//printf("|%s|\n", p);
@@ -6084,6 +6114,13 @@ final class CParser(AST) : Parser!AST
if (token.value == TOK.identifier)
{
auto id = token.ident;
+ // https://github.com/dlang/dmd/issues/20423
+ // skip macros that could shadow special builtins
+ if (id == Id.va_arg)
+ {
+ nextLine();
+ continue;
+ }
const params = *p == '(';
nextToken();
@@ -6181,7 +6218,7 @@ final class CParser(AST) : Parser!AST
/* Declare manifest constant:
* enum id = "string";
*/
- AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
+ AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix, true);
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addSym(v);
++p;
@@ -6329,10 +6366,7 @@ final class CParser(AST) : Parser!AST
if (token.value == TOK.identifier)
removeSym(token.ident);
}
- // scan to end of line
- while (*p)
- ++p;
- ++p; // advance to start of next line
+ nextLine();
}
if (newSymbols.length)
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
index 234b6523afbf..b61137ff20fa 100644
--- a/gcc/d/dmd/cxxfrontend.d
+++ b/gcc/d/dmd/cxxfrontend.d
@@ -112,11 +112,6 @@ void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
/***********************************************************
* dmodule.d
*/
-void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
-{
- return dmd.dmodule.getLocalClasses(mod, aclasses);
-}
-
FuncDeclaration findGetMembers(ScopeDsymbol dsym)
{
return dmd.dmodule.findGetMembers(dsym);
@@ -192,6 +187,24 @@ Dsymbol vtblSymbol(ClassDeclaration cd)
return dmd.dsymbolsem.vtblSymbol(cd);
}
+bool isAbstract(ClassDeclaration cd)
+{
+ import dmd.dsymbolsem;
+ return dmd.dsymbolsem.isAbstract(cd);
+}
+
+bool hasPointers(Dsymbol d)
+{
+ import dmd.dsymbolsem;
+ return dmd.dsymbolsem.hasPointers(d);
+}
+
+void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
+{
+ import dmd.dsymbolsem;
+ return dmd.dsymbolsem.getLocalClasses(mod, aclasses);
+}
+
/***********************************************************
* dtemplate.d
*/
@@ -256,7 +269,7 @@ Expression getDefaultValue(EnumDeclaration ed, Loc loc)
/***********************************************************
* expression.d
*/
-void expandTuples(Expressions* exps, Identifiers* names = null)
+void expandTuples(Expressions* exps, ArgumentLabels* names = null)
{
return dmd.expression.expandTuples(exps, names);
}
@@ -305,7 +318,7 @@ bool functionSemantic3(FuncDeclaration fd)
return dmd.funcsem.functionSemantic3(fd);
}
-MATCH leastAsSpecialized(FuncDeclaration fd, FuncDeclaration g, Identifiers* names)
+MATCH leastAsSpecialized(FuncDeclaration fd, FuncDeclaration g, ArgumentLabels* names)
{
import dmd.funcsem;
return dmd.funcsem.leastAsSpecialized(fd, g, names);
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 86d2f0f07c3f..9e35dde29697 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -27,7 +27,6 @@ import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
-import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
@@ -149,8 +148,40 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
//type = type.typeSemantic(loc, sc);
//printf("type %s t %s\n", type.deco, t.deco);
auto ts = toAutoQualChars(e.type, t);
- error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
- e.toErrMsg(), ts[0], ts[1]);
+
+ // Special case for improved diagnostic when const to mutable conversion
+ // fails due to struct/union having pointers
+ if (e.type.ty == Tstruct && t.ty == Tstruct &&
+ e.type.isTypeStruct().sym == t.isTypeStruct().sym &&
+ e.type.mod == MODFlags.const_ && t.mod == 0 && e.type.hasPointers)
+ {
+ auto sym = e.type.isTypeStruct().sym;
+ error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s` because %s `%s` contains pointers or references",
+ e.toErrMsg(), ts[0], ts[1], sym.kind(), sym.toErrMsg());
+ return ErrorExp.get();
+ }
+
+ // Special case for pointer conversions
+ if (e.type.toBasetype().ty == Tpointer && t.toBasetype().ty == Tpointer)
+ {
+ Type fromPointee = e.type.nextOf();
+ Type toPointee = t.nextOf();
+ // Const -> mutable conversion (disallowed)
+ if (fromPointee.isConst() && !toPointee.isConst())
+ {
+ error(e.loc, "cannot implicitly convert `%s` to `%s`", e.type.toChars(), t.toChars());
+ errorSupplemental(e.loc, "Note: Converting const to mutable requires an explicit cast (`cast(int*)`).");
+ return ErrorExp.get();
+ }
+ // Incompatible pointee types (e.g., int* -> float* )
+ else if (fromPointee.toBasetype().ty != toPointee.toBasetype().ty)
+ {
+ error(e.loc, "cannot implicitly convert `%s` to `%s`", e.type.toChars(), t.toChars());
+ errorSupplemental(e.loc, "Note: Pointer types point to different base types (`%s` vs `%s`)", fromPointee.toChars(), toPointee.toChars());
+ return ErrorExp.get();
+ }
+ }
+ error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", e.toErrMsg(), ts[0], ts[1]);
}
}
return ErrorExp.get();
@@ -2715,13 +2746,6 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
ArrayLiteralExp ae = e;
Type tb = t.toBasetype();
- if (tb.ty == Tarray)
- {
- if (checkArrayLiteralEscape(*sc, ae, false))
- {
- return ErrorExp.get();
- }
- }
if (e.type == t)
{
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 80d39fac4267..51ac939ade09 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -23,7 +23,6 @@ import dmd.gluelayer;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic, addMember, setFieldOffset;
import dmd.errors;
import dmd.func;
import dmd.id;
@@ -33,7 +32,6 @@ import dmd.mtype;
import dmd.objc;
import dmd.root.rmem;
import dmd.target;
-import dmd.typesem : covariant, immutableOf, sarrayOf;
import dmd.visitor;
/***********************************************************
@@ -496,116 +494,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return null;
}
- final override void finalizeSize()
- {
- assert(sizeok != Sizeok.done);
-
- // Set the offsets of the fields and determine the size of the class
- if (baseClass)
- {
- assert(baseClass.sizeok == Sizeok.done);
-
- alignsize = baseClass.alignsize;
- if (classKind == ClassKind.cpp)
- structsize = target.cpp.derivedClassOffset(baseClass);
- else
- structsize = baseClass.structsize;
- }
- else if (classKind == ClassKind.objc)
- structsize = 0; // no hidden member for an Objective-C class
- else if (isInterfaceDeclaration())
- {
- if (interfaces.length == 0)
- {
- alignsize = target.ptrsize;
- structsize = target.ptrsize; // allow room for __vptr
- }
- }
- else
- {
- alignsize = target.ptrsize;
- structsize = target.ptrsize; // allow room for __vptr
- if (hasMonitor())
- structsize += target.ptrsize; // allow room for __monitor
- }
-
- //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
- size_t bi = 0; // index into vtblInterfaces[]
-
- /****
- * Runs through the inheritance graph to set the BaseClass.offset fields.
- * Recursive in order to account for the size of the interface classes, if they are
- * more than just interfaces.
- * Params:
- * cd = interface to look at
- * baseOffset = offset of where cd will be placed
- * Returns:
- * subset of instantiated size used by cd for interfaces
- */
- uint membersPlace(ClassDeclaration cd, uint baseOffset)
- {
- //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset);
- uint offset = baseOffset;
-
- foreach (BaseClass* b; cd.interfaces)
- {
- if (b.sym.sizeok != Sizeok.done)
- b.sym.finalizeSize();
- assert(b.sym.sizeok == Sizeok.done);
-
- if (!b.sym.alignsize)
- b.sym.alignsize = target.ptrsize;
- offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset);
- assert(bi < vtblInterfaces.length);
-
- BaseClass* bv = (*vtblInterfaces)[bi];
- if (b.sym.interfaces.length == 0)
- {
- //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset);
- bv.offset = offset;
- ++bi;
- // All the base interfaces down the left side share the same offset
- for (BaseClass* b2 = bv; b2.baseInterfaces.length; )
- {
- b2 = &b2.baseInterfaces[0];
- b2.offset = offset;
- //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset);
- }
- }
- membersPlace(b.sym, offset);
- //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize);
- offset += b.sym.structsize;
- if (alignsize < b.sym.alignsize)
- alignsize = b.sym.alignsize;
- }
- return offset - baseOffset;
- }
-
- structsize += membersPlace(this, structsize);
-
- if (isInterfaceDeclaration())
- {
- sizeok = Sizeok.done;
- return;
- }
-
- // FIXME: Currently setFieldOffset functions need to increase fields
- // to calculate each variable offsets. It can be improved later.
- fields.setDim(0);
-
- FieldState fieldState;
- fieldState.offset = structsize;
- foreach (s; *members)
- {
- s.setFieldOffset(this, &fieldState, false);
- }
-
- sizeok = Sizeok.done;
-
- // Calculate fields[i].overlapped
- checkOverlappedFields();
- }
-
/**************
* Returns: true if there's a __monitor field
*/
@@ -757,106 +645,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return false;
}
- /****************************************
- */
- final bool isAbstract()
- {
- enum log = false;
- if (isabstract != ThreeState.none)
- return isabstract == ThreeState.yes;
-
- if (log) printf("isAbstract(%s)\n", toChars());
-
- bool no() { if (log) printf("no\n"); isabstract = ThreeState.no; return false; }
- bool yes() { if (log) printf("yes\n"); isabstract = ThreeState.yes; return true; }
-
- if (storage_class & STC.abstract_ || _scope && _scope.stc & STC.abstract_)
- return yes();
-
- if (errors)
- return no();
-
- /* https://issues.dlang.org/show_bug.cgi?id=11169
- * Resolve forward references to all class member functions,
- * and determine whether this class is abstract.
- */
- static int func(Dsymbol s, void*)
- {
- auto fd = s.isFuncDeclaration();
- if (!fd)
- return 0;
- if (fd.storage_class & STC.static_)
- return 0;
-
- if (fd.isAbstract())
- return 1;
- return 0;
- }
-
- // opaque class is not abstract if it is not declared abstract
- if (!members)
- return no();
-
- for (size_t i = 0; i < members.length; i++)
- {
- auto s = (*members)[i];
- if (s.apply(&func, null))
- {
- return yes();
- }
- }
-
- /* If the base class is not abstract, then this class cannot
- * be abstract.
- */
- if (!isInterfaceDeclaration() && (!baseClass || !baseClass.isAbstract()))
- return no();
-
- /* If any abstract functions are inherited, but not overridden,
- * then the class is abstract. Do this by checking the vtbl[].
- * Need to do semantic() on class to fill the vtbl[].
- */
- this.dsymbolSemantic(null);
-
- /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic()
- * is called recursively it can set PASS.semanticdone without finishing it.
- */
- //if (semanticRun < PASS.semanticdone)
- {
- /* Could not complete semantic(). Try running semantic() on
- * each of the virtual functions,
- * which will fill in the vtbl[] overrides.
- */
- static int virtualSemantic(Dsymbol s, void*)
- {
- auto fd = s.isFuncDeclaration();
- if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration())
- fd.dsymbolSemantic(null);
- return 0;
- }
-
- for (size_t i = 0; i < members.length; i++)
- {
- auto s = (*members)[i];
- s.apply(&virtualSemantic,null);
- }
- }
-
- /* Finally, check the vtbl[]
- */
- foreach (i; 1 .. vtbl.length)
- {
- auto fd = vtbl[i].isFuncDeclaration();
- //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars());
- if (!fd || fd.isAbstract())
- {
- return yes();
- }
- }
-
- return no();
- }
-
/****************************************
* Determine if slot 0 of the vtbl[] is reserved for something else.
* For class objects, yes, this is where the classinfo ptr goes.
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 4510927da711..25e5c31dcc6f 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -27,7 +27,6 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
import dmd.func;
-import dmd.funcsem : overloadApply, getLevelAndCheck;
import dmd.globals;
import dmd.gluelayer;
import dmd.hdrgen;
@@ -783,25 +782,6 @@ extern (C++) final class OverDeclaration : Declaration
return true;
}
- Dsymbol isUnique()
- {
- Dsymbol result = null;
- overloadApply(aliassym, (Dsymbol s)
- {
- if (result)
- {
- result = null;
- return 1; // ambiguous, done
- }
- else
- {
- result = s;
- return 0;
- }
- });
- return result;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -1054,12 +1034,6 @@ extern (C++) class VarDeclaration : Declaration
vbitoffset < bitoffset + tbitsize;
}
- override final bool hasPointers()
- {
- //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
- return (!isDataseg() && type.hasPointers());
- }
-
/*************************************
* Return true if we can take the address of this variable.
*/
@@ -1109,83 +1083,6 @@ extern (C++) class VarDeclaration : Declaration
return e;
}
- /************************************
- * Check to see if this variable is actually in an enclosing function
- * rather than the current one.
- * Update nestedrefs[], closureVars[] and outerVars[].
- * Returns: true if error occurs.
- */
- extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
- {
- //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
- if (sc.intypeof == 1 || sc.ctfe)
- return false;
- if (!parent || parent == sc.parent)
- return false;
- if (isDataseg() || (storage_class & STC.manifest))
- return false;
-
- // The current function
- FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
- if (!fdthis)
- return false; // out of function scope
-
- Dsymbol p = toParent2();
-
- // Function literals from fdthis to p must be delegates
- ensureStaticLinkTo(fdthis, p);
-
- // The function that this variable is in
- FuncDeclaration fdv = p.isFuncDeclaration();
- if (!fdv || fdv == fdthis)
- return false;
-
- // Add fdthis to nestedrefs[] if not already there
- if (!nestedrefs.contains(fdthis))
- nestedrefs.push(fdthis);
-
- //printf("\tfdv = %s\n", fdv.toChars());
- //printf("\tfdthis = %s\n", fdthis.toChars());
- if (loc.isValid())
- {
- if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
- return true;
- }
-
- // Add this VarDeclaration to fdv.closureVars[] if not already there
- if (!sc.intypeof && !sc.traitsCompiles &&
- // https://issues.dlang.org/show_bug.cgi?id=17605
- (fdv.skipCodegen || !fdthis.skipCodegen))
- {
- if (!fdv.closureVars.contains(this))
- fdv.closureVars.push(this);
- }
-
- if (!fdthis.outerVars.contains(this))
- fdthis.outerVars.push(this);
-
- //printf("fdthis is %s\n", fdthis.toChars());
- //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
- // __dollar creates problems because it isn't a real variable
- // https://issues.dlang.org/show_bug.cgi?id=3326
- if (ident == Id.dollar)
- {
- .error(loc, "cannnot use `$` inside a function literal");
- return true;
- }
- if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
- {
- ExpInitializer ez = _init.isExpInitializer();
- assert(ez);
- Expression e = ez.exp;
- if (e.op == EXP.construct || e.op == EXP.blit)
- e = (cast(AssignExp)e).e2;
- return lambdaCheckForNestedRef(e, sc);
- }
-
- return false;
- }
-
override final Dsymbol toAlias()
{
//printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index c7e45526084d..74ea20cb56f8 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -35,10 +35,11 @@ namespace dmd
bool functionSemantic(FuncDeclaration* fd);
bool functionSemantic3(FuncDeclaration* fd);
bool checkClosure(FuncDeclaration* fd);
- MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
+ MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, ArgumentLabels *names);
PURE isPure(FuncDeclaration *f);
FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0);
FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0);
+ bool isAbstract(ClassDeclaration *cd);
}
//enum STC : ulong from astenums.d:
@@ -297,7 +298,6 @@ public:
bool isThreadlocal() override final;
bool isCTFE();
bool isOverlappedWith(VarDeclaration *v);
- bool hasPointers() override final;
bool canTakeAddressOf();
bool needsScopeDtor();
Dsymbol *toAlias() override final;
diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d
index 344130b5e31d..1f5dca66b598 100644
--- a/gcc/d/dmd/delegatize.d
+++ b/gcc/d/dmd/delegatize.d
@@ -21,6 +21,7 @@ import dmd.dsymbol;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
+import dmd.funcsem : checkNestedReference;
import dmd.init;
import dmd.initsem;
import dmd.location;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 13051db37897..543c0e22e39f 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -1027,12 +1027,6 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
* assigning a larger array into a smaller one, such as:
* `a = [1, 2], a ~= [3]` => `[1, 2] ~= [3]` => `[1, 2] = [1, 2, 3]`
*/
- if (isRuntimeHook(s.exp, Id._d_arrayappendT) || isRuntimeHook(s.exp, Id._d_arrayappendTTrace))
- {
- auto rs = new ReturnStatement(s.loc, e);
- visitReturn(rs);
- return;
- }
// Disallow returning pointers to stack-allocated variables (bug 7876)
if (!stopPointersEscaping(s.loc, e))
@@ -3189,7 +3183,8 @@ public:
if (cmp == -1)
{
char dir = (e.op == EXP.greaterThan || e.op == EXP.greaterOrEqual) ? '<' : '>';
- error(e.loc, "the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
+ error(e.loc, "the ordering of pointers to unrelated memory blocks is indeterminate in CTFE.");
+ errorSupplemental(e.loc, "to check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
result = CTFEExp.cantexp;
return;
}
@@ -5001,61 +4996,6 @@ public:
printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
}
- bool isNewThrowableHook()
- {
- auto de = e.e1.isDeclarationExp();
- if (de is null)
- return false;
-
- auto vd = de.declaration.isVarDeclaration();
- if (vd is null)
- return false;
-
- auto ei = vd._init.isExpInitializer();
- if (ei is null)
- return false;
-
- auto ce = ei.exp.isConstructExp();
- if (ce is null)
- return false;
-
- return isRuntimeHook(ce.e2, Id._d_newThrowable) !is null;
- }
-
- if (auto ce = isRuntimeHook(e.e1, Id._d_arrayappendcTX))
- {
- // In expressionsem.d `arr ~= elem` was lowered to
- // `_d_arrayappendcTX(arr, elem), arr[arr.length - 1] = elem, elem;`.
- // The following code will rewrite it back to `arr ~= elem`
- // and then interpret that expression.
- assert(ce.arguments.length == 2);
-
- auto arr = (*ce.arguments)[0];
- auto elem = e.e2.isConstructExp().e2;
- assert(elem);
-
- auto cae = new CatAssignExp(e.loc, arr, elem);
- cae.type = arr.type;
-
- result = interpret(cae, istate);
- return;
- }
- else if (isNewThrowableHook())
- {
- // In expressionsem.d `throw new Exception(args)` was lowered to
- // `throw (tmp = _d_newThrowable!Exception(), tmp.ctor(args), tmp)`.
- // The following code will rewrite it back to `throw new Exception(args)`
- // and then interpret this expression instead.
- auto ce = e.e2.isCallExp();
- assert(ce);
-
- auto ne = new NewExp(e.loc, null, null, e.type, ce.arguments);
- ne.type = e.e1.type;
-
- result = interpret(ne, istate);
- return;
- }
-
// If it creates a variable, and there's no context for
// the variable to be created in, we need to create one now.
InterState istateComma;
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 0e0070aab588..33539d4bf0b8 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -30,7 +30,7 @@ import dmd.dmacro;
import dmd.doc;
import dmd.dscope;
import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic, importAll, load, include;
+import dmd.dsymbolsem : dsymbolSemantic, importAll, load;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
@@ -43,6 +43,7 @@ import dmd.id;
import dmd.identifier;
import dmd.location;
import dmd.parse;
+import dmd.root.aav;
import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
@@ -544,6 +545,8 @@ extern (C++) final class Module : Package
}
buf.printf("%s\t(%s)", ident.toChars(), m.srcfile.toChars());
message("import %s", buf.peekChars());
+ if (loc != Loc.initial)
+ message("(imported from %s)", loc.toChars());
}
if((m = m.parse()) is null) return null;
@@ -1008,22 +1011,31 @@ extern (C++) final class Module : Package
extern (D) static void addDeferredSemantic(Dsymbol s)
{
//printf("Module::addDeferredSemantic('%s')\n", s.toChars());
- if (!deferred.contains(s))
+ if (!s.deferred)
+ {
+ s.deferred = true;
deferred.push(s);
+ }
}
extern (D) static void addDeferredSemantic2(Dsymbol s)
{
//printf("Module::addDeferredSemantic2('%s')\n", s.toChars());
- if (!deferred2.contains(s))
+ if (!s.deferred2)
+ {
+ s.deferred2 = true;
deferred2.push(s);
+ }
}
extern (D) static void addDeferredSemantic3(Dsymbol s)
{
//printf("Module::addDeferredSemantic3('%s')\n", s.toChars());
- if (!deferred.contains(s))
+ if (!s.deferred3)
+ {
+ s.deferred3 = true;
deferred3.push(s);
+ }
}
/******************************************
@@ -1057,6 +1069,8 @@ extern (C++) final class Module : Package
todoalloc = todo;
}
memcpy(todo, deferred.tdata(), len * Dsymbol.sizeof);
+ foreach (Dsymbol s; Module.deferred[])
+ s.deferred = false;
deferred.setDim(0);
foreach (i; 0..len)
@@ -1082,6 +1096,7 @@ extern (C++) final class Module : Package
for (size_t i = 0; i < a.length; i++)
{
Dsymbol s = (*a)[i];
+ s.deferred2 = false;
//printf("[%d] %s semantic2a\n", i, s.toPrettyChars());
s.semantic2(null);
@@ -1099,6 +1114,7 @@ extern (C++) final class Module : Package
for (size_t i = 0; i < a.length; i++)
{
Dsymbol s = (*a)[i];
+ s.deferred3 = false;
//printf("[%d] %s semantic3a\n", i, s.toPrettyChars());
s.semantic3(null);
@@ -1306,83 +1322,8 @@ extern (C++) struct ModuleDeclaration
}
}
-/****************************************
- * Create array of the local classes in the Module, suitable
- * for inclusion in ModuleInfo
- * Params:
- * mod = the Module
- * aclasses = array to fill in
- * Returns: array of local classes
- */
-void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
-{
- //printf("members.length = %d\n", mod.members.length);
- int pushAddClassDg(size_t n, Dsymbol sm)
- {
- if (!sm)
- return 0;
-
- if (auto cd = sm.isClassDeclaration())
- {
- // compatibility with previous algorithm
- if (cd.parent && cd.parent.isTemplateMixin())
- return 0;
-
- if (cd.classKind != ClassKind.objc)
- aclasses.push(cd);
- }
- return 0;
- }
-
- _foreach(null, mod.members, &pushAddClassDg);
-}
-
-
alias ForeachDg = int delegate(size_t idx, Dsymbol s);
-/***************************************
- * Expands attribute declarations in members in depth first
- * order. Calls dg(size_t symidx, Dsymbol *sym) for each
- * member.
- * If dg returns !=0, stops and returns that value else returns 0.
- * Use this function to avoid the O(N + N^2/2) complexity of
- * calculating dim and calling N times getNth.
- * Returns:
- * last value returned by dg()
- */
-int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null)
-{
- assert(dg);
- if (!members)
- return 0;
- size_t n = pn ? *pn : 0; // take over index
- int result = 0;
- foreach (size_t i; 0 .. members.length)
- {
- import dmd.attrib : AttribDeclaration;
- import dmd.dtemplate : TemplateMixin;
-
- Dsymbol s = (*members)[i];
- if (AttribDeclaration a = s.isAttribDeclaration())
- result = _foreach(sc, a.include(sc), dg, &n);
- else if (TemplateMixin tm = s.isTemplateMixin())
- result = _foreach(sc, tm.members, dg, &n);
- else if (s.isTemplateInstance())
- {
- }
- else if (s.isUnitTestDeclaration())
- {
- }
- else
- result = dg(n++, s);
- if (result)
- break;
- }
- if (pn)
- *pn = n; // update index
- return result;
-}
-
/**
* Process the content of a source file
*
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 725a55e94184..c70e7d381b56 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -64,7 +64,7 @@ private extern (D) struct BitFields
bool inTemplateConstraint; /// inside template constraint
Contract contract;
bool ctfe; /// inside a ctfe-only expression
- bool traitsCompiles; /// inside __traits(compile)
+ bool traitsCompiles; /// inside __traits(compile) or is-expression
/// ignore symbol visibility
/// https://issues.dlang.org/show_bug.cgi?id=15907
bool ignoresymbolvisibility;
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index d07be2f13193..5aef3585cafe 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -151,127 +151,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return "struct";
}
- override final void finalizeSize()
- {
- //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
- assert(sizeok != Sizeok.done);
-
- if (sizeok == Sizeok.inProcess)
- {
- return;
- }
- sizeok = Sizeok.inProcess;
-
- //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok);
-
- fields.setDim(0); // workaround
-
- // Set the offsets of the fields and determine the size of the struct
- FieldState fieldState;
- bool isunion = isUnionDeclaration() !is null;
- for (size_t i = 0; i < members.length; i++)
- {
- Dsymbol s = (*members)[i];
- s.setFieldOffset(this, &fieldState, isunion);
- if (type.ty == Terror)
- {
- errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars);
- errors = true;
- return;
- }
- }
-
- if (structsize == 0)
- {
- hasNoFields = true;
- alignsize = 1;
-
- // A fine mess of what size a zero sized struct should be
- final switch (classKind)
- {
- case ClassKind.d:
- case ClassKind.cpp:
- structsize = 1;
- break;
-
- case ClassKind.c:
- case ClassKind.objc:
- if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS)
- {
- /* Undocumented MS behavior for:
- * struct S { int :0; };
- */
- structsize = 4;
- }
- else
- structsize = 0;
- break;
- }
- }
-
- // Round struct size up to next alignsize boundary.
- // This will ensure that arrays of structs will get their internals
- // aligned properly.
- if (alignment.isDefault() || alignment.isPack())
- structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
- else
- structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1);
-
- sizeok = Sizeok.done;
-
- //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize);
-
- if (errors)
- return;
-
- // Calculate fields[i].overlapped
- if (checkOverlappedFields())
- {
- errors = true;
- return;
- }
-
- // Determine if struct is all zeros or not
- zeroInit = true;
- auto lastOffset = -1;
- foreach (vd; fields)
- {
- // First skip zero sized fields
- if (vd.type.size(vd.loc) == 0)
- continue;
-
- // only consider first sized member of an (anonymous) union
- if (vd.overlapped && vd.offset == lastOffset)
- continue;
- lastOffset = vd.offset;
-
- if (vd._init)
- {
- if (vd._init.isVoidInitializer())
- /* Treat as 0 for the purposes of putting the initializer
- * in the BSS segment, or doing a mass set to 0
- */
- continue;
-
- // Examine init to see if it is all 0s.
- auto exp = vd.getConstInitializer();
- if (!exp || !_isZeroInit(exp))
- {
- zeroInit = false;
- break;
- }
- }
- else if (!vd.type.isZeroInit(loc))
- {
- zeroInit = false;
- break;
- }
- }
-
-
- argTypes = target.toArgTypes(type);
- }
-
/// Compute cached type properties for `TypeStruct`
extern(D) final void determineTypeProperties()
{
@@ -279,13 +158,14 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return;
foreach (vd; fields)
{
+ import dmd.dsymbolsem : hasPointers;
if (vd.storage_class & STC.ref_ || vd.hasPointers())
{
hasPointerField = true;
hasUnsafeBitpatterns = true;
}
- if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers())
+ if (vd._init && vd._init.isVoidInitializer() && vd.hasPointers())
hasVoidInitPointers = true;
if (vd.storage_class & STC.system || vd.type.hasUnsafeBitpatterns())
@@ -399,13 +279,12 @@ extern (C++) class StructDeclaration : AggregateDeclaration
* is not disabled.
*
* Params:
- * checkDisabled = if the struct has a regular
- non-disabled constructor
+ * ignoreDisabled = true to ignore disabled constructors
* Returns:
* true, if the struct has a regular (optionally,
* not disabled) constructor, false otherwise.
*/
- final bool hasRegularCtor(bool checkDisabled = false)
+ final bool hasRegularCtor(bool ignoreDisabled = false)
{
if (!ctor)
return false;
@@ -415,7 +294,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
{
if (auto td = s.isTemplateDeclaration())
{
- if (checkDisabled && td.onemember)
+ if (ignoreDisabled && td.onemember)
{
if (auto ctorDecl = td.onemember.isCtorDeclaration())
{
@@ -428,7 +307,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
}
if (auto ctorDecl = s.isCtorDeclaration())
{
- if (!ctorDecl.isCpCtor && (!checkDisabled || !(ctorDecl.storage_class & STC.disable)))
+ if (!ctorDecl.isCpCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable)))
{
result = true;
return 1;
@@ -440,96 +319,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
}
}
-/**********************************
- * Determine if exp is all binary zeros.
- * Params:
- * exp = expression to check
- * Returns:
- * true if it's all binary 0
- */
-bool _isZeroInit(Expression exp)
-{
- switch (exp.op)
- {
- case EXP.int64:
- return exp.toInteger() == 0;
-
- case EXP.null_:
- return true;
-
- case EXP.structLiteral:
- {
- auto sle = exp.isStructLiteralExp();
- if (sle.sd.isNested())
- return false;
- const isCstruct = sle.sd.isCsymbol(); // C structs are default initialized to all zeros
- foreach (i; 0 .. sle.sd.fields.length)
- {
- auto field = sle.sd.fields[i];
- if (field.type.size(field.loc))
- {
- auto e = sle.elements && i < sle.elements.length ? (*sle.elements)[i] : null;
- if (e ? !_isZeroInit(e)
- : !isCstruct && !field.type.isZeroInit(field.loc))
- return false;
- }
- }
- return true;
- }
-
- case EXP.arrayLiteral:
- {
- auto ale = cast(ArrayLiteralExp)exp;
-
- const dim = ale.elements ? ale.elements.length : 0;
-
- if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array
- return dim == 0;
-
- foreach (i; 0 .. dim)
- {
- if (!_isZeroInit(ale[i]))
- return false;
- }
-
- /* Note that true is returned for all T[0]
- */
- return true;
- }
-
- case EXP.string_:
- {
- auto se = cast(StringExp)exp;
-
- if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array
- return se.len == 0;
-
- foreach (i; 0 .. se.len)
- {
- if (se.getIndex(i) != 0)
- return false;
- }
- return true;
- }
-
- case EXP.vector:
- {
- auto ve = cast(VectorExp) exp;
- return _isZeroInit(ve.e1);
- }
-
- case EXP.float64:
- case EXP.complex80:
- {
- import dmd.root.ctfloat : CTFloat;
- return (exp.toReal() is CTFloat.zero) &&
- (exp.toImaginary() is CTFloat.zero);
- }
-
- default:
- return false;
- }
-}
/***********************************************************
* Unions are a variation on structs.
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 74ca9cbda4d3..e65068c7622b 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -51,7 +51,6 @@ import dmd.statement;
import dmd.staticassert;
import dmd.tokens;
import dmd.visitor;
-import dmd.dsymbolsem;
import dmd.common.outbuffer;
@@ -344,6 +343,11 @@ extern (C++) class Dsymbol : ASTNode
{
bool errors; // this symbol failed to pass semantic()
PASS semanticRun = PASS.initial;
+
+ // Queued for deferred semantics:
+ bool deferred; // In Module.deferred
+ bool deferred2; // In Module.deferred2
+ bool deferred3; // In Module.deferred3
}
import dmd.common.bitfields;
mixin(generateBitFields!(BitFields, ubyte));
@@ -900,78 +904,6 @@ extern (C++) class Dsymbol : ASTNode
assert(0);
}
- /*****************************************
- * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
- */
- extern (D) static bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident)
- {
- //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0);
- Dsymbol s = null;
- if (!members)
- {
- ps = null;
- return true;
- }
-
- for (size_t i = 0; i < members.length; i++)
- {
- Dsymbol sx = (*members)[i];
- bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later
- //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps);
- if (!x)
- {
- //printf("\tfalse 1\n");
- assert(ps is null);
- return false;
- }
- if (ps)
- {
- assert(ident);
- if (!ps.ident || !ps.ident.equals(ident))
- continue;
- if (!s)
- s = ps;
- else if (s.isOverloadable() && ps.isOverloadable())
- {
- // keep head of overload set
- FuncDeclaration f1 = s.isFuncDeclaration();
- FuncDeclaration f2 = ps.isFuncDeclaration();
- if (f1 && f2)
- {
- assert(!f1.isFuncAliasDeclaration());
- assert(!f2.isFuncAliasDeclaration());
- for (; f1 != f2; f1 = f1.overnext0)
- {
- if (f1.overnext0 is null)
- {
- f1.overnext0 = f2;
- break;
- }
- }
- }
- }
- else // more than one symbol
- {
- ps = null;
- //printf("\tfalse 2\n");
- return false;
- }
- }
- }
- ps = s; // s is the one symbol, null if none
- //printf("\ttrue\n");
- return true;
- }
-
- /*****************************************
- * Is Dsymbol a variable that contains pointers?
- */
- bool hasPointers()
- {
- //printf("Dsymbol::hasPointers() %s\n", toChars());
- return false;
- }
-
void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
{
}
@@ -1235,6 +1167,7 @@ extern (C++) class Dsymbol : ASTNode
return null;
}
}
+ inout(AlignDeclaration) isAlignDeclaration() inout { return dsym == DSYM.alignDeclaration ? cast(inout(AlignDeclaration)) cast(void*) this : null; }
inout(AnonDeclaration) isAnonDeclaration() inout { return dsym == DSYM.anonDeclaration ? cast(inout(AnonDeclaration)) cast(void*) this : null; }
inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return dsym == DSYM.cppNamespaceDeclaration ? cast(inout(CPPNamespaceDeclaration)) cast(void*) this : null; }
inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return dsym == DSYM.visibilityDeclaration ? cast(inout(VisibilityDeclaration)) cast(void*) this : null; }
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 558d15608884..77e7dabcb6cf 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -243,7 +243,6 @@ public:
virtual bool needThis(); // need a 'this' pointer?
virtual Visibility visible();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
- virtual bool hasPointers();
virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { }
virtual void addComment(const utf8_t *comment);
@@ -428,7 +427,5 @@ namespace dmd
Dsymbols *include(Dsymbol *d, Scope *sc);
void setScope(Dsymbol *d, Scope *sc);
void importAll(Dsymbol *d, Scope *sc);
- void addComment(Dsymbol *d, const char *comment);
- bool oneMember(Dsymbol *d, Dsymbol *&ps, Identifier *ident);
- bool hasStaticCtorOrDtor(Dsymbol *d);
+ bool hasPointers(Dsymbol *d);
}
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index acbac7a0e047..43fb0b72e4ba 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -953,6 +953,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (dsym.storage_class & STC.constscoperef)
dsym.storage_class |= STC.scope_;
+ import dmd.typesem : hasPointers;
+
if (dsym.storage_class & STC.scope_)
{
STC stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
@@ -3089,10 +3091,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
StructDeclaration sym = ts.sym;
if (sd.isCsymbol() && sym.isCsymbol())
{
- /* This is two structs imported from different C files.
- * Just ignore sd, the second one. The first one will always
- * be found when going through the type.
- */
+
+ if (!isCCompatible(sd, sym))
+ {
+ // Already issued an error.
+ errorSupplemental(sd.loc, "C %ss with the same name from different imports are merged", sd.kind);
+ }
+ else {
+ /* This is two structs imported from different C files.
+ * Just ignore sd, the second one. The first one will always
+ * be found when going through the type.
+ */
+ }
}
else
{
@@ -3132,6 +3142,234 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
//printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
}
+ //
+ // Checks if two structs are compatible
+ // Implements the rules according to C23 6.2.7
+ //
+ static bool isCCompatible(StructDeclaration a, StructDeclaration b)
+ {
+ // Get the name of a type, while avoiding exposing "__tagXXX" anonymous structs
+ static const(char)* typeName(Type t)
+ {
+ if (TypeStruct ts = t.isTypeStruct())
+ {
+ if (ts.sym.ident.toString().startsWith("__tag"))
+ return ts.sym.isUnionDeclaration() ? "(anonymous union)".ptr: "(anonymous struct)".ptr;
+ }
+ return t.toChars();
+ }
+
+ void incompatError()
+ {
+ .error(a.loc, "%s `%s` already exists with an incompatible definition.",
+ a.kind, typeName(a.type));
+ errorSupplemental(b.loc, "previously declared here");
+ }
+
+
+ // For recursive calls into unnamed structs (so Type.equals() doesn't work).
+ static bool isCCompatibleUnnamedStruct(Type a, Type b)
+ {
+ TypeStruct ats = a.isTypeStruct();
+ if (!ats) return false;
+ TypeStruct bts = b.isTypeStruct();
+ if (!bts) return false;
+ // Hack, anonymous structs within a struct are given
+ // an anonymous id starting with __tag.
+ if (!ats.sym.ident.toString().startsWith("__tag"))
+ return false;
+ if (!bts.sym.ident.toString().startsWith("__tag"))
+ return false;
+ return isCCompatible(ats.sym, bts.sym);
+ }
+
+ if (a.fields.length != b.fields.length)
+ {
+ incompatError();
+ errorSupplemental(a.loc, "`%s` has %zu field(s) while `%s` has %zu field(s)",
+ a.toPrettyChars(), a.fields.length, b.toPrettyChars(), b.fields.length);
+ return false;
+ }
+ // both are structs or both are unions
+ if ((a.isUnionDeclaration() is null) != (b.isUnionDeclaration() is null))
+ {
+ incompatError();
+ errorSupplemental(a.loc, "`%s` is a %s while `%s` is a %s",
+ a.toPrettyChars(), a.kind, b.toPrettyChars(), b.kind);
+ return false;
+ }
+ if (a.alignment != b.alignment)
+ {
+ incompatError();
+ errorSupplemental(a.loc, "`%s` has different alignment or packing", a.toPrettyChars());
+ if (a.alignment.isDefault() && ! b.alignment.isDefault())
+ {
+ errorSupplemental(a.loc, "`%s` alignment: default", a.toPrettyChars());
+ errorSupplemental(b.loc, "`%s` alignment: %u",
+ b.toPrettyChars(), cast(uint)b.alignment.get());
+ }
+ else if (!a.alignment.isDefault() && b.alignment.isDefault())
+ {
+ errorSupplemental(a.loc, "`%s` alignment: %u",
+ a.toPrettyChars(), cast(uint)a.alignment.get());
+ errorSupplemental(b.loc, "`%s` alignment: default",
+ b.toPrettyChars());
+ }
+ else if (a.alignment.get() != b.alignment.get())
+ {
+ errorSupplemental(a.loc, "`%s` alignment: %u",
+ a.toPrettyChars(), cast(uint)a.alignment.get());
+ errorSupplemental(b.loc, "`%s` alignment: %u",
+ b.toPrettyChars(), cast(uint)b.alignment.get());
+ }
+ if (a.alignment.isPack() != b.alignment.isPack())
+ {
+ errorSupplemental(a.loc, "`%s` packed: %s",
+ a.toPrettyChars(), a.alignment.isPack()?"true".ptr:"false".ptr);
+ errorSupplemental(b.loc, "`%s` packed: %s",
+ b.toPrettyChars(), b.alignment.isPack()?"true".ptr:"false".ptr);
+ }
+ return false;
+ }
+ foreach (size_t i, VarDeclaration a_field; a.fields[])
+ {
+ VarDeclaration b_field = b.fields[i];
+ //
+ // — there shall be a one-to-one correspondence between
+ // their members such that each pair of corresponding
+ // members are declared with compatible types;
+ //
+ if (!a_field.type.equals(b_field.type) && !isCCompatibleUnnamedStruct(a_field.type, b_field.type))
+ {
+ // Already errored, just bail
+ incompatError();
+ if (a_field.type.isTypeError()) return false;
+ if (b_field.type.isTypeError()) return false;
+
+ errorSupplemental(a_field.loc, "Field %zu differs in type", i);
+ errorSupplemental(a_field.loc, "typeof(%s): %s",
+ a_field.toChars(), typeName(a_field.type));
+ errorSupplemental(b_field.loc, "typeof(%s): %s",
+ b_field.toChars(), typeName(b_field.type));
+ return false;
+ }
+ //
+ // — if one member of the pair is declared with an
+ // alignment specifier, the second is declared with an
+ // equivalent alignment specifier;
+ //
+ if (a_field.alignment != b_field.alignment)
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in alignment or packing", i);
+ if (a_field.alignment.isDefault() && ! b_field.alignment.isDefault())
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` alignment: default",
+ a.toPrettyChars(),a_field.toChars());
+ errorSupplemental(b_field.loc, "`%s.%s` alignment: %u",
+ b.toPrettyChars(), b_field.toChars(), cast(uint)b_field.alignment.get());
+ }
+ else if (!a_field.alignment.isDefault() && b_field.alignment.isDefault())
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` alignment: %u",
+ a.toPrettyChars(), a_field.toChars(), cast(uint)a_field.alignment.get());
+ errorSupplemental(b_field.loc, "`%s.%s` alignment: default",
+ b.toPrettyChars(), b_field.toChars());
+ }
+ else if (a_field.alignment.get() != b_field.alignment.get())
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` alignment: %u",
+ a.toPrettyChars(), a_field.toChars(),
+ cast(uint)a_field.alignment.get());
+ errorSupplemental(b_field.loc, "`%s.%s` alignment: %u",
+ b.toPrettyChars(), b_field.toChars(),
+ cast(uint)b_field.alignment.get());
+ }
+ if (a_field.alignment.isPack() != b_field.alignment.isPack())
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` packed: %s",
+ a.toPrettyChars(), a_field.toChars(),
+ a_field.alignment.isPack()?"true".ptr:"false".ptr);
+ errorSupplemental(b_field.loc, "`%s.%s` packed: %s",
+ b.toPrettyChars(), b_field.toChars(),
+ b_field.alignment.isPack()?"true".ptr:"false".ptr);
+ }
+ return false;
+ }
+ //
+ // - and, if one member of the pair is declared with a
+ // name, the second is declared with the same name.
+ //
+ if (a_field.ident.isAnonymous())
+ {
+ if (!b_field.ident.isAnonymous())
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in name", i);
+ errorSupplemental(a_field.loc, "(anonymous)", a_field.ident.toChars());
+ errorSupplemental(b_field.loc, "%s", b_field.ident.toChars());
+ return false;
+ }
+ }
+ else if (b_field.ident.isAnonymous())
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in name", i);
+ errorSupplemental(a_field.loc, "%s", a_field.ident.toChars());
+ errorSupplemental(b_field.loc, "(anonymous)");
+ return false;
+ }
+ else if (a_field.ident != b_field.ident)
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in name", i);
+ errorSupplemental(a_field.loc, "%s", a_field.ident.toChars());
+ errorSupplemental(b_field.loc, "%s", b_field.ident.toChars());
+ return false;
+ }
+
+ //
+ // For two structures or unions, corresponding bit-fields shall have the same widths.
+ //
+ BitFieldDeclaration bfa = a_field.isBitFieldDeclaration();
+ BitFieldDeclaration bfb = b_field.isBitFieldDeclaration();
+ if ((bfa is null) != (bfb is null))
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in being a bitfield", i);
+ if (bfa is null)
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` is not a bitfield",
+ a.toPrettyChars(), a_field.toChars());
+ errorSupplemental(b_field.loc, "`%s.%s` is a bitfield",
+ b.toPrettyChars(), b_field.toChars());
+ }
+ else if (bfb is null)
+ {
+ errorSupplemental(a_field.loc, "`%s.%s` *is a bitfield",
+ a.toPrettyChars(), a_field.toChars());
+ errorSupplemental(b_field.loc, "`%s.%s` is not a bitfield",
+ b.toPrettyChars(), b_field.toChars());
+ }
+ return false;
+ }
+ if (bfa !is null && bfb !is null)
+ {
+ if (bfa.fieldWidth != bfb.fieldWidth)
+ {
+ incompatError();
+ errorSupplemental(a_field.loc, "Field %zu differs in bitfield width", i);
+ errorSupplemental(a_field.loc, "`%s.%s`: %u",
+ a.toPrettyChars(), a_field.toChars(), bfa.fieldWidth);
+ errorSupplemental(b_field.loc, "`%s.%s`: %u",
+ b.toPrettyChars(), b_field.toChars(), bfb.fieldWidth);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
void interfaceSemantic(ClassDeclaration cd)
{
cd.vtblInterfaces = new BaseClasses();
@@ -4520,7 +4758,7 @@ private bool isDRuntimeHook(Identifier id)
id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
id == Id._d_arraysetassign || id == Id._d_arraysetctor ||
id == Id._d_arrayctor ||
- id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
+ id == Id._d_arraysetlengthT ||
id == Id._d_arraysetlengthTTrace ||
id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
id == Id._d_arrayappendcTX;
@@ -4903,7 +5141,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
if (tempinst.members.length)
{
Dsymbol s;
- if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
+ if (oneMembers(tempinst.members, s, tempdecl.ident) && s)
{
//printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
//printf("setting aliasdecl\n");
@@ -4948,7 +5186,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
if (tempinst.members.length)
{
Dsymbol s;
- if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s)
+ if (oneMembers(tempinst.members, s, tempdecl.ident) && s)
{
if (!tempinst.aliasdecl || tempinst.aliasdecl != s)
{
@@ -7531,14 +7769,14 @@ private extern(C++) class NewScopeVisitor : Visitor
}
-extern(C++) Dsymbols* include(Dsymbol d, Scope* sc)
+Dsymbols* include(Dsymbol d, Scope* sc)
{
- scope icv = new IncludeVisitor(sc);
+ scope icv = new ConditionIncludeVisitor(sc);
d.accept(icv);
return icv.symbols;
}
-extern(C++) class IncludeVisitor : Visitor
+extern(C++) class ConditionIncludeVisitor : Visitor
{
alias visit = typeof(super).visit;
Scope* sc;
@@ -7570,7 +7808,7 @@ extern(C++) class IncludeVisitor : Visitor
return;
}
assert(cdc.condition);
- symbols = cdc.condition.include(cdc._scope ? cdc._scope : sc) ? cdc.decl : cdc.elsedecl;
+ symbols = dmd.expressionsem.include(cdc.condition, cdc._scope ? cdc._scope : sc) ? cdc.decl : cdc.elsedecl;
}
override void visit(StaticIfDeclaration sif)
@@ -7891,7 +8129,7 @@ Lfail:
return false;
}
-extern (C++) void addComment(Dsymbol d, const(char)* comment)
+void addComment(Dsymbol d, const(char)* comment)
{
scope v = new AddCommentVisitor(comment);
d.accept(v);
@@ -8004,7 +8242,7 @@ private extern(C++) class OneMemberVisitor : Visitor
override void visit(AttribDeclaration atb)
{
Dsymbols* d = atb.include(null);
- result = Dsymbol.oneMembers(d, *ps, ident);
+ result = oneMembers(d, *ps, ident);
}
override void visit(StaticForeachDeclaration sfd)
@@ -8027,7 +8265,7 @@ private extern(C++) class OneMemberVisitor : Visitor
override void visit(StorageClassDeclaration scd)
{
- bool t = Dsymbol.oneMembers(scd.decl, *ps, ident);
+ bool t = oneMembers(scd.decl, *ps, ident);
if (t && *ps)
{
/* This is to deal with the following case:
@@ -8056,12 +8294,12 @@ private extern(C++) class OneMemberVisitor : Visitor
//printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
if (cd.condition.inc != Include.notComputed)
{
- Dsymbols* d = cd.condition.include(null) ? cd.decl : cd.elsedecl;
- result = Dsymbol.oneMembers(d, *ps, ident);
+ Dsymbols* d = dmd.expressionsem.include(cd.condition, null) ? cd.decl : cd.elsedecl;
+ result = oneMembers(d, *ps, ident);
}
else
{
- bool res = (Dsymbol.oneMembers(cd.decl, *ps, ident) && *ps is null && Dsymbol.oneMembers(cd.elsedecl, *ps, ident) && *ps is null);
+ bool res = (oneMembers(cd.decl, *ps, ident) && *ps is null && oneMembers(cd.elsedecl, *ps, ident) && *ps is null);
*ps = null;
result = res;
}
@@ -8070,7 +8308,7 @@ private extern(C++) class OneMemberVisitor : Visitor
override void visit(ScopeDsymbol sd)
{
if (sd.isAnonymous())
- result = Dsymbol.oneMembers(sd.members, *ps, ident);
+ result = oneMembers(sd.members, *ps, ident);
else {
// visit(Dsymbol dsym)
*ps = sd;
@@ -8108,7 +8346,7 @@ private extern(C++) class OneMemberVisitor : Visitor
* Return true if any of the members are static ctors or static dtors, or if
* any members have members that are.
*/
-extern(C++) bool hasStaticCtorOrDtor(Dsymbol d)
+bool hasStaticCtorOrDtor(Dsymbol d)
{
scope v = new HasStaticCtorOrDtor();
d.accept(v);
@@ -8162,7 +8400,7 @@ private extern(C++) class HasStaticCtorOrDtor : Visitor
}
}
-extern(C++) bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd)
+bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd)
{
import dmd.funcsem : overloadApply;
//printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
@@ -8210,3 +8448,618 @@ Dsymbol vtblSymbol(ClassDeclaration cd)
}
return cd.vtblsym;
}
+
+bool isAbstract(ClassDeclaration cd)
+{
+ enum log = false;
+ if (cd.isabstract != ThreeState.none)
+ return cd.isabstract == ThreeState.yes;
+
+ if (log) printf("isAbstract(%s)\n", cd.toChars());
+
+ bool no() { if (log) printf("no\n"); cd.isabstract = ThreeState.no; return false; }
+ bool yes() { if (log) printf("yes\n"); cd.isabstract = ThreeState.yes; return true; }
+
+ if (cd.storage_class & STC.abstract_ || cd._scope && cd._scope.stc & STC.abstract_)
+ return yes();
+
+ if (cd.errors)
+ return no();
+
+ /* https://issues.dlang.org/show_bug.cgi?id=11169
+ * Resolve forward references to all class member functions,
+ * and determine whether this class is abstract.
+ */
+ static int func(Dsymbol s, void*)
+ {
+ auto fd = s.isFuncDeclaration();
+ if (!fd)
+ return 0;
+ if (fd.storage_class & STC.static_)
+ return 0;
+
+ if (fd.isAbstract())
+ return 1;
+ return 0;
+ }
+
+ // opaque class is not abstract if it is not declared abstract
+ if (!(cd.members))
+ return no();
+
+ for (size_t i = 0; i < cd.members.length; i++)
+ {
+ auto s = (*(cd.members))[i];
+ if (s.apply(&func, null))
+ {
+ return yes();
+ }
+ }
+
+ /* If the base class is not abstract, then this class cannot
+ * be abstract.
+ */
+ if (!cd.isInterfaceDeclaration() && (!cd.baseClass || !cd.baseClass.isAbstract()))
+ return no();
+
+ /* If any abstract functions are inherited, but not overridden,
+ * then the class is abstract. Do this by checking the vtbl[].
+ * Need to do semantic() on class to fill the vtbl[].
+ */
+ cd.dsymbolSemantic(null);
+
+ /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic()
+ * is called recursively it can set PASS.semanticdone without finishing it.
+ */
+ //if (semanticRun < PASS.semanticdone)
+ {
+ /* Could not complete semantic(). Try running semantic() on
+ * each of the virtual functions,
+ * which will fill in the vtbl[] overrides.
+ */
+ static int virtualSemantic(Dsymbol s, void*)
+ {
+ auto fd = s.isFuncDeclaration();
+ if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration())
+ fd.dsymbolSemantic(null);
+ return 0;
+ }
+
+ for (size_t i = 0; i < cd.members.length; i++)
+ {
+ auto s = (*(cd.members))[i];
+ s.apply(&virtualSemantic,null);
+ }
+ }
+
+ /* Finally, check the vtbl[]
+ */
+ foreach (i; 1 .. cd.vtbl.length)
+ {
+ auto fd = cd.vtbl[i].isFuncDeclaration();
+ //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars());
+ if (!fd || fd.isAbstract())
+ {
+ return yes();
+ }
+ }
+
+ return no();
+}
+
+void finalizeSize(AggregateDeclaration ad)
+{
+ scope v = new FinalizeSizeVisitor();
+ ad.accept(v);
+}
+
+/**********************************
+ * Determine if exp is all binary zeros.
+ * Params:
+ * exp = expression to check
+ * Returns:
+ * true if it's all binary 0
+ */
+bool _isZeroInit(Expression exp)
+{
+ switch (exp.op)
+ {
+ case EXP.int64:
+ return exp.toInteger() == 0;
+
+ case EXP.null_:
+ return true;
+
+ case EXP.structLiteral:
+ {
+ auto sle = exp.isStructLiteralExp();
+ if (sle.sd.isNested())
+ return false;
+ const isCstruct = sle.sd.isCsymbol(); // C structs are default initialized to all zeros
+ foreach (i; 0 .. sle.sd.fields.length)
+ {
+ auto field = sle.sd.fields[i];
+ if (field.type.size(field.loc))
+ {
+ auto e = sle.elements && i < sle.elements.length ? (*sle.elements)[i] : null;
+ if (e ? !_isZeroInit(e)
+ : !isCstruct && !field.type.isZeroInit(field.loc))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ case EXP.arrayLiteral:
+ {
+ auto ale = cast(ArrayLiteralExp)exp;
+
+ const dim = ale.elements ? ale.elements.length : 0;
+
+ if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array
+ return dim == 0;
+
+ foreach (i; 0 .. dim)
+ {
+ if (!_isZeroInit(ale[i]))
+ return false;
+ }
+
+ /* Note that true is returned for all T[0]
+ */
+ return true;
+ }
+
+ case EXP.string_:
+ {
+ auto se = cast(StringExp)exp;
+
+ if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array
+ return se.len == 0;
+
+ foreach (i; 0 .. se.len)
+ {
+ if (se.getIndex(i) != 0)
+ return false;
+ }
+ return true;
+ }
+
+ case EXP.vector:
+ {
+ auto ve = cast(VectorExp) exp;
+ return _isZeroInit(ve.e1);
+ }
+
+ case EXP.float64:
+ case EXP.complex80:
+ {
+ import dmd.root.ctfloat : CTFloat;
+ return (exp.toReal() is CTFloat.zero) &&
+ (exp.toImaginary() is CTFloat.zero);
+ }
+
+ default:
+ return false;
+ }
+}
+
+private extern(C++) class FinalizeSizeVisitor : Visitor
+{
+ alias visit = Visitor.visit;
+
+ override void visit(ClassDeclaration outerCd)
+ {
+ assert(outerCd.sizeok != Sizeok.done);
+
+ // Set the offsets of the fields and determine the size of the class
+ if (outerCd.baseClass)
+ {
+ assert(outerCd.baseClass.sizeok == Sizeok.done);
+
+ outerCd.alignsize = outerCd.baseClass.alignsize;
+ if (outerCd.classKind == ClassKind.cpp)
+ outerCd.structsize = target.cpp.derivedClassOffset(outerCd.baseClass);
+ else
+ outerCd.structsize = outerCd.baseClass.structsize;
+ }
+ else if (outerCd.classKind == ClassKind.objc)
+ outerCd.structsize = 0; // no hidden member for an Objective-C class
+ else if (outerCd.isInterfaceDeclaration())
+ {
+ if (outerCd.interfaces.length == 0)
+ {
+ outerCd.alignsize = target.ptrsize;
+ outerCd.structsize = target.ptrsize; // allow room for __vptr
+ }
+ }
+ else
+ {
+ outerCd.alignsize = target.ptrsize;
+ outerCd.structsize = target.ptrsize; // allow room for __vptr
+ if (outerCd.hasMonitor())
+ outerCd.structsize += target.ptrsize; // allow room for __monitor
+ }
+
+ //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
+ size_t bi = 0; // index into vtblInterfaces[]
+
+ /****
+ * Runs through the inheritance graph to set the BaseClass.offset fields.
+ * Recursive in order to account for the size of the interface classes, if they are
+ * more than just interfaces.
+ * Params:
+ * cd = interface to look at
+ * baseOffset = offset of where cd will be placed
+ * Returns:
+ * subset of instantiated size used by cd for interfaces
+ */
+ uint membersPlace(ClassDeclaration cd, uint baseOffset)
+ {
+ //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset);
+ uint offset = baseOffset;
+
+ foreach (BaseClass* b; cd.interfaces)
+ {
+ if (b.sym.sizeok != Sizeok.done)
+ b.sym.finalizeSize();
+ assert(b.sym.sizeok == Sizeok.done);
+
+ if (!b.sym.alignsize)
+ b.sym.alignsize = target.ptrsize;
+ offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset);
+ assert(bi < outerCd.vtblInterfaces.length);
+
+ BaseClass* bv = (*(outerCd.vtblInterfaces))[bi];
+ if (b.sym.interfaces.length == 0)
+ {
+ //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset);
+ bv.offset = offset;
+ ++bi;
+ // All the base interfaces down the left side share the same offset
+ for (BaseClass* b2 = bv; b2.baseInterfaces.length; )
+ {
+ b2 = &b2.baseInterfaces[0];
+ b2.offset = offset;
+ //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset);
+ }
+ }
+ membersPlace(b.sym, offset);
+ //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize);
+ offset += b.sym.structsize;
+ if (outerCd.alignsize < b.sym.alignsize)
+ outerCd.alignsize = b.sym.alignsize;
+ }
+ return offset - baseOffset;
+ }
+
+ outerCd.structsize += membersPlace(outerCd, outerCd.structsize);
+
+ if (outerCd.isInterfaceDeclaration())
+ {
+ outerCd.sizeok = Sizeok.done;
+ return;
+ }
+
+ // FIXME: Currently setFieldOffset functions need to increase fields
+ // to calculate each variable offsets. It can be improved later.
+ outerCd.fields.setDim(0);
+
+ FieldState fieldState;
+ fieldState.offset = outerCd.structsize;
+ foreach (s; *(outerCd.members))
+ {
+ s.setFieldOffset(outerCd, &fieldState, false);
+ }
+
+ outerCd.sizeok = Sizeok.done;
+
+ // Calculate fields[i].overlapped
+ outerCd.checkOverlappedFields();
+ }
+
+ override void visit(StructDeclaration sd)
+ {
+ //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
+ assert(sd.sizeok != Sizeok.done);
+
+ if (sd.sizeok == Sizeok.inProcess)
+ {
+ return;
+ }
+ sd.sizeok = Sizeok.inProcess;
+
+ //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok);
+
+ sd.fields.setDim(0); // workaround
+
+ // Set the offsets of the fields and determine the size of the struct
+ FieldState fieldState;
+ bool isunion = sd.isUnionDeclaration() !is null;
+ for (size_t i = 0; i < sd.members.length; i++)
+ {
+ Dsymbol s = (*sd.members)[i];
+ s.setFieldOffset(sd, &fieldState, isunion);
+ if (sd.type.ty == Terror)
+ {
+ errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars);
+ sd.errors = true;
+ return;
+ }
+ }
+
+ if (sd.structsize == 0)
+ {
+ sd.hasNoFields = true;
+ sd.alignsize = 1;
+
+ // A fine mess of what size a zero sized struct should be
+ final switch (sd.classKind)
+ {
+ case ClassKind.d:
+ case ClassKind.cpp:
+ sd.structsize = 1;
+ break;
+
+ case ClassKind.c:
+ case ClassKind.objc:
+ if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS)
+ {
+ /* Undocumented MS behavior for:
+ * struct S { int :0; };
+ */
+ sd.structsize = 4;
+ }
+ else
+ sd.structsize = 0;
+ break;
+ }
+ }
+
+ // Round struct size up to next alignsize boundary.
+ // This will ensure that arrays of structs will get their internals
+ // aligned properly.
+ if (sd.alignment.isDefault() || sd.alignment.isPack())
+ sd.structsize = (sd.structsize + sd.alignsize - 1) & ~(sd.alignsize - 1);
+ else
+ sd.structsize = (sd.structsize + sd.alignment.get() - 1) & ~(sd.alignment.get() - 1);
+
+ sd.sizeok = Sizeok.done;
+
+ //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize);
+
+ if (sd.errors)
+ return;
+
+ // Calculate fields[i].overlapped
+ if (sd.checkOverlappedFields())
+ {
+ sd.errors = true;
+ return;
+ }
+
+ // Determine if struct is all zeros or not
+ sd.zeroInit = true;
+ auto lastOffset = -1;
+ foreach (vd; sd.fields)
+ {
+ // First skip zero sized fields
+ if (vd.type.size(vd.loc) == 0)
+ continue;
+
+ // only consider first sized member of an (anonymous) union
+ if (vd.overlapped && vd.offset == lastOffset)
+ continue;
+ lastOffset = vd.offset;
+
+ if (vd._init)
+ {
+ if (vd._init.isVoidInitializer())
+ /* Treat as 0 for the purposes of putting the initializer
+ * in the BSS segment, or doing a mass set to 0
+ */
+ continue;
+
+ // Examine init to see if it is all 0s.
+ auto exp = vd.getConstInitializer();
+ if (!exp || !_isZeroInit(exp))
+ {
+ sd.zeroInit = false;
+ break;
+ }
+ }
+ else if (!vd.type.isZeroInit(sd.loc))
+ {
+ sd.zeroInit = false;
+ break;
+ }
+ }
+
+
+ sd.argTypes = target.toArgTypes(sd.type);
+ }
+}
+
+/*****************************************
+* Is Dsymbol a variable that contains pointers?
+*/
+bool hasPointers(Dsymbol d)
+{
+ scope v = new HasPointersVisitor();
+ d.accept(v);
+ return v.result;
+}
+
+private extern(C++) class HasPointersVisitor : Visitor
+{
+ import dmd.mtype : Type;
+
+ alias visit = Visitor.visit;
+ bool result;
+
+ override void visit(AttribDeclaration ad)
+ {
+ result = ad.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
+ }
+
+ override void visit(VarDeclaration vd)
+ {
+ import dmd.typesem : hasPointers;
+ result = (!vd.isDataseg() && vd.type.hasPointers());
+ }
+
+ override void visit(Dsymbol d)
+ {
+ //printf("Dsymbol::hasPointers() %s\n", toChars());
+ result = false;
+ }
+
+ override void visit(TemplateMixin tm)
+ {
+ //printf("TemplateMixin.hasPointers() %s\n", toChars());
+ result = tm.members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
+ }
+
+ override void visit(Nspace ns)
+ {
+ //printf("Nspace::hasPointers() %s\n", toChars());
+ result = ns.members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
+ }
+}
+
+/***************************************
+ * Expands attribute declarations in members in depth first
+ * order. Calls dg(size_t symidx, Dsymbol *sym) for each
+ * member.
+ * If dg returns !=0, stops and returns that value else returns 0.
+ * Use this function to avoid the O(N + N^2/2) complexity of
+ * calculating dim and calling N times getNth.
+ * Returns:
+ * last value returned by dg()
+ */
+int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null)
+{
+ assert(dg);
+ if (!members)
+ return 0;
+ size_t n = pn ? *pn : 0; // take over index
+ int result = 0;
+ foreach (size_t i; 0 .. members.length)
+ {
+ import dmd.attrib : AttribDeclaration;
+ import dmd.dtemplate : TemplateMixin;
+
+ Dsymbol s = (*members)[i];
+ if (AttribDeclaration a = s.isAttribDeclaration())
+ result = _foreach(sc, a.include(sc), dg, &n);
+ else if (TemplateMixin tm = s.isTemplateMixin())
+ result = _foreach(sc, tm.members, dg, &n);
+ else if (s.isTemplateInstance())
+ {
+ }
+ else if (s.isUnitTestDeclaration())
+ {
+ }
+ else
+ result = dg(n++, s);
+ if (result)
+ break;
+ }
+ if (pn)
+ *pn = n; // update index
+ return result;
+}
+
+/****************************************
+ * Create array of the local classes in the Module, suitable
+ * for inclusion in ModuleInfo
+ * Params:
+ * mod = the Module
+ * aclasses = array to fill in
+ * Returns: array of local classes
+ */
+void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
+{
+ //printf("members.length = %d\n", mod.members.length);
+ int pushAddClassDg(size_t n, Dsymbol sm)
+ {
+ if (!sm)
+ return 0;
+
+ if (auto cd = sm.isClassDeclaration())
+ {
+ // compatibility with previous algorithm
+ if (cd.parent && cd.parent.isTemplateMixin())
+ return 0;
+
+ if (cd.classKind != ClassKind.objc)
+ aclasses.push(cd);
+ }
+ return 0;
+ }
+
+ _foreach(null, mod.members, &pushAddClassDg);
+}
+
+/*****************************************
+* Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
+*/
+extern (D) bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident)
+{
+ //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0);
+ Dsymbol s = null;
+ if (!members)
+ {
+ ps = null;
+ return true;
+ }
+
+ for (size_t i = 0; i < members.length; i++)
+ {
+ Dsymbol sx = (*members)[i];
+ bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later
+ //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps);
+ if (!x)
+ {
+ //printf("\tfalse 1\n");
+ assert(ps is null);
+ return false;
+ }
+ if (ps)
+ {
+ assert(ident);
+ if (!ps.ident || !ps.ident.equals(ident))
+ continue;
+ if (!s)
+ s = ps;
+ else if (s.isOverloadable() && ps.isOverloadable())
+ {
+ // keep head of overload set
+ FuncDeclaration f1 = s.isFuncDeclaration();
+ FuncDeclaration f2 = ps.isFuncDeclaration();
+ if (f1 && f2)
+ {
+ assert(!f1.isFuncAliasDeclaration());
+ assert(!f2.isFuncAliasDeclaration());
+ for (; f1 != f2; f1 = f1.overnext0)
+ {
+ if (f1.overnext0 is null)
+ {
+ f1.overnext0 = f2;
+ break;
+ }
+ }
+ }
+ }
+ else // more than one symbol
+ {
+ ps = null;
+ //printf("\tfalse 2\n");
+ return false;
+ }
+ }
+ }
+ ps = s; // s is the one symbol, null if none
+ //printf("\ttrue\n");
+ return true;
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 215889574570..16e192da20ff 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -53,7 +53,7 @@ import dmd.dinterpret;
import dmd.dmodule;
import dmd.dscope;
import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include, hasStaticCtorOrDtor;
+import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include, hasStaticCtorOrDtor, oneMembers;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
@@ -593,6 +593,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
bool isTrivialAliasSeq; /// matches pattern `template AliasSeq(T...) { alias AliasSeq = T; }`
bool isTrivialAlias; /// matches pattern `template Alias(T) { alias Alias = qualifiers(T); }`
bool deprecated_; /// this template declaration is deprecated
+ bool isCmacro; /// Whether this template is a translation of a C macro
Visibility visibility;
// threaded list of previous instantiation attempts on stack
@@ -639,7 +640,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
return;
Dsymbol s;
- if (!Dsymbol.oneMembers(members, s, ident) || !s)
+ if (!oneMembers(members, s, ident) || !s)
return;
onemember = s;
@@ -3661,11 +3662,11 @@ extern (C++) class TemplateInstance : ScopeDsymbol
ScopeDsymbol argsym; // argument symbol table
size_t hash; // cached result of toHash()
- /// For function template, these are the function names and arguments
+ /// For function template, these are the function fnames(name and loc of it) and arguments
/// Relevant because different resolutions of `auto ref` parameters
/// create different template instances even with the same template arguments
Expressions* fargs;
- Identifiers* fnames;
+ ArgumentLabels* fnames;
TemplateInstances* deferred;
@@ -5273,7 +5274,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
if (members.length)
{
Dsymbol sa;
- if (Dsymbol.oneMembers(members, sa, tempdecl.ident) && sa)
+ if (oneMembers(members, sa, tempdecl.ident) && sa)
aliasdecl = sa;
}
done = true;
@@ -5490,12 +5491,6 @@ extern (C++) final class TemplateMixin : TemplateInstance
return "mixin";
}
- override bool hasPointers()
- {
- //printf("TemplateMixin.hasPointers() %s\n", toChars());
- return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
- }
-
extern (D) bool findTempDecl(Scope* sc)
{
// Follow qualifications to find the TemplateDeclaration
diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d
index 4f0d4e5f53f2..6d325e44c964 100644
--- a/gcc/d/dmd/enumsem.d
+++ b/gcc/d/dmd/enumsem.d
@@ -81,7 +81,7 @@ import dmd.visitor;
/*********************************
- * Perform semantic analysis on enum declaration `em`
+ * Perform semantic analysis on enum declaration `ed`
*/
void enumSemantic(Scope* sc, EnumDeclaration ed)
{
@@ -158,9 +158,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
ed.semanticRun = PASS.initial;
return;
}
- else
- // Ensure that semantic is run to detect. e.g. invalid forward references
- sym.dsymbolSemantic(sc);
+ // Ensure that semantic is run to detect. e.g. invalid forward references
+ sym.dsymbolSemantic(sc);
+ if (ed.errors)
+ ed.memtype = Type.terror; // avoid infinite recursion in toBaseType
}
if (ed.memtype.ty == Tvoid)
{
@@ -175,6 +176,8 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
ed.semanticRun = PASS.semanticdone;
return;
}
+ if (global.params.useTypeInfo && Type.dtypeinfo && !ed.inNonRoot())
+ semanticTypeInfo(sc, ed.memtype);
}
if (!ed.members) // enum ident : memtype;
@@ -229,122 +232,24 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
if (sc.inCfile)
- {
- /* C11 6.7.2.2
- */
- Type commonType = ed.memtype;
- if (!commonType)
- commonType = Type.tint32;
- ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
-
- // C11 6.7.2.2-2 value must be representable as an int.
- // The sizemask represents all values that int will fit into,
- // from 0..uint.max. We want to cover int.min..uint.max.
- IntRange ir = IntRange.fromType(commonType);
-
- void emSemantic(EnumMember em, ref ulong nextValue)
- {
- static void errorReturn(EnumMember em)
- {
- em.value = ErrorExp.get();
- em.errors = true;
- em.semanticRun = PASS.semanticdone;
- }
-
- em.semanticRun = PASS.semantic;
- em.type = commonType;
- em._linkage = LINK.c;
- em.storage_class |= STC.manifest;
- if (em.value)
- {
- Expression e = em.value;
- assert(e.dyncast() == DYNCAST.expression);
-
- /* To merge the type of e with commonType, add 0 of type commonType
- */
- if (!ed.memtype)
- e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
-
- e = e.expressionSemantic(sc);
- e = resolveProperties(sc, e);
- e = e.integralPromotions(sc);
- e = e.ctfeInterpret();
- if (e.op == EXP.error)
- return errorReturn(em);
- auto ie = e.isIntegerExp();
- if (!ie)
- {
- // C11 6.7.2.2-2
- .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
- return errorReturn(em);
- }
- if (ed.memtype && !ir.contains(getIntRange(ie)))
- {
- // C11 6.7.2.2-2
- .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
- return errorReturn(em);
- }
- nextValue = ie.toInteger();
- if (!ed.memtype)
- commonType = e.type;
- em.value = new IntegerExp(em.loc, nextValue, commonType);
- }
- else
- {
- // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
- bool first = (em == (*em.ed.members)[0]);
- if (!first)
- {
- Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
- if (nextValue == max.toInteger())
- {
- .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
- return errorReturn(em);
- }
- nextValue += 1;
- }
- em.value = new IntegerExp(em.loc, nextValue, commonType);
- }
- em.type = commonType;
- em.semanticRun = PASS.semanticdone;
- }
-
- ed.members.foreachDsymbol( (s)
- {
- if (EnumMember em = s.isEnumMember())
- emSemantic(em, nextValue);
- });
-
- if (!ed.memtype)
- {
- // cast all members to commonType
- ed.members.foreachDsymbol( (s)
- {
- if (EnumMember em = s.isEnumMember())
- {
- em.type = commonType;
- // optimize out the cast so that other parts of the compiler can
- // assume that an integral enum's members are `IntegerExp`s.
- // https://issues.dlang.org/show_bug.cgi?id=24504
- em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
- }
- });
- }
-
- ed.memtype = commonType;
- ed.semanticRun = PASS.semanticdone;
- return;
- }
+ return cEnumSemantic(sc, ed);
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
em.dsymbolSemantic(em._scope);
});
+
+ if (global.params.useTypeInfo && Type.dtypeinfo && !ed.inNonRoot())
+ semanticTypeInfo(sc, ed.memtype);
//printf("ed.defaultval = %lld\n", ed.defaultval);
//if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars());
//printf("members = %s\n", members.toChars());
+
+ // Set semantic2done here to indicate all members have been processed
+ // This prevents using the enum in a final switch while being defined
+ ed.semanticRun = PASS.semantic2done;
}
Expression getDefaultValue(EnumDeclaration ed, Loc loc)
@@ -625,6 +530,21 @@ void enumMemberSemantic(Scope* sc, EnumMember em)
});
assert(emprev);
+
+ // New check: if the base type is an enum, auto-increment is not supported,
+ // unless it is a special enum (for example, the C types like cpp_long/longlong).
+ if (auto te = em.ed.memtype ? em.ed.memtype.isTypeEnum() : null)
+ {
+ if (!te.sym.isSpecial())
+ {
+ error(em.loc,
+ "cannot automatically assign value to enum member `%s` because base type `%s` is an enum; provide an explicit value",
+ em.toPrettyChars(), em.ed.memtype.toChars());
+ return errorReturn();
+ }
+ }
+
+
if (emprev.semanticRun < PASS.semanticdone) // if forward reference
emprev.dsymbolSemantic(emprev._scope); // resolve it
if (emprev.errors)
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index d65b163ee668..c29484d9e7bf 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -86,7 +86,7 @@ inout(Expression) lastComma(inout Expression e)
* exps = array of Expressions
* names = optional array of names corresponding to Expressions
*/
-void expandTuples(Expressions* exps, Identifiers* names = null)
+void expandTuples(Expressions* exps, ArgumentLabels* names = null)
{
//printf("expandTuples()\n");
if (exps is null)
@@ -116,7 +116,7 @@ void expandTuples(Expressions* exps, Identifiers* names = null)
}
foreach (i; 1 .. length)
{
- names.insert(index + i, cast(Identifier) null);
+ names.insert(index + i, ArgumentLabel(cast(Identifier) null, Loc.init));
}
}
}
@@ -306,6 +306,7 @@ extern (C++) abstract class Expression : ASTNode
{
bool parens; // if this is a parenthesized expression
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue
+ bool gcPassDone; // `checkGC` has been run on this expression
}
import dmd.common.bitfields;
mixin(generateBitFields!(BitFields, ubyte));
@@ -1405,6 +1406,8 @@ extern (C++) final class StringExp : Expression
/// If the string is parsed from a hex string literal
bool hexString = false;
+ /// If the string is from a collected C macro
+ bool cMacro = false;
enum char NoPostfix = 0;
@@ -1416,13 +1419,14 @@ extern (C++) final class StringExp : Expression
this.sz = 1; // work around LDC bug #1286
}
- extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) scope
+ extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix, bool cMacro = false) scope
{
super(loc, EXP.string_);
this.string = cast(char*)string.ptr; // note that this.string should be const
this.len = len;
this.sz = sz;
this.postfix = postfix;
+ this.cMacro = cMacro;
}
static StringExp create(Loc loc, const(char)* s)
@@ -2445,7 +2449,7 @@ extern (C++) final class NewExp : Expression
Expression thisexp; // if !=null, 'this' for class being allocated
Type newtype;
Expressions* arguments; // Array of Expression's
- Identifiers* names; // Array of names corresponding to expressions
+ ArgumentLabels* names; // Array of names(name and location of name) corresponding to expressions
Expression placement; // if !=null, then PlacementExpression
Expression argprefix; // expression to be evaluated just before arguments[]
@@ -2457,9 +2461,10 @@ extern (C++) final class NewExp : Expression
/// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around.
/// The fields are still separate for backwards compatibility
+
extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); }
- extern (D) this(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe
+ extern (D) this(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, ArgumentLabels* names = null) @safe
{
super(loc, EXP.new_);
this.placement = placement;
@@ -3271,29 +3276,36 @@ extern (C++) final class DotTypeExp : UnaExp
struct ArgumentList
{
Expressions* arguments; // function arguments
- Identifiers* names; // named argument identifiers
+ ArgumentLabels* names; // named argument labels
size_t length() const @nogc nothrow pure @safe { return arguments ? arguments.length : 0; }
/// Returns: whether this argument list contains any named arguments
- bool hasNames() const @nogc nothrow pure @safe
+ bool hasArgNames() const @nogc nothrow pure @safe
{
if (names is null)
return false;
- foreach (name; *names)
- if (name !is null)
+ foreach (argLabel; *names)
+ if (argLabel.name !is null)
return true;
return false;
}
}
+// Contains both `name` and `location of the name` for an expression.
+struct ArgumentLabel
+{
+ Identifier name; // name of the argument
+ Loc loc; // location of the name
+ }
+
/***********************************************************
*/
extern (C++) final class CallExp : UnaExp
{
Expressions* arguments; // function arguments
- Identifiers* names; // named argument identifiers
+ ArgumentLabels *names; // named argument labels
FuncDeclaration f; // symbol to call
bool directcall; // true if a virtual call is devirtualized
bool inDebugStatement; /// true if this was in a debug statement
@@ -3305,7 +3317,7 @@ extern (C++) final class CallExp : UnaExp
/// The fields are still separate for backwards compatibility
extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); }
- extern (D) this(Loc loc, Expression e, Expressions* exps, Identifiers* names = null) @safe
+ extern (D) this(Loc loc, Expression e, Expressions* exps, ArgumentLabels *names = null) @safe
{
super(loc, EXP.call, e);
this.arguments = exps;
@@ -3851,6 +3863,9 @@ extern (C++) final class CommaExp : BinExp
/// false will be passed will be from the parser.
bool allowCommaExp;
+ /// The original expression before any rewriting occurs.
+ /// This is used in error messages.
+ Expression originalExp;
extern (D) this(Loc loc, Expression e1, Expression e2, bool generated = true) @safe
{
@@ -3858,6 +3873,12 @@ extern (C++) final class CommaExp : BinExp
allowCommaExp = isGenerated = generated;
}
+ extern (D) this(Loc loc, Expression e1, Expression e2, Expression oe) @safe
+ {
+ this(loc, e1, e2);
+ originalExp = oe;
+ }
+
override bool isLvalue()
{
return !rvalue && e2.isLvalue();
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 3c8d90dd7eb6..6b4298b3308b 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -51,14 +51,13 @@ namespace dmd
{
// in expressionsem.d
Expression *expressionSemantic(Expression *e, Scope *sc);
- void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc);
// in typesem.d
Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false);
// Entry point for CTFE.
// A compile-time result is required. Give an error if not possible
Expression *ctfeInterpret(Expression *e);
- void expandTuples(Expressions *exps, Identifiers *names = nullptr);
+ void expandTuples(Expressions *exps, ArgumentLabels *names = nullptr);
Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
}
@@ -354,6 +353,7 @@ public:
unsigned char sz; // 1: char, 2: wchar, 4: dchar
d_bool committed; // if type is committed
d_bool hexString; // if string is parsed from a hex string literal
+ d_bool cMacro; // If the string is from a collected C macro
static StringExp *create(Loc loc, const char *s);
static StringExp *create(Loc loc, const void *s, d_size_t len);
@@ -518,7 +518,7 @@ public:
Expression *thisexp; // if !NULL, 'this' for class being allocated
Type *newtype;
Expressions *arguments; // Array of Expression's
- Identifiers *names; // Array of names corresponding to expressions
+ ArgumentLabels *names; // Array of argument Labels (name and location of name) corresponding to expressions
Expression *placement; // if !NULL, placement expression
Expression *argprefix; // expression to be evaluated just before arguments[]
@@ -795,23 +795,38 @@ public:
struct ArgumentList final
{
Expressions* arguments;
- Identifiers* names;
+ ArgumentLabels* names;
ArgumentList() :
arguments(),
names()
{
}
- ArgumentList(Expressions* arguments, Identifiers* names = nullptr) :
+ ArgumentList(Expressions* arguments, ArgumentLabels* names = nullptr) :
arguments(arguments),
names(names)
{}
};
+struct ArgumentLabel final
+{
+ Identifier* name;
+ Loc loc;
+ ArgumentLabel() :
+ name(),
+ loc()
+ {
+ }
+ ArgumentLabel(Identifier* name, Loc loc = Loc()) :
+ name(name),
+ loc(loc)
+ {}
+};
+
class CallExp final : public UnaExp
{
public:
Expressions *arguments; // function arguments
- Identifiers *names;
+ ArgumentLabels* names; // function argument Labels (name + location of name)
FuncDeclaration *f; // symbol to call
d_bool directcall; // true if a virtual call is devirtualized
d_bool inDebugStatement; // true if this was in a debug statement
@@ -935,6 +950,7 @@ public:
class ArrayLengthExp final : public UnaExp
{
public:
+ Expression lowering;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -990,6 +1006,7 @@ class CommaExp final : public BinExp
public:
d_bool isGenerated;
d_bool allowCommaExp;
+ Expression* originalExp;
bool isLvalue() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index b02f6ea64102..2576d7c0d056 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1334,8 +1334,8 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
ce.arguments = new Expressions();
ce.arguments.shift(eleft);
if (!ce.names)
- ce.names = new Identifiers();
- ce.names.shift(null);
+ ce.names = new ArgumentLabels();
+ ce.names.shift(ArgumentLabel(cast(Identifier) null, Loc.init));
ce.isUfcsRewrite = true;
return null;
}
@@ -4115,16 +4115,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Look for what user might have meant
*/
- if (const n = importHint(exp.ident.toString()))
- error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
- else if (auto s2 = sc.search_correct(exp.ident))
- error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
- else if (const p = Scope.search_correct_C(exp.ident))
- error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
- else if (exp.ident == Id.dollar)
- error(exp.loc, "undefined identifier `$`");
+ if (!(sc && sc.inCfile))
+ {
+ if (const n = importHint(exp.ident.toString()))
+ error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
+ else if (auto s2 = sc.search_correct(exp.ident))
+ error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
+ else if (const p = Scope.search_correct_C(exp.ident))
+ error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
+ else if (exp.ident == Id.dollar)
+ error(exp.loc, "undefined identifier `$`");
+ else
+ error(exp.loc, "undefined identifier `%s`", exp.ident.toChars());
+ }
else
- error(exp.loc, "undefined identifier `%s`", exp.ident.toChars());
+ {
+ if (const n = cIncludeHint(exp.ident.toString()))
+ error(exp.loc, "`%s` is not defined, perhaps `#include %.*s` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
+ else if (auto s2 = sc.search_correct(exp.ident))
+ error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
+ else
+ error(exp.loc, "undefined identifier `%s`", exp.ident.toChars());
+ }
result = ErrorExp.get();
}
@@ -4416,7 +4428,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
buffer.write4(0);
e.setData(buffer.extractData(), newlen, 4);
- if (sc && sc.inCfile)
+ if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tuns32.sarrayOf(e.len + 1);
else
e.type = Type.tdchar.immutableOf().arrayOf();
@@ -4441,7 +4453,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
buffer.writeUTF16(0);
e.setData(buffer.extractData(), newlen, 2);
- if (sc && sc.inCfile)
+ if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tuns16.sarrayOf(e.len + 1);
else
e.type = Type.twchar.immutableOf().arrayOf();
@@ -4453,7 +4465,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
goto default;
default:
- if (sc && sc.inCfile)
+ if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tchar.sarrayOf(e.len + 1);
else
e.type = Type.tchar.immutableOf().arrayOf();
@@ -4551,7 +4563,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
}
-
+ if (e.type)
+ {
+ // already done, but we might have missed generating type info
+ semanticTypeInfo(sc, e.type);
+ result = e;
+ return;
+ }
// Run semantic() on each element
bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc);
bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc);
@@ -4894,6 +4912,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
error(p.loc, "PlacementExpression `%s` of type `%s` be unshared and mutable", p.toChars(), toChars(p.type));
return setError();
}
+ checkModifiable(exp.placement, sc);
}
//for error messages if the argument in [] is not convertible to size_t
@@ -5294,10 +5313,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
if (exp.names)
{
- exp.arguments = resolveStructLiteralNamedArgs(sd, exp.type, sc, exp.loc,
- exp.names ? (*exp.names)[] : null,
+ exp.arguments = resolveStructLiteralNamedArgs(sd, exp.type, sc, exp.loc, exp.names.length,
+ i => (*exp.names)[i].name,
(size_t i, Type t) => (*exp.arguments)[i],
- i => (*exp.arguments)[i].loc
+ i => (*exp.arguments)[i].loc,
+ i => (*exp.names)[i].loc
);
if (!exp.arguments)
return setError();
@@ -5361,9 +5381,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Expression arg = (*exp.arguments)[i];
- if (exp.names && (*exp.names)[i])
+ if (exp.names && (*exp.names)[i].name)
{
- error(exp.loc, "no named argument `%s` allowed for array dimension", (*exp.names)[i].toChars());
+ error(exp.loc, "no named argument `%s` allowed for array dimension", (*exp.names)[i].name.toChars());
return setError();
}
@@ -5477,9 +5497,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (nargs == 1)
{
- if (exp.names && (*exp.names)[0])
+ if (exp.names && (*exp.names)[0].name)
{
- error(exp.loc, "no named argument `%s` allowed for scalar", (*exp.names)[0].toChars());
+ error(exp.loc, "no named argument `%s` allowed for scalar", (*exp.names)[0].name.toChars());
return setError();
}
Expression e = (*exp.arguments)[0];
@@ -6269,10 +6289,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expressions* resolvedArgs = exp.arguments;
if (exp.names)
{
- resolvedArgs = resolveStructLiteralNamedArgs(sd, exp.e1.type, sc, exp.loc,
- (*exp.names)[],
+ resolvedArgs = resolveStructLiteralNamedArgs(sd, exp.e1.type, sc, exp.loc, exp.names.length,
+ i => (*exp.names)[i].name,
(size_t i, Type t) => (*exp.arguments)[i],
- i => (*exp.arguments)[i].loc
+ i => (*exp.arguments)[i].loc,
+ i => (*exp.names)[i].loc
);
if (!resolvedArgs)
{
@@ -7303,6 +7324,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sc2.tinst = null;
sc2.minst = null;
sc2.fullinst = true;
+ sc2.traitsCompiles = true;
Type t = dmd.typesem.trySemantic(e.targ, e.loc, sc2);
sc2.pop();
if (!t) // errors, so condition is false
@@ -8177,37 +8199,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.arrow) // ImportC only
exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
- if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
- {
- // C11 6.5.3 says _Alignof only applies to types
- Expression e;
- Type t;
- Dsymbol s;
- dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
- if (e)
- {
- error(exp.e1.loc, "argument to `_Alignof` must be a type");
- return setError();
- }
- else if (t)
- {
- // Note similarity to getProperty() implementation of __xalignof
- const explicitAlignment = t.alignment();
- const naturalAlignment = t.alignsize();
- const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
- result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
- }
- else if (s)
- {
- error(exp.e1.loc, "argument to `_Alignof` must be a type");
- return setError();
- }
- else
- assert(0);
- return;
- }
-
- if (exp.ident != Id.__sizeof)
+ if (exp.ident != Id.__sizeof && exp.ident != Id.__xalignof)
{
result = fieldLookup(exp.e1, sc, exp.ident, exp.arrow);
return;
@@ -10595,7 +10587,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
TupleDeclaration td = isAliasThisTuple(e2x);
if (!td)
- goto Lnomatch;
+ {
+ Lnomatch:
+ error(exp.loc, "cannot assign `%s` to expression sequence `%s`",
+ exp.e2.type.toChars(), exp.e1.type.toChars());
+ return setError();
+ }
assert(exp.e1.type.ty == Ttuple);
TypeTuple tt = cast(TypeTuple)exp.e1.type;
@@ -10637,7 +10634,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Do not need to overwrite this.e2
goto Ltupleassign;
}
- Lnomatch:
}
/* Inside constructor, if this is the first assignment of object field,
@@ -11241,25 +11237,30 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
if (auto ale = exp.e1.isArrayLengthExp())
{
- // e1 is not an lvalue, but we let code generator handle it
+ // Ensure e1 is a modifiable lvalue
auto ale1x = ale.e1.modifiableLvalueImpl(sc, exp.e1);
if (ale1x.op == EXP.error)
return setResult(ale1x);
ale.e1 = ale1x;
+ // Ensure the element type has a valid constructor
Type tn = ale.e1.type.toBasetype().nextOf();
checkDefCtor(ale.loc, tn);
+ // Choose correct GC hook
Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
- if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
+
+ // Verify the correct hook exists
+ if (!verifyHookExist(exp.loc, *sc, hook, "resizing arrays"))
return setError();
exp.e2 = exp.e2.expressionSemantic(sc);
auto lc = lastComma(exp.e2);
lc = lc.optimize(WANTvalue);
- // use slice expression when arr.length = 0 to avoid runtime call
- if(lc.op == EXP.int64 && lc.toInteger() == 0)
+
+ // Optimize case where arr.length = 0
+ if (lc.op == EXP.int64 && lc.toInteger() == 0)
{
Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
Expression as = new AssignExp(ale.loc, ale.e1, se);
@@ -11269,30 +11270,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setResult(res);
}
- if (!sc.needsCodegen()) // if compile time creature only
+ if (!sc.needsCodegen()) // Compile-time only case
{
exp.type = Type.tsize_t;
return setResult(exp);
}
- // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
+ // Ensure correct reference for _d_arraysetlengthT
Expression id = new IdentifierExp(ale.loc, Id.empty);
id = new DotIdExp(ale.loc, id, Id.object);
- auto tiargs = new Objects();
- tiargs.push(ale.e1.type);
- id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
id = new DotIdExp(ale.loc, id, hook);
id = id.expressionSemantic(sc);
+ // Generate call: _d_arraysetlengthT(e1, e2)
auto arguments = new Expressions();
- arguments.push(ale.e1);
- arguments.push(exp.e2);
+ arguments.push(ale.e1); // array
+ arguments.push(exp.e2); // new length
Expression ce = new CallExp(ale.loc, id, arguments).expressionSemantic(sc);
auto res = new LoweredAssignExp(exp, ce);
- // if (global.params.verbose)
- // message("lowered %s =>\n %s", exp.toChars(), res.toChars());
res.type = Type.tsize_t;
+
return setResult(res);
}
else if (auto se = exp.e1.isSliceExp())
@@ -11761,6 +11759,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
res = new LoweredAssignExp(ae, res);
res.type = ae.type;
+ res = res.checkGC(sc);
return res;
}
@@ -12795,6 +12794,57 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ // Inline the expression, if possible.
+ PowExp pe = cast(PowExp)e;
+ if (pe.e1.type.isScalar() && pe.e2.isIntegerExp())
+ {
+ Expression one;
+ if (pe.e1.type.isIntegral()) {
+ one = new IntegerExp(e.loc, 1, pe.e1.type);
+ } else {
+ one = new RealExp(e.loc, CTFloat.one, pe.e1.type);
+ }
+
+ const expo = cast(sinteger_t)pe.e2.toInteger();
+ // Replace e1 ^^ -1 with 1 / e1
+ if (expo == -1)
+ {
+ Expression ex = new DivExp(exp.loc, one, pe.e1);
+ ex = ex.expressionSemantic(sc);
+ result = ex;
+ return;
+ }
+ // Replace e1 ^^ 0 with (e1, 1)
+ else if (expo == 0)
+ {
+ Expression ex = new CommaExp(exp.loc, pe.e1, one, exp);
+ ex = ex.expressionSemantic(sc);
+ result = ex;
+ return;
+ }
+ // Replace e1 ^^ 1 with e1
+ else if (expo == 1)
+ {
+ Expression ex = pe.e1;
+ ex.loc = exp.loc;
+ ex = ex.expressionSemantic(sc);
+ result = ex;
+ return;
+ }
+ // Replace e1 ^^ 2 with e1 * e1
+ else if (expo == 2)
+ {
+ auto v = copyToTemp(STC.const_, "__powtmp", pe.e1);
+ auto ve = new VarExp(exp.loc, v);
+ auto de = new DeclarationExp(exp.e1.loc, v);
+ auto me = new MulExp(exp.e2.loc, ve, ve);
+ Expression ex = new CommaExp(exp.loc, de, me, exp);
+ ex = ex.expressionSemantic(sc);
+ result = ex;
+ return;
+ }
+ }
+
Module mmath = Module.loadStdMath();
if (!mmath)
{
@@ -13874,6 +13924,7 @@ private bool expressionSemanticDone(Expression e)
|| e.isTypeExp() // stores its type in the Expression.type field
|| e.isCompoundLiteralExp() // stores its `(type) {}` in type field, gets rewritten to struct literal
|| e.isVarExp() // type sometimes gets set already before semantic
+ || (e.isAssocArrayLiteralExp() && !e.type.vtinfo) // semanticTypeInfo not run during initialization
);
}
@@ -15771,11 +15822,12 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action
}
/***************************************
- * Parameters:
- * sc: scope
- * flag: 1: do not issue error message for invalid modification
- 2: the exp is a DotVarExp and a subfield of the leftmost
- variable is modified
+ * Params:
+ * exp = expression to check if modifiable
+ * sc = scope
+ * flag = noError - do not issue error message for invalid modification
+ fieldAssign - exp is a DotVarExp and a subfield of the leftmost
+ variable is modified
* Returns:
* Whether the type is modifiable
*/
@@ -16728,11 +16780,12 @@ enum ModifyFlags
}
/*************************************
- * Check to see if declaration can be modified in this context (sc).
+ * Check to see if `d` can be modified in this context `sc`.
* Issue error if not.
* Params:
+ * d = declaration to check
* loc = location for error messages
- * e1 = `null` or `this` expression when this declaration is a field
+ * e1 = `null` or `this` expression when `d` is a field
* sc = context
* flag = if the first bit is set it means do not issue error message for
* invalid modification; if the second bit is set, it means that
@@ -16742,6 +16795,7 @@ enum ModifyFlags
*/
private Modifiable checkModify(Declaration d, Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
{
+ //printf("checkModify() d: %s, e1: %s\n", d.toChars(), e1.toChars());
VarDeclaration v = d.isVarDeclaration();
if (v && v.canassign)
return Modifiable.initialization;
@@ -16787,15 +16841,19 @@ private Modifiable checkModify(Declaration d, Loc loc, Scope* sc, Expression e1,
}
/***********************************************
- * Mark variable v as modified if it is inside a constructor that var
+ * Mark variable `var` as modified if it is inside a constructor that `var`
* is a field in.
* Also used to allow immutable globals to be initialized inside a static constructor.
+ * Params:
+ * loc = location for error messages
+ * sc = scope
+ * var = field
* Returns:
- * true if it's an initialization of v
+ * true if it's an initialization of `var`
*/
private bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
{
- //printf("modifyFieldVar(var = %s)\n", var.toChars());
+ //printf("modifyFieldVar(var: %s, e1: %s)\n", var.toChars(), e1.toChars());
Dsymbol s = sc.func;
while (1)
{
@@ -16811,7 +16869,7 @@ private bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e
bool result = true;
var.ctorinit = true;
- //printf("setting ctorinit\n");
+ //printf("setting ctorinit for %s\n", var.toChars());
if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
{
@@ -17457,7 +17515,7 @@ bool fill(StructDeclaration sd, Loc loc, ref Expressions elements, bool ctorinit
* sfe = The 'static foreach'.
* sc = The current scope.
*/
-extern (C++) void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc)
+void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc)
{
import dmd.statement;
@@ -17671,3 +17729,143 @@ extern(D) void lowerArrayAggregate(StaticForeach sfe, Scope* sc)
sfe.aggrfe.aggr = sfe.aggrfe.aggr.optimize(WANTvalue);
sfe.aggrfe.aggr = sfe.aggrfe.aggr.ctfeInterpret();
}
+
+int include(Condition c, Scope* sc)
+{
+ scope v = new IncludeVisitor(sc);
+ c.accept(v);
+ return v.result;
+}
+
+private extern(C++) class IncludeVisitor : Visitor {
+ alias visit = Visitor.visit;
+
+ Scope *sc;
+ int result;
+
+ this(Scope* sc)
+ {
+ this.sc = sc;
+ }
+
+ override void visit(DebugCondition dc)
+ {
+ //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
+ if (dc.inc != Include.notComputed)
+ {
+ result = dc.inc == Include.yes;
+ return;
+ }
+ dc.inc = Include.no;
+ bool definedInModule = false;
+ if (dc.ident)
+ {
+ if (dc.mod.debugids && findCondition(*dc.mod.debugids, dc.ident))
+ {
+ dc.inc = Include.yes;
+ definedInModule = true;
+ }
+ else if (findCondition(global.debugids, dc.ident))
+ dc.inc = Include.yes;
+ else
+ {
+ if (!dc.mod.debugidsNot)
+ dc.mod.debugidsNot = new Identifiers();
+ dc.mod.debugidsNot.push(dc.ident);
+ }
+ }
+ else if (global.params.debugEnabled)
+ dc.inc = Include.yes;
+
+ if (!definedInModule)
+ printDepsConditional(sc, dc, "depsDebug ");
+ result = (dc.inc == Include.yes);
+ }
+
+ override void visit(VersionCondition vc)
+ {
+ //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
+ //if (ident) printf("\tident = '%s'\n", ident.toChars());
+ if (vc.inc != Include.notComputed)
+ {
+ result = vc.inc == Include.yes;
+ return;
+ }
+
+ vc.inc = Include.no;
+ bool definedInModule = false;
+ if (vc.ident)
+ {
+ if (vc.mod.versionids && findCondition(*vc.mod.versionids, vc.ident))
+ {
+ vc.inc = Include.yes;
+ definedInModule = true;
+ }
+ else if (findCondition(global.versionids, vc.ident))
+ vc.inc = Include.yes;
+ else
+ {
+ if (!vc.mod.versionidsNot)
+ vc.mod.versionidsNot = new Identifiers();
+ vc.mod.versionidsNot.push(vc.ident);
+ }
+ }
+ if (!definedInModule &&
+ (!vc.ident || (!vc.isReserved(vc.ident.toString()) && vc.ident != Id._unittest && vc.ident != Id._assert)))
+ {
+ printDepsConditional(sc, vc, "depsVersion ");
+ }
+ result = (vc.inc == Include.yes);
+ }
+
+ override void visit(StaticIfCondition sic)
+ {
+ // printf("StaticIfCondition::include(sc = %p) this=%p inc = %d\n", sc, this, inc);
+
+ int errorReturn()
+ {
+ if (!global.gag)
+ sic.inc = Include.no; // so we don't see the error message again
+ return 0;
+ }
+
+ if (sic.inc != Include.notComputed)
+ {
+ result = sic.inc == Include.yes;
+ return;
+ }
+
+ if (!sc)
+ {
+ error(sic.loc, "`static if` conditional cannot be at global scope");
+ sic.inc = Include.no;
+ result = 0;
+ return;
+ }
+
+ import dmd.staticcond;
+ bool errors;
+
+ bool local_result = evalStaticCondition(sc, sic.exp, sic.exp, errors);
+
+ // Prevent repeated condition evaluation.
+ // See: fail_compilation/fail7815.d
+ if (sic.inc != Include.notComputed)
+ {
+ result = (sic.inc == Include.yes);
+ return;
+ }
+
+ if (errors)
+ {
+ result = errorReturn();
+ return;
+ }
+
+ if (local_result)
+ sic.inc = Include.yes;
+ else
+ sic.inc = Include.no;
+ result = (sic.inc == Include.yes);
+ }
+}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 064b67f96060..6a573810a4b9 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -820,15 +820,13 @@ extern (C++) class FuncDeclaration : Declaration
bool addPreInvariant()
{
auto ad = isThis();
- ClassDeclaration cd = ad ? ad.isClassDeclaration() : null;
- return (ad && !(cd && cd.isCPPclass()) && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
+ return (ad && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
}
bool addPostInvariant()
{
auto ad = isThis();
- ClassDeclaration cd = ad ? ad.isClassDeclaration() : null;
- return (ad && !(cd && cd.isCPPclass()) && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
+ return (ad && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
}
override const(char)* kind() const
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index 1231496e41ab..10f6f154b2ff 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -235,6 +235,17 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested()))
funcdecl.storage_class &= ~STC.TYPECTOR;
+ auto tf = funcdecl.type.isTypeFunction();
+ if ((funcdecl.storage_class & STC.auto_) && tf.isRef && !funcdecl.inferRetType)
+ {
+ if (!(funcdecl.storage_class & STC.autoref))
+ {
+ // @@@DEPRECATED_2.122@@@
+ // Deprecated in 2.112, turn into an error in 2.122
+ deprecation(funcdecl.loc, "`auto ref` return type must have `auto` and `ref` adjacent");
+ funcdecl.storage_class |= STC.autoref;
+ }
+ }
//printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal());
if (sc.traitsCompiles)
@@ -272,20 +283,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
if (!funcdecl.originalType)
funcdecl.originalType = funcdecl.type.syntaxCopy();
- static TypeFunction getFunctionType(FuncDeclaration fd)
- {
- if (auto tf = fd.type.isTypeFunction())
- return tf;
-
- if (!fd.type.isTypeError())
- {
- .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
- fd.type = Type.terror;
- }
- fd.errors = true;
- return null;
- }
-
if (sc.inCfile)
{
/* C11 allows a function to be declared with a typedef, D does not.
@@ -313,7 +310,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
sc = sc.push();
sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type
- TypeFunction tf = funcdecl.type.toTypeFunction();
if (sc.func)
{
/* If the nesting parent is pure without inference,
@@ -563,587 +559,697 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
if (ClassDeclaration cd = parent.isClassDeclaration())
{
- parent = cd = objc.getParent(funcdecl, cd);
+ switch (classFuncSemantic(cd, funcdecl, parent, sc, f))
+ {
+ case 0: break;
+ case 1: goto Ldone;
+ case 2: return;
+ default: assert(0);
+ }
+ }
+ else if (funcdecl.isOverride() && !parent.isTemplateInstance())
+ .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
+
+ if (auto ti = parent.isTemplateInstance)
+ {
+ objc.setSelector(funcdecl, sc);
+ objc.setAsOptional(funcdecl, sc);
+ }
- if (funcdecl.isCtorDeclaration())
+ objc.validateSelector(funcdecl);
+ objc.validateOptional(funcdecl);
+ // Reflect this.type to f because it could be changed by findVtblIndex
+ f = funcdecl.type.toTypeFunction();
+
+Ldone:
+ if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
+ .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
+
+ /* Do not allow template instances to add virtual functions
+ * to a class.
+ */
+ if (funcdecl.isVirtual())
+ {
+ if (auto ti = parent.isTemplateInstance())
{
- goto Ldone;
+ // Take care of nested templates
+ while (1)
+ {
+ TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
+ if (!ti2)
+ break;
+ ti = ti2;
+ }
+
+ // If it's a member template
+ if (ClassDeclaration cd = ti.tempdecl.isClassMember())
+ {
+ .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
+ }
}
+ }
+
+ funcdecl.checkMain(); // Check main() parameters and return type
- if (funcdecl.storage_class & STC.abstract_)
- cd.isabstract = ThreeState.yes;
+ /* Purity and safety can be inferred for some functions by examining
+ * the function body.
+ */
+ if (funcdecl.canInferAttributes(sc))
+ funcdecl.initInferAttributes();
+
+ funcdecl.semanticRun = PASS.semanticdone;
- // if static function, do not put in vtbl[]
- if (!funcdecl.isVirtual())
+ /* Save scope for possible later use (if we need the
+ * function internals)
+ */
+ funcdecl._scope = sc.copy();
+ funcdecl._scope.setNoFree();
+
+ __gshared bool printedMain = false; // semantic might run more than once
+ if (global.params.v.verbose && !printedMain)
+ {
+ const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
+ Module mod = sc._module;
+
+ if (type && mod)
{
- //printf("\tnot virtual\n");
- goto Ldone;
+ printedMain = true;
+ auto name = mod.srcfile.toChars();
+ auto path = FileName.searchPath(global.importPaths, name, true);
+ message("entry %-10s\t%s", type, path ? path : name);
}
- // Suppress further errors if the return type is an error
- if (funcdecl.type.nextOf() == Type.terror)
- goto Ldone;
+ }
- bool may_override = false;
- for (size_t i = 0; i < cd.baseclasses.length; i++)
+ if (funcdecl.fbody && sc._module.isRoot() &&
+ (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
+ global.hasMainFunction = true;
+
+ if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
+ {
+ // check if `_d_cmain` is defined
+ bool cmainTemplateExists()
{
- BaseClass* b = (*cd.baseclasses)[i];
- ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
- if (!cbd)
+ Dsymbol pscopesym;
+ auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym);
+ if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object))
+ if (moduleSymbol.search(funcdecl.loc, Id.CMain))
+ return true;
+
+ return false;
+ }
+
+ // Only mixin `_d_cmain` if it is defined
+ if (cmainTemplateExists())
+ {
+ // add `mixin _d_cmain!();` to the declaring module
+ auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain);
+ auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null);
+ sc._module.members.push(tm);
+ }
+ }
+
+ assert(funcdecl.type.ty != Terror || funcdecl.errors);
+
+ // semantic for parameters' UDAs
+ foreach (i, param; f.parameterList)
+ {
+ if (param && param.userAttribDecl)
+ param.userAttribDecl.dsymbolSemantic(sc);
+ }
+}
+
+/**
+ Returns:
+ 0 if semantic analysis in `funcDeclarationSemantic` should continue as normal
+ 1 if it should skip over some analysis and `goto Ldone;`
+ 2 if `funcDeclarationSemantic` should return early because of forward refernce error or
+ the derived class cd doesn't have its vtbl[] allocated yet
+ */
+private int classFuncSemantic(ClassDeclaration cd, FuncDeclaration funcdecl,
+ ref Dsymbol parent, Scope* sc, TypeFunction f)
+{
+ parent = cd = objc.getParent(funcdecl, cd);
+
+ if (funcdecl.isCtorDeclaration())
+ {
+ return 1;
+ }
+
+ if (funcdecl.storage_class & STC.abstract_)
+ cd.isabstract = ThreeState.yes;
+
+ // if static function, do not put in vtbl[]
+ if (!funcdecl.isVirtual())
+ {
+ //printf("\tnot virtual\n");
+ return 1;
+ }
+ // Suppress further errors if the return type is an error
+ if (funcdecl.type.nextOf() == Type.terror)
+ return 1;
+
+ bool may_override = false;
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
+ {
+ BaseClass* b = (*cd.baseclasses)[i];
+ ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
+ if (!cbd)
+ continue;
+ for (size_t j = 0; j < cbd.vtbl.length; j++)
+ {
+ FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
+ if (!f2 || f2.ident != funcdecl.ident)
continue;
- for (size_t j = 0; j < cbd.vtbl.length; j++)
+ if (cbd.parent && cbd.parent.isTemplateInstance())
{
- FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
- if (!f2 || f2.ident != funcdecl.ident)
- continue;
- if (cbd.parent && cbd.parent.isTemplateInstance())
- {
- if (!functionSemantic(f2))
- goto Ldone;
- }
- may_override = true;
+ if (!functionSemantic(f2))
+ return 1;
}
+ may_override = true;
}
- if (may_override && funcdecl.type.nextOf() is null)
+ }
+ if (may_override && funcdecl.type.nextOf() is null)
+ {
+ /* If same name function exists in base class but 'this' is auto return,
+ * cannot find index of base class's vtbl[] to override.
+ */
+ .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
+ }
+
+ /* Find index of existing function in base class's vtbl[] to override
+ * (the index will be the same as in cd's current vtbl[])
+ */
+ int vi = cd.baseClass ? findVtblIndex(funcdecl, cd.baseClass.vtbl[]) : -1;
+
+ bool doesoverride = false;
+ switch (vi)
+ {
+ case -1:
+ Lintro:
+ /* Didn't find one, so
+ * This is an 'introducing' function which gets a new
+ * slot in the vtbl[].
+ */
+
+ // Verify this doesn't override previous final function
+ if (cd.baseClass)
{
- /* If same name function exists in base class but 'this' is auto return,
- * cannot find index of base class's vtbl[] to override.
- */
- .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
+ Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
+ if (s)
+ {
+ if (auto f2 = s.isFuncDeclaration())
+ {
+ f2 = f2.overloadExactMatch(funcdecl.type);
+ if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
+ .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
+ }
+ }
}
- /* Find index of existing function in base class's vtbl[] to override
- * (the index will be the same as in cd's current vtbl[])
+ /* These quirky conditions mimic what happens when virtual
+ inheritance is implemented by producing a virtual base table
+ with offsets to each of the virtual bases.
*/
- int vi = cd.baseClass ? findVtblIndex(funcdecl, cd.baseClass.vtbl[]) : -1;
-
- bool doesoverride = false;
- switch (vi)
+ if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
+ cd.baseClass && cd.baseClass.vtbl.length)
{
- case -1:
- Lintro:
- /* Didn't find one, so
- * This is an 'introducing' function which gets a new
- * slot in the vtbl[].
+ /* if overriding an interface function, then this is not
+ * introducing and don't put it in the class vtbl[]
*/
+ funcdecl.interfaceVirtual = overrideInterface(funcdecl);
+ if (funcdecl.interfaceVirtual)
+ {
+ //printf("\tinterface function %s\n", toChars());
+ cd.vtblFinal.push(funcdecl);
+ goto Linterfaces;
+ }
+ }
- // Verify this doesn't override previous final function
- if (cd.baseClass)
+ if (funcdecl.isFinalFunc())
+ {
+ // Don't check here, as it may override an interface function
+ //if (isOverride())
+ // error("is marked as override, but does not override any function");
+ cd.vtblFinal.push(funcdecl);
+ }
+ else
+ {
+ //printf("\tintroducing function %s\n", funcdecl.toChars());
+ funcdecl.isIntroducing = true;
+ if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
{
- Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
- if (s)
+ /* Overloaded functions with same name are grouped and in reverse order.
+ * Search for first function of overload group, and insert
+ * funcdecl into vtbl[] immediately before it.
+ */
+ funcdecl.vtblIndex = cast(int)cd.vtbl.length;
+ bool found;
+ foreach (const i, s; cd.vtbl)
{
- if (auto f2 = s.isFuncDeclaration())
+ if (found)
+ // the rest get shifted forward
+ ++s.isFuncDeclaration().vtblIndex;
+ else if (s.ident == funcdecl.ident && s.parent == parent)
{
- f2 = f2.overloadExactMatch(funcdecl.type);
- if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
- .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
+ // found first function of overload group
+ funcdecl.vtblIndex = cast(int)i;
+ found = true;
+ ++s.isFuncDeclaration().vtblIndex;
}
}
+ cd.vtbl.insert(funcdecl.vtblIndex, funcdecl);
+
+ debug foreach (const i, s; cd.vtbl)
+ {
+ // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl),
+ // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception.
+ if (auto fd = s.isFuncDeclaration())
+ assert(fd.vtblIndex == i ||
+ (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) ||
+ funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls
+ }
+ }
+ else
+ {
+ // Append to end of vtbl[]
+ vi = cast(int)cd.vtbl.length;
+ cd.vtbl.push(funcdecl);
+ funcdecl.vtblIndex = vi;
}
+ }
+ break;
- /* These quirky conditions mimic what happens when virtual
- inheritance is implemented by producing a virtual base table
- with offsets to each of the virtual bases.
- */
- if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
- cd.baseClass && cd.baseClass.vtbl.length)
+ case -2:
+ // can't determine because of forward references
+ funcdecl.errors = true;
+ return 2;
+
+ default:
+ {
+ if (vi >= cd.vtbl.length)
{
- /* if overriding an interface function, then this is not
- * introducing and don't put it in the class vtbl[]
+ /* the derived class cd doesn't have its vtbl[] allocated yet.
+ * https://issues.dlang.org/show_bug.cgi?id=21008
*/
- funcdecl.interfaceVirtual = overrideInterface(funcdecl);
- if (funcdecl.interfaceVirtual)
- {
- //printf("\tinterface function %s\n", toChars());
- cd.vtblFinal.push(funcdecl);
- goto Linterfaces;
- }
+ .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
+ funcdecl.errors = true;
+ return 2;
}
+ FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
+ FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
+ // This function is covariant with fdv
- if (funcdecl.isFinalFunc())
+ if (fdc == funcdecl)
{
- // Don't check here, as it may override an interface function
- //if (isOverride())
- // error("is marked as override, but does not override any function");
- cd.vtblFinal.push(funcdecl);
+ doesoverride = true;
+ break;
}
- else
+
+ auto vtf = getFunctionType(fdv);
+ if (vtf.trust > TRUST.system && f.trust == TRUST.system)
+ .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
+ fdv.toPrettyChars);
+
+ if (fdc.toParent() == parent)
{
- //printf("\tintroducing function %s\n", funcdecl.toChars());
- funcdecl.isIntroducing = true;
- if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
- {
- /* Overloaded functions with same name are grouped and in reverse order.
- * Search for first function of overload group, and insert
- * funcdecl into vtbl[] immediately before it.
- */
- funcdecl.vtblIndex = cast(int)cd.vtbl.length;
- bool found;
- foreach (const i, s; cd.vtbl)
- {
- if (found)
- // the rest get shifted forward
- ++s.isFuncDeclaration().vtblIndex;
- else if (s.ident == funcdecl.ident && s.parent == parent)
- {
- // found first function of overload group
- funcdecl.vtblIndex = cast(int)i;
- found = true;
- ++s.isFuncDeclaration().vtblIndex;
- }
- }
- cd.vtbl.insert(funcdecl.vtblIndex, funcdecl);
+ //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
+ // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(),
+ // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(),
+ // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars());
+
+ // fdc overrides fdv exactly, then this introduces new function.
+ if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod)
+ goto Lintro;
+ }
- debug foreach (const i, s; cd.vtbl)
- {
- // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl),
- // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception.
- if (auto fd = s.isFuncDeclaration())
- assert(fd.vtblIndex == i ||
- (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) ||
- funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls
- }
+ if (fdv.isDeprecated && !funcdecl.isDeprecated)
+ deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
+ funcdecl.toPrettyChars, fdv.toPrettyChars);
+
+ // This function overrides fdv
+ if (fdv.isFinalFunc())
+ .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
+
+ if (!funcdecl.isOverride())
+ {
+ if (fdv.isFuture())
+ {
+ deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former",
+ funcdecl.toPrettyChars());
+ deprecationSupplemental(fdv.loc, "base method `%s` defined here",
+ fdv.toPrettyChars());
+ // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
+ goto Lintro;
}
else
{
- // Append to end of vtbl[]
- vi = cast(int)cd.vtbl.length;
- cd.vtbl.push(funcdecl);
- funcdecl.vtblIndex = vi;
+ // https://issues.dlang.org/show_bug.cgi?id=17349
+ error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
+ fdv.toPrettyChars(), funcdecl.toPrettyChars());
}
}
- break;
-
- case -2:
- // can't determine because of forward references
- funcdecl.errors = true;
- return;
-
- default:
+ doesoverride = true;
+ if (fdc.toParent() == parent)
{
- if (vi >= cd.vtbl.length)
+ // If both are mixins, or both are not, then error.
+ // If either is not, the one that is not overrides the other.
+ bool thismixin = funcdecl.parent.isClassDeclaration() !is null;
+ bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
+ if (thismixin == fdcmixin)
+ {
+ .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
+ }
+ /*
+ * https://issues.dlang.org/show_bug.cgi?id=711
+ *
+ * If an overriding method is introduced through a mixin,
+ * we need to update the vtbl so that both methods are
+ * present.
+ */
+ else if (thismixin)
{
- /* the derived class cd doesn't have its vtbl[] allocated yet.
- * https://issues.dlang.org/show_bug.cgi?id=21008
+ /* if the mixin introduced the overriding method, then reintroduce it
+ * in the vtbl. The initial entry for the mixined method
+ * will be updated at the end of the enclosing `if` block
+ * to point to the current (non-mixined) function.
*/
- .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
- funcdecl.errors = true;
- return;
+ auto vitmp = cast(int)cd.vtbl.length;
+ cd.vtbl.push(fdc);
+ fdc.vtblIndex = vitmp;
}
- FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
- FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
- // This function is covariant with fdv
-
- if (fdc == funcdecl)
+ else if (fdcmixin)
{
- doesoverride = true;
+ /* if the current overriding function is coming from a
+ * mixined block, then push the current function in the
+ * vtbl, but keep the previous (non-mixined) function as
+ * the overriding one.
+ */
+ auto vitmp = cast(int)cd.vtbl.length;
+ cd.vtbl.push(funcdecl);
+ funcdecl.vtblIndex = vitmp;
break;
}
-
- auto vtf = getFunctionType(fdv);
- if (vtf.trust > TRUST.system && f.trust == TRUST.system)
- .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
- fdv.toPrettyChars);
-
- if (fdc.toParent() == parent)
+ else // fdc overrides fdv
{
- //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
- // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(),
- // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(),
- // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars());
-
- // fdc overrides fdv exactly, then this introduces new function.
- if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod)
- goto Lintro;
+ // this doesn't override any function
+ break;
}
+ }
+ cd.vtbl[vi] = funcdecl;
+ funcdecl.vtblIndex = vi;
- if (fdv.isDeprecated && !funcdecl.isDeprecated)
- deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
- funcdecl.toPrettyChars, fdv.toPrettyChars);
-
- // This function overrides fdv
- if (fdv.isFinalFunc())
- .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
+ /* Remember which functions this overrides
+ */
+ funcdecl.foverrides.push(fdv);
+
+ /* This works by whenever this function is called,
+ * it actually returns tintro, which gets dynamically
+ * cast to type. But we know that tintro is a base
+ * of type, so we could optimize it by not doing a
+ * dynamic cast, but just subtracting the isBaseOf()
+ * offset if the value is != null.
+ */
- if (!funcdecl.isOverride())
- {
- if (fdv.isFuture())
- {
- deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former",
- funcdecl.toPrettyChars());
- deprecationSupplemental(fdv.loc, "base method `%s` defined here",
- fdv.toPrettyChars());
- // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
- goto Lintro;
- }
- else
- {
- // https://issues.dlang.org/show_bug.cgi?id=17349
- error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
- fdv.toPrettyChars(), funcdecl.toPrettyChars());
- }
- }
- doesoverride = true;
- if (fdc.toParent() == parent)
+ if (fdv.tintro)
+ funcdecl.tintro = fdv.tintro;
+ else if (!funcdecl.type.equals(fdv.type))
+ {
+ auto tnext = funcdecl.type.nextOf();
+ if (auto handle = tnext.isClassHandle())
{
- // If both are mixins, or both are not, then error.
- // If either is not, the one that is not overrides the other.
- bool thismixin = funcdecl.parent.isClassDeclaration() !is null;
- bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
- if (thismixin == fdcmixin)
- {
- .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
- }
- /*
- * https://issues.dlang.org/show_bug.cgi?id=711
- *
- * If an overriding method is introduced through a mixin,
- * we need to update the vtbl so that both methods are
- * present.
- */
- else if (thismixin)
- {
- /* if the mixin introduced the overriding method, then reintroduce it
- * in the vtbl. The initial entry for the mixined method
- * will be updated at the end of the enclosing `if` block
- * to point to the current (non-mixined) function.
- */
- auto vitmp = cast(int)cd.vtbl.length;
- cd.vtbl.push(fdc);
- fdc.vtblIndex = vitmp;
- }
- else if (fdcmixin)
- {
- /* if the current overriding function is coming from a
- * mixined block, then push the current function in the
- * vtbl, but keep the previous (non-mixined) function as
- * the overriding one.
- */
- auto vitmp = cast(int)cd.vtbl.length;
- cd.vtbl.push(funcdecl);
- funcdecl.vtblIndex = vitmp;
- break;
- }
- else // fdc overrides fdv
- {
- // this doesn't override any function
- break;
- }
+ if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
+ handle.dsymbolSemantic(null);
}
- cd.vtbl[vi] = funcdecl;
- funcdecl.vtblIndex = vi;
-
- /* Remember which functions this overrides
+ /* Only need to have a tintro if the vptr
+ * offsets differ
*/
- funcdecl.foverrides.push(fdv);
-
- /* This works by whenever this function is called,
- * it actually returns tintro, which gets dynamically
- * cast to type. But we know that tintro is a base
- * of type, so we could optimize it by not doing a
- * dynamic cast, but just subtracting the isBaseOf()
- * offset if the value is != null.
- */
-
- if (fdv.tintro)
- funcdecl.tintro = fdv.tintro;
- else if (!funcdecl.type.equals(fdv.type))
+ int offset;
+ if (fdv.type.nextOf().isBaseOf(tnext, &offset))
{
- auto tnext = funcdecl.type.nextOf();
- if (auto handle = tnext.isClassHandle())
- {
- if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
- handle.dsymbolSemantic(null);
- }
- /* Only need to have a tintro if the vptr
- * offsets differ
- */
- int offset;
- if (fdv.type.nextOf().isBaseOf(tnext, &offset))
- {
- funcdecl.tintro = fdv.type;
- }
+ funcdecl.tintro = fdv.type;
}
- break;
}
+ break;
}
+ }
- /* Go through all the interface bases.
- * If this function is covariant with any members of those interface
- * functions, set the tintro.
- */
- Linterfaces:
- bool foundVtblMatch = false;
+ /* Go through all the interface bases.
+ * If this function is covariant with any members of those interface
+ * functions, set the tintro.
+ */
+Linterfaces:
+ bool foundVtblMatch = false;
- for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass)
+ for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass)
+ {
+ foreach (b; bcd.interfaces)
{
- foreach (b; bcd.interfaces)
+ vi = findVtblIndex(funcdecl, b.sym.vtbl[]);
+ switch (vi)
{
- vi = findVtblIndex(funcdecl, b.sym.vtbl[]);
- switch (vi)
- {
- case -1:
- break;
+ case -1:
+ break;
- case -2:
- // can't determine because of forward references
- funcdecl.errors = true;
- return;
+ case -2:
+ // can't determine because of forward references
+ funcdecl.errors = true;
+ return 2;
- default:
- {
- auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi];
- Type ti = null;
+ default:
+ {
+ auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi];
+ Type ti = null;
- foundVtblMatch = true;
+ foundVtblMatch = true;
- /* Remember which functions this overrides
- */
- funcdecl.foverrides.push(fdv);
+ /* Remember which functions this overrides
+ */
+ funcdecl.foverrides.push(fdv);
- if (fdv.tintro)
- ti = fdv.tintro;
- else if (!funcdecl.type.equals(fdv.type))
+ if (fdv.tintro)
+ ti = fdv.tintro;
+ else if (!funcdecl.type.equals(fdv.type))
+ {
+ /* Only need to have a tintro if the vptr
+ * offsets differ
+ */
+ int offset;
+ if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
{
- /* Only need to have a tintro if the vptr
- * offsets differ
- */
- int offset;
- if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
- {
- ti = fdv.type;
- }
+ ti = fdv.type;
}
- if (ti)
+ }
+ if (ti)
+ {
+ if (funcdecl.tintro)
{
- if (funcdecl.tintro)
- {
- if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
- {
- .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
- }
- }
- else
+ if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
{
- funcdecl.tintro = ti;
+ .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
}
}
+ else
+ {
+ funcdecl.tintro = ti;
+ }
}
}
}
}
- if (foundVtblMatch)
+ }
+ if (foundVtblMatch)
+ {
+ goto L2;
+ }
+
+ if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override))
+ {
+ BaseClass* bc = null;
+ Dsymbol s = null;
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
- goto L2;
+ bc = (*cd.baseclasses)[i];
+ s = bc.sym.search_correct(funcdecl.ident);
+ if (s)
+ break;
}
- if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override))
+ if (s)
{
- BaseClass* bc = null;
- Dsymbol s = null;
- for (size_t i = 0; i < cd.baseclasses.length; i++)
- {
- bc = (*cd.baseclasses)[i];
- s = bc.sym.search_correct(funcdecl.ident);
- if (s)
- break;
- }
+ HdrGenState hgs;
+ OutBuffer buf;
- if (s)
+ auto fd = s.isFuncDeclaration();
+ functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
+ new Identifier(funcdecl.toPrettyChars()), hgs, null);
+ const(char)* funcdeclToChars = buf.peekChars();
+
+ if (fd)
{
- HdrGenState hgs;
- OutBuffer buf;
+ OutBuffer buf1;
- auto fd = s.isFuncDeclaration();
- functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
- new Identifier(funcdecl.toPrettyChars()), hgs, null);
- const(char)* funcdeclToChars = buf.peekChars();
+ if (fd.ident == funcdecl.ident)
+ hgs.fullQual = true;
- if (fd)
+ // https://issues.dlang.org/show_bug.cgi?id=23745
+ // If the potentially overridden function contains errors,
+ // inform the user to fix that one first
+ if (fd.errors)
{
- OutBuffer buf1;
-
- if (fd.ident == funcdecl.ident)
- hgs.fullQual = true;
+ error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
+ funcdecl.toChars(), fd.toPrettyChars());
+ errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
+ fd.toPrettyChars());
+ }
+ else if (fd.isFinalFunc())
+ {
+ // When trying to override a final method, don't suggest it as a candidate(Issue #19613)
+ .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
- // https://issues.dlang.org/show_bug.cgi?id=23745
- // If the potentially overridden function contains errors,
- // inform the user to fix that one first
- if (fd.errors)
- {
- error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
- funcdecl.toChars(), fd.toPrettyChars());
- errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
- fd.toPrettyChars());
- }
- else
+ // Look for a non-final method with the same name to suggest as an alternative
+ auto cdparent = fd.parent ? fd.parent.isClassDeclaration() : null;
+ if (cdparent)
{
- functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
- new Identifier(fd.toPrettyChars()), hgs, null);
+ Dsymbol nonFinalAlt = null;
- error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
- funcdeclToChars, buf1.peekChars());
- }
+ auto overloadableSyms = cdparent.symtab.lookup(fd.ident);
+ if (overloadableSyms)
+ {
+ // Check each overload to find one that's not final
+ overloadApply(overloadableSyms, (Dsymbol s)
+ {
+ if (auto funcAlt = s.isFuncDeclaration())
+ {
+ if (funcAlt != fd && !funcAlt.isFinalFunc())
+ {
+ nonFinalAlt = funcAlt;
+ return 1;
+ }
+ }
+ return 0;
+ });
+
+ // Provide a helpful suggestion if we found a viable alternative
+ if (nonFinalAlt)
+ {
+ auto funcAlt = nonFinalAlt.isFuncDeclaration();
+ OutBuffer buf2;
+ functionToBufferFull(cast(TypeFunction)(funcAlt.type), buf2,
+ new Identifier(funcAlt.toPrettyChars()), hgs, null);
+ errorSupplemental(funcdecl.loc, "Did you mean to override `%s`?", buf2.peekChars());
+ }
+ }
+ }
}
else
{
- error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
- funcdeclToChars, s.kind, s.toPrettyChars());
- errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
- }
- }
- else
- .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
- }
+ functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
+ new Identifier(fd.toPrettyChars()), hgs, null);
- L2:
- objc.setSelector(funcdecl, sc);
- objc.checkLinkage(funcdecl);
- objc.addToClassMethodList(funcdecl, cd);
- objc.setAsOptional(funcdecl, sc);
+ error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
+ funcdeclToChars, buf1.peekChars());
- /* Go through all the interface bases.
- * Disallow overriding any final functions in the interface(s).
- */
- foreach (b; cd.interfaces)
- {
- if (b.sym)
- {
- if (auto s = search_function(b.sym, funcdecl.ident))
- {
- if (auto f2 = s.isFuncDeclaration())
- {
- f2 = f2.overloadExactMatch(funcdecl.type);
- if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
- .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
- }
- }
- }
- }
-
- if (funcdecl.isOverride)
- {
- if (funcdecl.storage_class & STC.disable)
- deprecation(funcdecl.loc,
- "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
- funcdecl.toPrettyChars);
+ // Supplemental error for parameter scope differences
+ auto tf1 = cast(TypeFunction)funcdecl.type;
+ auto tf2 = cast(TypeFunction)fd.type;
- if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
- deprecation(funcdecl.loc,
- "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
- funcdecl.toPrettyChars);
- }
+ if (tf1 && tf2)
+ {
+ auto params1 = tf1.parameterList;
+ auto params2 = tf2.parameterList;
- }
- else if (funcdecl.isOverride() && !parent.isTemplateInstance())
- .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
+ if (params1.length == params2.length)
+ {
+ bool hasScopeDifference = false;
- if (auto ti = parent.isTemplateInstance)
- {
- objc.setSelector(funcdecl, sc);
- objc.setAsOptional(funcdecl, sc);
- }
+ for (size_t i = 0; i < params1.length; i++)
+ {
+ auto p1 = params1[i];
+ auto p2 = params2[i];
- objc.validateSelector(funcdecl);
- objc.validateOptional(funcdecl);
- // Reflect this.type to f because it could be changed by findVtblIndex
- f = funcdecl.type.toTypeFunction();
+ if ((p1.storageClass & STC.scope_) == (p2.storageClass & STC.scope_))
+ continue;
-Ldone:
- if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
- .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
+ if (!(p2.storageClass & STC.scope_))
+ continue;
- /* Do not allow template instances to add virtual functions
- * to a class.
- */
- if (funcdecl.isVirtual())
- {
- if (auto ti = parent.isTemplateInstance())
- {
- // Take care of nested templates
- while (1)
- {
- TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
- if (!ti2)
- break;
- ti = ti2;
+ if (!hasScopeDifference)
+ {
+ // Intended signature
+ errorSupplemental(funcdecl.loc, "Did you intend to override:");
+ errorSupplemental(funcdecl.loc, "`%s`", buf1.peekChars());
+ hasScopeDifference = true;
+ }
+ errorSupplemental(funcdecl.loc, "Parameter %d is missing `scope`",
+ cast(int)(i + 1));
+ }
+ }
+ }
+ }
}
-
- // If it's a member template
- if (ClassDeclaration cd = ti.tempdecl.isClassMember())
+ else
{
- .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
+ error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
+ funcdeclToChars, s.kind, s.toPrettyChars());
+ errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
}
}
+ else
+ .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
}
- funcdecl.checkMain(); // Check main() parameters and return type
+L2:
+ objc.setSelector(funcdecl, sc);
+ objc.checkLinkage(funcdecl);
+ objc.addToClassMethodList(funcdecl, cd);
+ objc.setAsOptional(funcdecl, sc);
- /* Purity and safety can be inferred for some functions by examining
- * the function body.
+ /* Go through all the interface bases.
+ * Disallow overriding any final functions in the interface(s).
*/
- if (funcdecl.canInferAttributes(sc))
- funcdecl.initInferAttributes();
-
- funcdecl.semanticRun = PASS.semanticdone;
-
- /* Save scope for possible later use (if we need the
- * function internals)
- */
- funcdecl._scope = sc.copy();
- funcdecl._scope.setNoFree();
-
- __gshared bool printedMain = false; // semantic might run more than once
- if (global.params.v.verbose && !printedMain)
+ foreach (b; cd.interfaces)
{
- const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
- Module mod = sc._module;
-
- if (type && mod)
+ if (b.sym)
{
- printedMain = true;
- auto name = mod.srcfile.toChars();
- auto path = FileName.searchPath(global.importPaths, name, true);
- message("entry %-10s\t%s", type, path ? path : name);
+ if (auto s = search_function(b.sym, funcdecl.ident))
+ {
+ if (auto f2 = s.isFuncDeclaration())
+ {
+ f2 = f2.overloadExactMatch(funcdecl.type);
+ if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
+ .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
+ }
+ }
}
}
- if (funcdecl.fbody && sc._module.isRoot() &&
- (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
- global.hasMainFunction = true;
-
- if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
+ if (funcdecl.isOverride)
{
- // check if `_d_cmain` is defined
- bool cmainTemplateExists()
- {
- Dsymbol pscopesym;
- auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym);
- if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object))
- if (moduleSymbol.search(funcdecl.loc, Id.CMain))
- return true;
-
- return false;
- }
+ if (funcdecl.storage_class & STC.disable)
+ deprecation(funcdecl.loc,
+ "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
+ funcdecl.toPrettyChars);
- // Only mixin `_d_cmain` if it is defined
- if (cmainTemplateExists())
- {
- // add `mixin _d_cmain!();` to the declaring module
- auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain);
- auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null);
- sc._module.members.push(tm);
- }
+ if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
+ deprecation(funcdecl.loc,
+ "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
+ funcdecl.toPrettyChars);
}
+ return 0;
+}
- assert(funcdecl.type.ty != Terror || funcdecl.errors);
+private TypeFunction getFunctionType(FuncDeclaration fd)
+{
+ if (auto tf = fd.type.isTypeFunction())
+ return tf;
- // semantic for parameters' UDAs
- foreach (i, param; f.parameterList)
+ if (!fd.type.isTypeError())
{
- if (param && param.userAttribDecl)
- param.userAttribDecl.dsymbolSemantic(sc);
+ .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
+ fd.type = Type.terror;
}
+ fd.errors = true;
+ return null;
}
/*****************************************
@@ -1657,13 +1763,17 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s,
if (!od && !td.overnext)
{
.error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
- td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+ td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+
+ checkNamedArgErrorAndReport(td, argumentList, loc);
}
else
{
.error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
- td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
- tiargsBuf.peekChars(), fargsBuf.peekChars());
+ td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
+ tiargsBuf.peekChars(), fargsBuf.peekChars());
+
+ checkNamedArgErrorAndReport(td, argumentList, loc);
}
@@ -1683,7 +1793,9 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s,
if (od)
{
.error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`",
- od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+ od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+
+ checkNamedArgErrorAndReportOverload(od, argumentList, loc);
if (!global.gag || global.params.v.showGaggedErrors)
printCandidates(loc, od, sc.isDeprecated());
return null;
@@ -1713,8 +1825,14 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s,
OutBuffer buf;
buf.argExpTypesToCBuffer(fargs);
if (fd.isCtorDeclaration())
- .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
- fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+ {
+ if (tthis.mod & MODFlags.immutable_)
+ .error(loc, "none of the overloads of `%s` can construct an immutable object with argument types `(%s)`. Expected `immutable(%s)`",
+ fd.toChars(), buf.peekChars(), buf.peekChars());
+ else
+ .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
+ fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+ }
else
.error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`",
fd.toChars(), thisBuf.peekChars(), buf.peekChars());
@@ -1782,10 +1900,15 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s,
functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
if (mErr.last > MATCH.nomatch && mErr.lastf)
{
- errorSupplemental(loc, "%s `%s` hides base class function `%s`",
- fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
- errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
- fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
+ errorSupplemental(loc, "Note: %s `%s` hides base class %s `%s`",
+ fd.kind, fd.toPrettyChars(),
+ mErr.lastf.kind, mErr.lastf.toPrettyChars());
+
+ if (!fd.isCtorDeclaration)
+ {
+ errorSupplemental(loc, "Add `alias %s = %s;` to `%s`'s body to merge the overload sets",
+ fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
+ }
return null;
}
}
@@ -1803,6 +1926,62 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s,
return null;
}
+/********************************************************
+ * Check for named argument errors in template declarations and report them.
+ * Params:
+ * td = template declaration to check
+ * argumentList = arguments to check
+ * loc = location for error reporting
+ */
+private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc)
+{
+ if (!argumentList.hasArgNames())
+ return;
+
+ auto tf = td.onemember ? td.onemember.isFuncDeclaration() : null;
+ if (tf && tf.type && tf.type.ty == Tfunction)
+ {
+ OutBuffer buf;
+ auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf);
+ if (!resolvedArgs && buf.length)
+ .errorSupplemental(loc, "%s", buf.peekChars());
+ }
+}
+
+/******************************************
+ * Check for named argument errors in overload sets and report them.
+ * Params:
+ * od = overload declaration to check
+ * argumentList = arguments to check
+ * loc = location for error report
+ */
+private void checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argumentList, Loc loc)
+{
+ if (!argumentList.hasArgNames())
+ return;
+
+ FuncDeclaration tf = null;
+ overloadApply(od, (Dsymbol s) {
+ if (!tf)
+ {
+ if (auto fd = s.isFuncDeclaration())
+ tf = fd;
+ else if (auto td = s.isTemplateDeclaration())
+ if (td.onemember)
+ tf = td.onemember.isFuncDeclaration();
+ }
+ return 0;
+ });
+
+ if (tf && tf.type && tf.type.ty == Tfunction)
+ {
+ OutBuffer buf;
+ auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf);
+ if (!resolvedArgs && buf.length)
+ .errorSupplemental(loc, "%s", buf.peekChars());
+ }
+}
+
/*******************************************
* Prints template and function overload candidates as supplemental errors.
* Params:
@@ -2050,16 +2229,17 @@ int overrides(FuncDeclaration fd1, FuncDeclaration fd2)
* Params:
* f = first function
* g = second function
- * names = names of parameters
+ * names = argument Labels of parameters(name and location of the name)
* Returns:
* match 'this' is at least as specialized as g
* 0 g is more specialized than 'this'
*/
-MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
+MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, ArgumentLabels* names)
{
enum LOG_LEASTAS = 0;
static if (LOG_LEASTAS)
{
+ Identifiers *names = extractNames(names);
import core.stdc.stdio : printf;
printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null");
printf("%s, %s\n", f.type.toChars(), g.type.toChars());
@@ -3566,3 +3746,99 @@ extern (D) int overloadApply(Dsymbol fstart, scope int delegate(Dsymbol) dg, Sco
}
return overloadApplyRecurse(fstart, dg, sc);
}
+
+Dsymbol isUnique(OverDeclaration od)
+{
+ Dsymbol result = null;
+ overloadApply(od.aliassym, (Dsymbol s)
+ {
+ if (result)
+ {
+ result = null;
+ return 1; // ambiguous, done
+ }
+ else
+ {
+ result = s;
+ return 0;
+ }
+ });
+ return result;
+}
+
+/************************************
+* Check to see if this variable is actually in an enclosing function
+* rather than the current one.
+* Update nestedrefs[], closureVars[] and outerVars[].
+* Returns: true if error occurs.
+*/
+extern (D) bool checkNestedReference(VarDeclaration vd, Scope* sc, Loc loc)
+{
+ //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
+ if (sc.intypeof == 1 || sc.ctfe)
+ return false;
+ if (!vd.parent || vd.parent == sc.parent)
+ return false;
+ if (vd.isDataseg() || (vd.storage_class & STC.manifest))
+ return false;
+
+ // The current function
+ FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
+ if (!fdthis)
+ return false; // out of function scope
+
+ Dsymbol p = vd.toParent2();
+
+ // Function literals from fdthis to p must be delegates
+ ensureStaticLinkTo(fdthis, p);
+
+ // The function that this variable is in
+ FuncDeclaration fdv = p.isFuncDeclaration();
+ if (!fdv || fdv == fdthis)
+ return false;
+
+ // Add fdthis to nestedrefs[] if not already there
+ if (!vd.nestedrefs.contains(fdthis))
+ vd.nestedrefs.push(fdthis);
+
+ //printf("\tfdv = %s\n", fdv.toChars());
+ //printf("\tfdthis = %s\n", fdthis.toChars());
+ if (loc.isValid())
+ {
+ if (fdthis.getLevelAndCheck(loc, sc, fdv, vd) == fdthis.LevelError)
+ return true;
+ }
+
+ // Add this VarDeclaration to fdv.closureVars[] if not already there
+ if (!sc.intypeof && !sc.traitsCompiles &&
+ // https://issues.dlang.org/show_bug.cgi?id=17605
+ (fdv.skipCodegen || !fdthis.skipCodegen))
+ {
+ if (!fdv.closureVars.contains(vd))
+ fdv.closureVars.push(vd);
+ }
+
+ if (!fdthis.outerVars.contains(vd))
+ fdthis.outerVars.push(vd);
+
+ //printf("fdthis is %s\n", fdthis.toChars());
+ //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
+ // __dollar creates problems because it isn't a real variable
+ // https://issues.dlang.org/show_bug.cgi?id=3326
+ if (vd.ident == Id.dollar)
+ {
+ .error(loc, "cannnot use `$` inside a function literal");
+ return true;
+ }
+ if (vd.ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
+ {
+ ExpInitializer ez = vd._init.isExpInitializer();
+ assert(ez);
+ Expression e = ez.exp;
+ if (e.op == EXP.construct || e.op == EXP.blit)
+ e = (cast(AssignExp)e).e2;
+ return lambdaCheckForNestedRef(e, sc);
+ }
+
+ return false;
+}
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 61ff273c6b79..0f8c8c67b927 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -2724,6 +2724,12 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
void visitComma(CommaExp e)
{
+ if (e.originalExp !is null)
+ {
+ e.originalExp.expressionPrettyPrint(buf, hgs);
+ return;
+ }
+
// CommaExp is generated by the compiler so it shouldn't
// appear in error messages or header files.
// For now, this treats the case where the compiler
@@ -3695,9 +3701,9 @@ private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState h
* buf = buffer to write to
* hgs = context
* basis = replace `null`s in argument list with this expression (for sparse array literals)
- * names = if non-null, use these as the names for the arguments
+ * names = if non-null, use these as the argument Labels for the arguments
*/
-private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, Identifiers* names = null)
+private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, ArgumentLabels* names = null)
{
if (!expressions || !expressions.length)
return;
@@ -3708,9 +3714,9 @@ private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGe
if (i)
buf.writestring(", ");
- if (names && i < names.length && (*names)[i])
+ if (names && i < names.length && (*names)[i].name)
{
- buf.writestring((*names)[i].toString());
+ buf.writestring((*names)[i].name.toString());
buf.writestring(": ");
}
if (!el)
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 3d6e6ab5b511..4d9a758bb471 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -69,7 +69,7 @@ public Statement gccAsmSemantic(GccAsmStatement s, Scope* sc)
s.insn = semanticString(sc, s.insn, "asm instruction template");
if (s.labels && s.outputargs)
- error(s.loc, "extended asm statements with labels cannot have output constraints");
+ p.eSink.error(s.loc, "extended asm statements with labels cannot have output constraints");
// Analyse all input and output operands.
if (s.args)
@@ -143,6 +143,35 @@ public void gccAsmSemantic(CAsmDeclaration ad, Scope* sc)
private:
+/***********************************
+ * Parse an expression that evaluates to a string.
+ * Grammar:
+ * | AsmStringExpr:
+ * | StringLiteral
+ * | ( AssignExpression )
+ * Params:
+ * p = parser state
+ * Returns:
+ * the parsed string expression
+ */
+Expression parseAsmString(Parser)(Parser p)
+{
+ if (p.token.value == TOK.leftParenthesis)
+ {
+ p.nextToken();
+ Expression insn = p.parseAssignExp();
+ p.check(TOK.rightParenthesis);
+ return insn;
+ }
+ else if (p.token.value != TOK.string_)
+ {
+ p.eSink.error(p.token.loc, "expected string literal or expression in parentheses");
+ return ErrorExp.get();
+ }
+
+ return p.parsePrimaryExp();
+}
+
/***********************************
* Parse list of extended asm input or output operands.
* Grammar:
@@ -202,7 +231,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
if (p.token.value != TOK.leftParenthesis)
{
arg = p.parseAssignExp();
- error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
+ p.eSink.error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
}
else
{
@@ -352,13 +381,13 @@ Lerror:
* | GotoAsmInstruction
* |
* | BasicAsmInstruction:
- * | AssignExpression
+ * | AsmStringExpr
* |
* | ExtAsmInstruction:
- * | AssignExpression : Operands(opt) : Operands(opt) : Clobbers(opt)
+ * | AsmStringExpr : Operands(opt) : Operands(opt) : Clobbers(opt)
* |
* | GotoAsmInstruction:
- * | AssignExpression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
+ * | AsmStringExpr : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
* Params:
* p = parser state
* s = asm statement to parse
@@ -367,7 +396,10 @@ Lerror:
*/
GccAsmStatement parseGccAsm(Parser)(Parser p, GccAsmStatement s)
{
- s.insn = p.parseAssignExp();
+ s.insn = p.parseAsmString();
+ if (s.insn.isErrorExp())
+ return s;
+
if (p.token.value == TOK.semicolon || p.token.value == TOK.endOfFile)
goto Ldone;
@@ -519,11 +551,11 @@ unittest
} },
// Any CTFE-able string allowed as instruction template.
- q{ asm { generateAsm();
+ q{ asm { (generateAsm);
} },
// Likewise mixins, permissible so long as the result is a string.
- q{ asm { mixin(`"repne"`, `~ "scasb"`);
+ q{ asm { (mixin(`"repne"`, `~ "scasb"`));
} },
// :: token tests
@@ -557,6 +589,11 @@ unittest
// https://issues.dlang.org/show_bug.cgi?id=20593
q{ asm { "instruction" : : "operand" 123; } },
+
+ // https://github.com/dlang/dmd/issues/21298
+ q{ asm { 1; } },
+ q{ asm { int; } },
+ q{ asm { : "=r" (i); } },
];
foreach (test; passAsmTests)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index e1c22f2f04ca..2d10e6f991af 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -324,7 +324,6 @@ immutable Msgtable[] msgtable =
{ "__switch_error"},
{ "__ArrayCast"},
{ "_d_HookTraceImpl" },
- { "_d_arraysetlengthTImpl"},
{ "_d_arraysetlengthT"},
{ "_d_arraysetlengthTTrace"},
{ "_d_arrayappendT" },
diff --git a/gcc/d/dmd/imphint.d b/gcc/d/dmd/imphint.d
index 382a0f378633..e22bcc8b123f 100644
--- a/gcc/d/dmd/imphint.d
+++ b/gcc/d/dmd/imphint.d
@@ -26,8 +26,15 @@ const(char)[] importHint(const(char)[] s) @safe
return *entry;
return null;
}
+const(char)[] cIncludeHint(const(char)[] s) @safe
+{
+ if (auto entry = s in cHints)
+ return *entry;
+ return null;
+}
private immutable string[string] hints;
+private immutable string[string] cHints;
shared static this()
{
@@ -83,6 +90,23 @@ shared static this()
"InterpolationHeader": "core.interpolation",
"InterpolationFooter": "core.interpolation",
];
+ cHints = [
+ "NULL": "<stddef.h>",
+ "calloc": "<stdlib.h>",
+ "fopen": "<stdio.h>",
+ "fprintf": "<stdio.h>",
+ "free": "<stdlib.h>",
+ "malloc": "<stdlib.h>",
+ "memcpy": "<string.h>",
+ "memmove": "<string.h>",
+ "memset": "<string.h>",
+ "printf": "<stdio.h>",
+ "ptrdiff_t": "<stddef.h>",
+ "size_t": "<stddef.h>",
+ "stderr": "<stdio.h>",
+ "stdin": "<stdio.h>",
+ "stdout": "<stdio.h>",
+ ];
}
unittest
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 2f88a21c049f..059de62b1f9c 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -17,16 +17,22 @@ import core.stdc.stdio;
import dmd.astenums;
import dmd.dcast;
+import dmd.denum;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem;
+import dmd.dinterpret : ctfeInterpret;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.identifier;
+import dmd.id : Id;
import dmd.init;
+import dmd.intrange : IntRange;
import dmd.mtype;
+import dmd.optimize : optimize;
+import dmd.rootobject : DYNCAST;
import dmd.tokens;
import dmd.typesem;
@@ -120,6 +126,12 @@ Expression fieldLookup(Expression e, Scope* sc, Identifier id, bool arrow)
e = e.expressionSemantic(sc);
if (e.isErrorExp())
return e;
+ if (arrow)
+ {
+ e = arrayFuncConv(e, sc);
+ if (e.isErrorExp())
+ return e;
+ }
auto t = e.type;
if (t.isTypePointer())
@@ -532,11 +544,17 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
}
}
+ // Don't let macros shadow real symbols
+ if (auto td = s.isTemplateDeclaration())
+ {
+ if (td.isCmacro) return s2;
+ }
+
auto vd = s.isVarDeclaration(); // new declaration
auto vd2 = s2.isVarDeclaration(); // existing declaration
if (vd && vd.isCmacro())
- return vd2;
+ return s2;
assert(!(vd2 && vd2.isCmacro()));
@@ -638,3 +656,115 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
return collision();
}
+
+/*********************************
+ * ImportC-specific semantic analysis on enum declaration `ed`
+ */
+void cEnumSemantic(Scope* sc, EnumDeclaration ed)
+{
+ // C11 6.7.2.2
+ Type commonType = ed.memtype;
+ if (!commonType)
+ commonType = Type.tint32;
+ ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
+
+ // C11 6.7.2.2-2 value must be representable as an int.
+ // The sizemask represents all values that int will fit into,
+ // from 0..uint.max. We want to cover int.min..uint.max.
+ IntRange ir = IntRange.fromType(commonType);
+
+ void emSemantic(EnumMember em, ref ulong nextValue)
+ {
+ static void errorReturn(EnumMember em)
+ {
+ em.value = ErrorExp.get();
+ em.errors = true;
+ em.semanticRun = PASS.semanticdone;
+ }
+
+ em.semanticRun = PASS.semantic;
+ em.type = commonType;
+ em._linkage = LINK.c;
+ em.storage_class |= STC.manifest;
+ if (em.value)
+ {
+ Expression e = em.value;
+ assert(e.dyncast() == DYNCAST.expression);
+
+ /* To merge the type of e with commonType, add 0 of type commonType
+ */
+ if (!ed.memtype)
+ e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
+
+ e = e.expressionSemantic(sc);
+ e = resolveProperties(sc, e);
+ e = e.integralPromotions(sc);
+ e = e.ctfeInterpret();
+ if (e.op == EXP.error)
+ return errorReturn(em);
+ auto ie = e.isIntegerExp();
+ if (!ie)
+ {
+ // C11 6.7.2.2-2
+ .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
+ return errorReturn(em);
+ }
+ if (ed.memtype && !ir.contains(getIntRange(ie)))
+ {
+ // C11 6.7.2.2-2
+ .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
+ return errorReturn(em);
+ }
+ nextValue = ie.toInteger();
+ if (!ed.memtype)
+ commonType = e.type;
+ em.value = new IntegerExp(em.loc, nextValue, commonType);
+ }
+ else
+ {
+ // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
+ bool first = (em == (*em.ed.members)[0]);
+ if (!first)
+ {
+ Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
+ if (nextValue == max.toInteger())
+ {
+ .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
+ return errorReturn(em);
+ }
+ nextValue += 1;
+ }
+ em.value = new IntegerExp(em.loc, nextValue, commonType);
+ }
+ em.type = commonType;
+ em.semanticRun = PASS.semanticdone;
+ }
+
+ ed.members.foreachDsymbol( (s)
+ {
+ if (EnumMember em = s.isEnumMember())
+ emSemantic(em, nextValue);
+ });
+
+ if (!ed.memtype)
+ {
+ // cast all members to commonType
+ ed.members.foreachDsymbol( (s)
+ {
+ if (EnumMember em = s.isEnumMember())
+ {
+ em.type = commonType;
+ // optimize out the cast so that other parts of the compiler can
+ // assume that an integral enum's members are `IntegerExp`s.
+ // https://issues.dlang.org/show_bug.cgi?id=24504
+ em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
+ }
+ });
+ }
+
+ ed.memtype = commonType;
+ // Set semantic2done to mark C enums as fully processed
+ // Prevents issues with final switch statements that reference C enums
+ ed.semanticRun = PASS.semantic2done;
+ return;
+}
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 1ebccf77ee32..7247d7479746 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -153,7 +153,10 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
// that is not disabled.
if (sd.hasRegularCtor(true))
{
- error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
+ error(i.loc, "Cannot use %s initializer syntax for %s `%s` because it has a constructor",
+ sd.kind(), sd.kind(), sd.toChars());
+ errorSupplemental(i.loc, "Use `%s( arguments )` instead of `{ initializers }`",
+ sd.toChars());
return err();
}
sd.size(i.loc);
@@ -171,7 +174,8 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
return ex;
}
- auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc);
+ auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field.length, (size_t j) => i.field[j], &getExp, (size_t j) => i.value[j].loc, (size_t j) => i.value[j].loc);
+ //Keeping both the getArgLoc and getNameLoc same as i.field doesn't have a .loc value here.
if (!elements)
return err();
@@ -240,6 +244,9 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
goto default;
break;
+ case Terror:
+ return err();
+
default:
error(i.loc, "cannot use array to initialize `%s`", t.toChars());
return err();
@@ -394,7 +401,10 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
if (needInterpret)
i.exp = i.exp.ctfeInterpret();
if (i.exp.op == EXP.voidExpression)
- error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
+ {
+ error(i.loc, "variables cannot be initialized with an expression of type `void`");
+ errorSupplemental(i.loc, "only `= void;` is allowed, which prevents default initialization");
+ }
}
else
{
@@ -755,9 +765,13 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
// C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
assert(0); // should have been detected by parser
}
+ auto bt = tsa.nextOf().toBasetype();
- auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
-
+ if (auto tnss = bt.isTypeStruct())
+ {
+ return subStruct(tnss, index);
+ }
+ auto tnsa = bt.isTypeSArray();
auto ai = new ArrayInitializer(ci.loc);
ai.isCarray = true;
@@ -1505,15 +1519,18 @@ Params:
t = type of struct (potentially including qualifiers such as `const` or `immutable`)
sc = scope of the expression initializing the struct
iloc = location of expression initializing the struct
- names = identifiers passed in argument list, `null` entries for positional arguments
- getExp = function that, given an index into `names` and destination type, returns the initializing expression
- getLoc = function that, given an index into `names`, returns a location for error messages
+ argCount = count of argumnet present
+ getExp = function that, given an index into `argNames` and destination type, returns the initializing expression
+ getArgName = function that, given an index into `argNames`, returns the name of argument for error messages
+ getArgLoc = function that, given an index into `argNames`, returns a location of argument for error messages
+ getNameLoc = function that, given an index into `argNames`, returns a location of that `name` for error messages
Returns: list of expressions ordered to the struct's fields, or `null` on error
*/
Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc,
- Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp,
- scope Loc delegate(size_t i) getLoc
+ Loc iloc, size_t argCount, scope Identifier delegate(size_t i) getArgName, scope Expression delegate(size_t i, Type fieldType) getExp,
+ scope Loc delegate(size_t i) getArgLoc,
+ scope Loc delegate(size_t i) getNameLoc
)
{
//expandTuples for non-identity arguments?
@@ -1527,9 +1544,11 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope*
// TODO: this part is slightly different from StructLiteralExp::semantic.
bool errors = false;
size_t fieldi = 0;
- foreach (j, id; names)
+ foreach (j; 0 .. argCount)
{
- const argLoc = getLoc(j);
+ const argLoc = getArgLoc(j);
+ const nameLoc = getNameLoc(j);
+ Identifier id = getArgName(j);
if (id)
{
// Determine `fieldi` that `id` matches
@@ -1538,9 +1557,9 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope*
{
s = sd.search_correct(id);
if (s)
- error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
+ error(nameLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
else
- error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
+ error(nameLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
return null;
}
s.checkDeprecated(iloc, sc);
diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d
index 393ffb8a92d4..daff06f3d2c6 100644
--- a/gcc/d/dmd/location.d
+++ b/gcc/d/dmd/location.d
@@ -48,6 +48,15 @@ struct Loc
nothrow:
+ /// Reset global (Base)Loc tables, invalidating every existing `Loc` out there
+ /// and giving room to create new `Loc`s
+ static void _init()
+ {
+ locIndex = 1;
+ locFileTable = null;
+ lastFileTableIndex = 0;
+ }
+
/*******************************
* Configure how display is done
* Params:
@@ -282,9 +291,7 @@ private size_t fileTableIndex(uint index) nothrow @nogc
// To speed up linear find, we cache the last hit and compare that first,
// since usually we stay in the same file for some time when resolving source locations.
// If it's a different file now, either scan forwards / backwards
- __gshared size_t lastI = 0; // index of last found hit
-
- size_t i = lastI;
+ size_t i = lastFileTableIndex;
if (index >= locFileTable[i].startIndex)
{
while (i + 1 < locFileTable.length && index >= locFileTable[i+1].startIndex)
@@ -296,7 +303,7 @@ private size_t fileTableIndex(uint index) nothrow @nogc
i--;
}
- lastI = i;
+ lastFileTableIndex = i;
return i;
}
@@ -364,6 +371,11 @@ struct BaseLoc
uint[] lines; /// For each line, the file offset at which it starts. At index 0 there's always a 0 entry.
BaseLoc[] substitutions; /// Substitutions from #line / #file directives
+ /// Cache for the last line lookup
+ private size_t lastLineIndex = 0;
+ /// Cache for the last substitution lookup
+ private size_t lastSubstIndex = 0;
+
/// Register that a new line starts at `offset` bytes from the start of the source file
void newLine(uint offset)
{
@@ -419,8 +431,61 @@ struct BaseLoc
private size_t getSubstitutionIndex(uint offset) @nogc
{
+ if (substitutions.length <= 1)
+ return 0;
+
+ // Check if the offset falls within the current cached substitution or the next one
+ if (lastSubstIndex < substitutions.length - 1)
+ {
+ // For the current substitution's range
+ if (substitutions[lastSubstIndex].startIndex <= offset &&
+ (lastSubstIndex == substitutions.length - 1 ||
+ substitutions[lastSubstIndex + 1].startIndex > offset))
+ return lastSubstIndex;
+
+ // For the next substitution's range
+ if (lastSubstIndex + 1 < substitutions.length - 1 &&
+ substitutions[lastSubstIndex + 1].startIndex <= offset &&
+ substitutions[lastSubstIndex + 2].startIndex > offset)
+ {
+ lastSubstIndex++;
+ return lastSubstIndex;
+ }
+
+ // For the previous substitution's range
+ if (lastSubstIndex > 0 &&
+ substitutions[lastSubstIndex - 1].startIndex <= offset &&
+ substitutions[lastSubstIndex].startIndex > offset)
+ {
+ lastSubstIndex--;
+ return lastSubstIndex;
+ }
+ }
+ else if (lastSubstIndex == substitutions.length - 1 &&
+ substitutions[lastSubstIndex].startIndex <= offset)
+ {
+ // Last substitution case
+ return lastSubstIndex;
+ }
+
+ // Fall back to binary search, but start near
size_t lo = 0;
- size_t hi = substitutions.length + -1;
+ size_t hi = substitutions.length - 1;
+
+ // Adjust the range based on the offset relative to lastSubstIndex
+ if (offset < substitutions[lastSubstIndex].startIndex)
+ {
+ // Search backward
+ lo = 0;
+ hi = lastSubstIndex;
+ }
+ else
+ {
+ // Search forward
+ lo = lastSubstIndex;
+ hi = substitutions.length - 1;
+ }
+
size_t mid = 0;
while (lo <= hi)
{
@@ -428,7 +493,10 @@ struct BaseLoc
if (substitutions[mid].startIndex <= offset)
{
if (mid == substitutions.length - 1 || substitutions[mid + 1].startIndex > offset)
+ {
+ lastSubstIndex = mid; // Update cache
return mid;
+ }
lo = mid + 1;
}
@@ -441,10 +509,51 @@ struct BaseLoc
}
/// Binary search the index in `this.lines` corresponding to `offset`
+ /// lastLineIndex cache to avoid full binary search when possible
private size_t getLineIndex(uint offset) @nogc
{
+ if (lines.length <= 1)
+ return 0;
+
+ if (lastLineIndex < lines.length - 1)
+ {
+ if (lines[lastLineIndex] <= offset && offset < lines[lastLineIndex + 1])
+ return lastLineIndex;
+
+ if (lastLineIndex + 1 < lines.length - 1 &&
+ lines[lastLineIndex + 1] <= offset && offset < lines[lastLineIndex + 2])
+ {
+ lastLineIndex++;
+ return lastLineIndex;
+ }
+
+ if (lastLineIndex > 0 &&
+ lines[lastLineIndex - 1] <= offset && offset < lines[lastLineIndex])
+ {
+ lastLineIndex--;
+ return lastLineIndex;
+ }
+ }
+ else if (lastLineIndex == lines.length - 1 && lines[lastLineIndex] <= offset)
+ {
+ return lastLineIndex;
+ }
+
+ // Fall back to binary search
size_t lo = 0;
- size_t hi = lines.length + -1;
+ size_t hi = lines.length - 1;
+
+ if (offset < lines[lastLineIndex])
+ {
+ lo = 0;
+ hi = lastLineIndex;
+ }
+ else
+ {
+ lo = lastLineIndex;
+ hi = lines.length - 1;
+ }
+
size_t mid = 0;
while (lo <= hi)
{
@@ -452,7 +561,10 @@ struct BaseLoc
if (lines[mid] <= offset)
{
if (mid == lines.length - 1 || lines[mid + 1] > offset)
+ {
+ lastLineIndex = mid; // Update cache
return mid;
+ }
lo = mid + 1;
}
@@ -470,3 +582,6 @@ private __gshared uint locIndex = 1;
// Global mapping of Loc indices to source file offset/line/column, see `BaseLoc`
private __gshared BaseLoc*[] locFileTable;
+
+// Index of last found hit in locFileTable, for optimization
+private __gshared size_t lastFileTableIndex = 0;
diff --git a/gcc/d/dmd/mangle/package.d b/gcc/d/dmd/mangle/package.d
index 3ad2c7d57941..cc797614ed0b 100644
--- a/gcc/d/dmd/mangle/package.d
+++ b/gcc/d/dmd/mangle/package.d
@@ -1339,7 +1339,11 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d)
const par = d.toParent(); //toParent() skips over mixin templates
if (!par || par.isModule() || linkage == LINK.cpp ||
(linkage == LINK.c && d.isCsymbol() &&
- (d.isFuncDeclaration() ||
+ // https://github.com/dlang/dmd/issues/21241
+ // Static check is so C static functions get a unique mangle so the linker
+ // won't merge them if compiling all-at-once.
+ // Non-static functions can use their ident as their mangle.
+ ((d.isFuncDeclaration() && !d.isStatic()) ||
(d.isVarDeclaration() && d.isDataseg() && d.storage_class & STC.extern_))))
{
if (linkage != LINK.d && d.localNum)
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index a3e1a8ca858b..c9b57449658a 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -2234,7 +2234,7 @@ extern (C++) final class TypeSArray : TypeArray
auto elements = new Expressions(d);
foreach (ref e; *elements)
e = null;
- auto ae = new ArrayLiteralExp(Loc.initial, this, elementinit, elements);
+ auto ae = new ArrayLiteralExp(loc, this, elementinit, elements);
return ae;
}
@@ -2631,7 +2631,7 @@ extern (C++) final class TypeFunction : TypeNext
extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, OutBuffer* buf)
{
Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null;
- Identifier[] names = argumentList.names ? (*argumentList.names)[] : null;
+ ArgumentLabel[] names = argumentList.names ? (*argumentList.names)[] : null;
const nParams = parameterList.length(); // cached because O(n)
auto newArgs = new Expressions(nParams);
newArgs.zero();
@@ -2645,7 +2645,7 @@ extern (C++) final class TypeFunction : TypeNext
ci++;
continue;
}
- auto name = i < names.length ? names[i] : null;
+ auto name = i < names.length ? names[i].name : null;
if (name)
{
hasNamedArgs = true;
@@ -3761,6 +3761,7 @@ extern (C++) final class TypeTag : Type
Loc loc; /// location of declaration
TOK tok; /// TOK.struct_, TOK.union_, TOK.enum_
structalign_t packalign; /// alignment of struct/union fields
+ Expressions* alignExps; /// alignment of struct itself
Identifier id; /// tag name identifier
Type base; /// base type for enums otherwise null
Dsymbols* members; /// members of struct, null if none
@@ -3770,7 +3771,7 @@ extern (C++) final class TypeTag : Type
/// struct S { int a; } s1, *s2;
MOD mod; /// modifiers to apply after type is resolved (only MODFlags.const_ at the moment)
- extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Type base, Dsymbols* members) @safe
+ extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Expressions* alignExps, Type base, Dsymbols* members) @safe
{
//printf("TypeTag ctor %s %p\n", id ? id.toChars() : "null".ptr, this);
super(Ttag);
@@ -3778,6 +3779,7 @@ extern (C++) final class TypeTag : Type
this.tok = tok;
this.id = id;
this.packalign = packalign;
+ this.alignExps = alignExps;
this.base = base;
this.members = members;
this.mod = 0;
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 4d1938f4a723..4d303acf3c3c 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -554,6 +554,8 @@ public:
void isReturn(bool v);
bool isReturnScope() const;
void isReturnScope(bool v);
+ bool isRvalue() const;
+ void isRvalue(bool v);
bool isScopeQual() const;
void isScopeQual(bool v);
bool isReturnInferred() const;
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index f1494a409f6e..5e3c164acbb4 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -24,6 +24,7 @@ import dmd.dscope;
import dmd.dtemplate : isDsymbol;
import dmd.dsymbol : PASS;
import dmd.errors;
+import dmd.escape;
import dmd.expression;
import dmd.func;
import dmd.globals;
@@ -45,13 +46,15 @@ extern (C++) final class NOGCVisitor : StoppableVisitor
alias visit = typeof(super).visit;
public:
FuncDeclaration f;
+ Scope* sc;
bool checkOnly; // don't print errors
bool err;
bool nogcExceptions; // -preview=dip1008 enabled
- extern (D) this(FuncDeclaration f) scope @safe
+ extern (D) this(FuncDeclaration f, Scope* sc) scope @safe
{
this.f = f;
+ this.sc = sc;
}
void doCond(Expression exp)
@@ -86,6 +89,8 @@ public:
*/
private bool setGC(Expression e, const(char)* msg)
{
+ if (sc.debug_)
+ return false;
if (checkOnly)
{
err = true;
@@ -119,10 +124,17 @@ public:
override void visit(ArrayLiteralExp e)
{
- if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack)
+ if (e.type.toBasetype().isTypeSArray() || !e.elements || !e.elements.length || e.onstack)
return;
if (setGC(e, "this array literal"))
return;
+
+ if (checkArrayLiteralEscape(*sc, e, false))
+ {
+ err = true;
+ return;
+ }
+
f.printGCUsage(e.loc, "array literal may cause a GC allocation");
}
@@ -208,9 +220,10 @@ public:
}
}
-Expression checkGC(Scope* sc, Expression e)
+Expression checkGC(Expression e, Scope* sc)
{
- if (sc.ctfeBlock) // ignore GC in ctfe blocks
+ // printf("%s checkGC(%s)\n", e.loc.toChars, e.toChars);
+ if (e.gcPassDone || sc.ctfeBlock || sc.ctfe || sc.intypeof == 1 || !sc.func)
return e;
/* If betterC, allow GC to happen in non-CTFE code.
@@ -219,28 +232,20 @@ Expression checkGC(Scope* sc, Expression e)
*/
const betterC = !global.params.useGC;
FuncDeclaration f = sc.func;
- if (e && e.op != EXP.error && f && sc.intypeof != 1 &&
- (!sc.ctfe || betterC) &&
- (f.type.ty == Tfunction &&
- (cast(TypeFunction)f.type).isNogc || f.nogcInprocess || global.params.v.gc) &&
- !sc.debug_)
- {
- scope NOGCVisitor gcv = new NOGCVisitor(f);
- gcv.checkOnly = betterC;
- gcv.nogcExceptions = sc.previews.dip1008;
- walkPostorder(e, gcv);
- if (gcv.err)
- {
- if (betterC)
- {
- /* Allow ctfe to use the gc code, but don't let it into the runtime
- */
- f.skipCodegen = true;
- }
- else
- return ErrorExp.get();
- }
- }
+ scope NOGCVisitor gcv = new NOGCVisitor(f, sc);
+ gcv.checkOnly = betterC && (f.type.isTypeFunction().isNogc || f.nogcInprocess);
+ gcv.nogcExceptions = sc.previews.dip1008;
+ walkPostorder(e, gcv);
+ e.gcPassDone = true;
+
+ if (!gcv.err)
+ return e;
+
+ if (!betterC)
+ return ErrorExp.get();
+
+ // Allow ctfe to use the gc code, but don't let it into the runtime
+ f.skipCodegen = true;
return e;
}
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 0c93f0e7994a..b8116343d6fe 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/dmd/nspace.d
@@ -78,12 +78,6 @@ extern (C++) final class Nspace : ScopeDsymbol
return ns;
}
- override bool hasPointers()
- {
- //printf("Nspace::hasPointers() %s\n", toChars());
- return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
- }
-
override const(char)* kind() const
{
return "namespace";
diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index 7b4c302303da..782688b9de1c 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -21,7 +21,6 @@ class Nspace final : public ScopeDsymbol
public:
Expression *identExp;
Nspace *syntaxCopy(Dsymbol *s) override;
- bool hasPointers() override;
const char *kind() const override;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 66b8c6a4953c..b13f8c64584f 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -1072,7 +1072,8 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
// All negative integral powers are illegal.
if (e.e1.type.isIntegral() && (e.e2.op == EXP.int64) && cast(sinteger_t)e.e2.toInteger() < 0)
{
- error(e.loc, "cannot raise `%s` to a negative integer power. Did you mean `(cast(real)%s)^^%s` ?", e.e1.type.toBasetype().toChars(), e.e1.toChars(), e.e2.toChars());
+ error(e.loc, "cannot raise `%s` to a negative integer power.", e.e1.type.toBasetype().toChars());
+ errorSupplemental(e.loc, "did you mean `(cast(real)%s)^^%s` ?", e.e1.toChars(), e.e2.toChars());
return errorReturn();
}
// If e2 *could* have been an integer, make it one.
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index e68017c87e55..c57f1d3f7f74 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -28,6 +28,7 @@ import dmd.root.rmem;
import dmd.rootobject;
import dmd.root.string;
import dmd.tokens;
+import dmd.expression;
alias CompileEnv = dmd.lexer.CompileEnv;
@@ -1319,12 +1320,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// Allow identifier, template instantiation, or function call
// for `@Argument` (single UDA) form.
- AST.Expression exp = parsePrimaryExp();
+ AST.Expression exp;
+
+ {
+ const loc = token.loc;
+ Identifier id = token.ident;
+ nextToken();
+ if (token.value == TOK.not)
+ {
+ auto tempinst = new AST.TemplateInstance(loc, id, parseTemplateArguments());
+ exp = new AST.ScopeExp(loc, tempinst);
+ }
+ else
+ exp = new AST.IdentifierExp(loc, id);
+ }
+
if (token.value == TOK.leftParenthesis)
{
const loc = token.loc;
AST.Expressions* args = new AST.Expressions();
- AST.Identifiers* names = new AST.Identifiers();
+ AST.ArgumentLabels* names = new AST.ArgumentLabels();
parseNamedArguments(args, names);
exp = new AST.CallExp(loc, exp, args, names);
}
@@ -2758,7 +2773,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (len > 0)
{
docline = cast(char*)mem.xmalloc_noscan(len + 2);
- memcpy(docline, begPtr, len);
+ docline[0 .. len] = begPtr[0 .. len];
docline[len] = '\n'; // Terminate all lines by LF
docline[len + 1] = '\0';
}
@@ -4067,7 +4082,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
*/
if (isParameters(&peekt))
{
- error("function declaration without return type. (Note that constructors are always named `this`)");
+ error("function declaration without return type");
+ errorSupplemental("Note that constructors are always named `this`");
}
else
error("unexpected `(` in declarator");
@@ -7090,12 +7106,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.colonColon: // treat as two separate : tokens for iasmgcc
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
(*ptoklist).value = TOK.colon;
ptoklist = &(*ptoklist).next;
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
(*ptoklist).value = TOK.colon;
ptoklist = &(*ptoklist).next;
@@ -7105,7 +7121,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
default:
*ptoklist = allocateToken();
- memcpy(*ptoklist, &token, Token.sizeof);
+ **ptoklist = this.token;
ptoklist = &(*ptoklist).next;
*ptoklist = null;
nextToken();
@@ -8249,9 +8265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
const len2 = token.len;
len = len1 + len2;
auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof);
- memcpy(s2, s, len1 * char.sizeof);
- memcpy(s2 + len1, token.ustring, len2 * char.sizeof);
- s = s2;
+ s2[0 .. len1] = s[0 .. len1];
+ s2[len1 .. len1 + len2] = token.ustring[0 .. len2];
}
else
break;
@@ -8454,10 +8469,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
if (token.value == TOK.identifier && peekNext() == TOK.leftParenthesis)
{
- error(loc, "unexpected `(` after `%s`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression", token.toChars());
+ error(loc, "unexpected `(` after `%s`, inside `is` expression", token.toChars());
+ errorSupplemental("try enclosing the contents of `is` with a `typeof` expression");
nextToken();
Token* tempTok = peekPastParen(&token);
- memcpy(&token, tempTok, Token.sizeof);
+ token = *tempTok;
goto Lerr;
}
targ = parseType(&ident);
@@ -9006,7 +9022,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.leftParenthesis:
AST.Expressions* args = new AST.Expressions();
- AST.Identifiers* names = new AST.Identifiers();
+ AST.ArgumentLabels* names = new AST.ArgumentLabels();
parseNamedArguments(args, names);
e = new AST.CallExp(loc, e, args, names);
continue;
@@ -9053,11 +9069,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseMulExp()
{
- const loc = token.loc;
auto e = parseUnaryExp();
while (1)
{
+ const loc = token.loc;
switch (token.value)
{
case TOK.mul:
@@ -9088,11 +9104,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseAddExp()
{
- const loc = token.loc;
auto e = parseMulExp();
while (1)
{
+ const loc = token.loc;
switch (token.value)
{
case TOK.add:
@@ -9123,11 +9139,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseShiftExp()
{
- const loc = token.loc;
auto e = parseAddExp();
while (1)
{
+ const loc = token.loc;
switch (token.value)
{
case TOK.leftShift:
@@ -9158,10 +9174,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseCmpExp()
{
- const loc = token.loc;
-
auto e = parseShiftExp();
EXP op = EXP.reserved;
+ const loc = token.loc;
switch (token.value)
{
@@ -9223,28 +9238,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseAndExp()
{
- Loc loc = token.loc;
auto e = parseCmpExp();
while (token.value == TOK.and)
{
checkParens(TOK.and, e);
+ const loc = token.loc;
nextToken();
auto e2 = parseCmpExp();
checkParens(TOK.and, e2);
e = new AST.AndExp(loc, e, e2);
- loc = token.loc;
}
return e;
}
private AST.Expression parseXorExp()
{
- const loc = token.loc;
-
auto e = parseAndExp();
while (token.value == TOK.xor)
{
checkParens(TOK.xor, e);
+ const loc = token.loc;
nextToken();
auto e2 = parseAndExp();
checkParens(TOK.xor, e2);
@@ -9255,12 +9268,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseOrExp()
{
- const loc = token.loc;
-
auto e = parseXorExp();
while (token.value == TOK.or)
{
checkParens(TOK.or, e);
+ const loc = token.loc;
nextToken();
auto e2 = parseXorExp();
checkParens(TOK.or, e2);
@@ -9271,11 +9283,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseAndAndExp()
{
- const loc = token.loc;
-
auto e = parseOrExp();
while (token.value == TOK.andAnd)
{
+ const loc = token.loc;
nextToken();
auto e2 = parseOrExp();
e = new AST.LogicalExp(loc, EXP.andAnd, e, e2);
@@ -9285,11 +9296,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseOrOrExp()
{
- const loc = token.loc;
-
auto e = parseAndAndExp();
while (token.value == TOK.orOr)
{
+ const loc = token.loc;
nextToken();
auto e2 = parseAndAndExp();
e = new AST.LogicalExp(loc, EXP.orOr, e, e2);
@@ -9299,11 +9309,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseCondExp()
{
- const loc = token.loc;
-
auto e = parseOrOrExp();
if (token.value == TOK.question)
{
+ const loc = token.loc;
nextToken();
auto e1 = parseExpression();
check(TOK.colon);
@@ -9452,7 +9461,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
* Collect argument list.
* Assume current token is ',', '$(LPAREN)' or '['.
*/
- private void parseNamedArguments(AST.Expressions* arguments, AST.Identifiers* names)
+ private void parseNamedArguments(AST.Expressions* arguments, AST.ArgumentLabels* names)
{
assert(arguments);
@@ -9470,14 +9479,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
check(TOK.identifier);
check(TOK.colon);
if (names)
- names.push(ident);
+ names.push(ArgumentLabel(ident, loc));
else
error(loc, "named arguments not allowed here");
}
else
{
if (names)
- names.push(null);
+ names.push(ArgumentLabel(null, Loc.init));
}
auto arg = parseAssignExp();
@@ -9518,7 +9527,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
AST.Expressions* arguments = null;
- AST.Identifiers* names = null;
+ AST.ArgumentLabels* names = null;
// An anonymous nested class starts with "class"
if (token.value == TOK.class_)
@@ -9527,7 +9536,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.leftParenthesis)
{
arguments = new AST.Expressions();
- names = new AST.Identifiers();
+ names = new AST.ArgumentLabels();
parseNamedArguments(arguments, names);
}
@@ -9572,7 +9581,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
else if (token.value == TOK.leftParenthesis && t.ty != Tsarray)
{
arguments = new AST.Expressions();
- names = new AST.Identifiers();
+ names = new AST.ArgumentLabels();
parseNamedArguments(arguments, names);
}
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 1c58e63936d7..26f0fa8a254f 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -287,7 +287,10 @@ private extern(C++) final class Semantic2Visitor : Visitor
}
if (hasInvalidEnumInitializer(ei.exp))
- .error(vd.loc, "%s `%s` : Unable to initialize enum with class or pointer to struct. Use static const variable instead.", vd.kind, vd.toPrettyChars);
+ {
+ .error(vd.loc, "%s `%s` : Unable to initialize enum with class or pointer to struct", vd.kind, vd.toPrettyChars);
+ .errorSupplemental(vd.loc, "use static const variable instead");
+ }
}
}
else if (vd._init && vd.isThreadlocal())
@@ -298,13 +301,20 @@ private extern(C++) final class Semantic2Visitor : Visitor
{
ExpInitializer ei = vd._init.isExpInitializer();
if (ei && ei.exp.op == EXP.classReference)
- .error(vd.loc, "%s `%s` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars);
+ {
+ .error(vd.loc, "%s `%s` is a thread-local class and cannot have a static initializer", vd.kind, vd.toPrettyChars);
+ .errorSupplemental(vd.loc, "use `static this()` to initialize instead");
+ }
}
else if (vd.type.ty == Tpointer && vd.type.nextOf().ty == Tstruct && vd.type.nextOf().isMutable() && !vd.type.nextOf().isShared())
{
ExpInitializer ei = vd._init.isExpInitializer();
if (ei && ei.exp.op == EXP.address && (cast(AddrExp)ei.exp).e1.op == EXP.structLiteral)
- .error(vd.loc, "%s `%s` is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars);
+ {
+ .error(vd.loc, "%s `%s` is a thread-local pointer to struct and cannot have a static initializer", vd.kind, vd.toPrettyChars);
+ .errorSupplemental(vd.loc, "use `static this()` to initialize instead");
+ }
+
}
}
vd.semanticRun = PASS.semantic2done;
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index a24af7bbbfcf..bafb2e7d8719 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -855,7 +855,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (tret.ty == Terror)
{
// https://issues.dlang.org/show_bug.cgi?id=13702
- exp = checkGC(sc2, exp);
+ exp = exp.checkGC(sc2);
continue;
}
@@ -977,7 +977,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
checkReturnEscape(*sc2, exp, false);
}
- exp = checkGC(sc2, exp);
+ exp = exp.checkGC(sc2);
if (funcdecl.vresult)
{
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 0c9b6becb700..523ed7b39781 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -219,7 +219,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
s.exp = ErrorExp.get();
s.exp = s.exp.optimize(WANTvalue);
- s.exp = checkGC(sc, s.exp);
+ s.exp = s.exp.checkGC(sc);
if (s.exp.op == EXP.error)
return setError();
result = s;
@@ -585,7 +585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(ds.condition))
ds.condition = ErrorExp.get();
ds.condition = ds.condition.optimize(WANTvalue);
- ds.condition = checkGC(sc, ds.condition);
+ ds.condition = ds.condition.checkGC(sc);
ds.condition = ds.condition.toBoolean(sc);
@@ -658,7 +658,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(fs.condition))
fs.condition = ErrorExp.get();
fs.condition = fs.condition.optimize(WANTvalue);
- fs.condition = checkGC(sc, fs.condition);
+ fs.condition = fs.condition.checkGC(sc);
fs.condition = fs.condition.toBoolean(sc);
}
@@ -677,7 +677,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(fs.increment))
fs.increment = ErrorExp.get();
fs.increment = fs.increment.optimize(WANTvalue);
- fs.increment = checkGC(sc, fs.increment);
+ fs.increment = fs.increment.checkGC(sc);
}
sc.sbreak = fs;
@@ -1709,7 +1709,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
// checkGC after optimizing the condition so that
// compile time constants are reduced.
- ifs.condition = checkGC(scd, ifs.condition);
+ ifs.condition = ifs.condition.checkGC(scd);
// Save 'root' of two branches (then and else) at the point where it forks
CtorFlow ctorflow_root = scd.ctorflow.clone();
@@ -1897,7 +1897,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(ss.condition))
ss.condition = ErrorExp.get();
ss.condition = ss.condition.optimize(WANTvalue);
- ss.condition = checkGC(sc, ss.condition);
+ ss.condition = ss.condition.checkGC(sc);
if (ss.condition.op == EXP.error)
conditionError = true;
@@ -1959,6 +1959,16 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
ed = ds.isEnumDeclaration(); // typedef'ed enum
if (!ed && te && ((ds = te.toDsymbol(sc)) !is null))
ed = ds.isEnumDeclaration();
+
+ // Circular references
+ // Check if enum semantic analysis is not yet complete
+ if (ed && ed.semanticRun < PASS.semantic2done)
+ {
+ error(ss.loc, "cannot use `final switch` on enum `%s` while it is being defined", ed.toChars());
+ sc.pop();
+ return setError();
+ }
+
if (ed && ss.cases.length < ed.members.length)
{
int missingMembers = 0;
@@ -2593,7 +2603,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (tbret && tbret.ty == Tvoid || convToVoid)
{
- if (!convToVoid)
+ if (!convToVoid && !texp.isTypeError())
{
error(rs.loc, "cannot return non-void from `void` function");
errors = true;
@@ -2626,7 +2636,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (e0)
{
e0 = e0.optimize(WANTvalue);
- e0 = checkGC(sc, e0);
+ e0 = e0.checkGC(sc);
}
}
@@ -3044,7 +3054,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
ss.exp = ss.exp.expressionSemantic(sc);
ss.exp = resolveProperties(sc, ss.exp);
ss.exp = ss.exp.optimize(WANTvalue);
- ss.exp = checkGC(sc, ss.exp);
+ ss.exp = ss.exp.checkGC(sc);
if (ss.exp.op == EXP.error)
{
if (ss._body)
@@ -3168,7 +3178,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
ws.exp = ws.exp.expressionSemantic(sc);
ws.exp = resolveProperties(sc, ws.exp);
ws.exp = ws.exp.optimize(WANTvalue);
- ws.exp = checkGC(sc, ws.exp);
+ ws.exp = ws.exp.checkGC(sc);
if (ws.exp.op == EXP.error)
return setError();
if (ws.exp.op == EXP.scope_)
@@ -3730,7 +3740,7 @@ public bool throwSemantic(Loc loc, ref Expression exp, Scope* sc)
exp = exp.expressionSemantic(sc);
exp = resolveProperties(sc, exp);
- exp = checkGC(sc, exp);
+ exp = exp.checkGC(sc);
if (exp.isErrorExp())
return false;
if (!exp.type.isNaked())
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 5576965ce4b2..bfc415148043 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -71,6 +71,7 @@ public:
d_bool isTrivialAliasSeq; // matches `template AliasSeq(T...) { alias AliasSeq = T; }
d_bool isTrivialAlias; // matches pattern `template Alias(T) { alias Alias = qualifiers(T); }`
d_bool deprecated_; // this template declaration is deprecated
+ d_bool isCmacro; // Whether this template is a translation of a C macro
Visibility visibility;
TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack
@@ -284,7 +285,6 @@ public:
TemplateMixin *syntaxCopy(Dsymbol *s) override;
const char *kind() const override;
- bool hasPointers() override;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d
index e5efce4a8bcc..a9cf867f1147 100644
--- a/gcc/d/dmd/templatesem.d
+++ b/gcc/d/dmd/templatesem.d
@@ -188,7 +188,7 @@ void templateDeclarationSemantic(Scope* sc, TemplateDeclaration tempdecl)
if (tempdecl.members)
{
Dsymbol s;
- if (Dsymbol.oneMembers(tempdecl.members, s, tempdecl.ident) && s)
+ if (oneMembers(tempdecl.members, s, tempdecl.ident) && s)
{
tempdecl.onemember = s;
s.parent = tempdecl;
@@ -948,7 +948,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
size_t nfargs2 = argumentList.length; // total number of arguments including applied defaultArgs
uint inoutMatch = 0; // for debugging only
Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null;
- Identifier[] fnames = argumentList.names ? (*argumentList.names)[] : null;
+ ArgumentLabel[] fnames = argumentList.names ? (*argumentList.names)[] : null;
for (size_t parami = 0; parami < nfparams; parami++)
{
@@ -958,16 +958,17 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
Type prmtype = fparam.type.addStorageClass(fparam.storageClass);
Expression farg;
- Identifier fname = argi < fnames.length ? fnames[argi] : null;
+ Identifier fname = argi < fnames.length ? fnames[argi].name : null;
bool foundName = false;
if (fparam.ident)
{
foreach (i; 0 .. fnames.length)
{
- if (fparam.ident == fnames[i])
+ if (fparam.ident == fnames[i].name)
{
argi = i;
foundName = true;
+ break; //Exits the loop after a match
}
}
}
@@ -1002,9 +1003,9 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
{
break;
}
- foreach(name; fnames)
+ foreach(argLabel; fnames)
{
- if (p.ident == name)
+ if (p.ident == argLabel.name)
break;
}
if (!reliesOnTemplateParameters(p.type, (*td.parameters)[inferStart .. td.parameters.length]))
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 127a89d19842..8cce1732e87e 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -1847,7 +1847,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
const tf = sc2.func.type.isTypeFunction();
err |= tf.isNothrow && canThrow(ex, sc2.func, null);
}
- ex = checkGC(sc2, ex);
+ ex = ex.checkGC(sc2);
if (ex.op == EXP.error)
err = true;
}
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index d4c7a5865d25..ffbdfed6eb37 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -169,17 +169,28 @@ private void resolveHelper(TypeQualified mt, Loc loc, Scope* sc, Dsymbol s, Dsym
*/
const p = mt.mutableOf().unSharedOf().toChars();
auto id = Identifier.idPool(p[0 .. strlen(p)]);
- if (const n = importHint(id.toString()))
- error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr);
- else if (auto s2 = sc.search_correct(id))
- error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
- else if (const q = Scope.search_correct_C(id))
- error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
- else if ((id == Id.This && sc.getStructClassScope()) ||
- (id == Id._super && sc.getClassScope()))
- error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p);
- else
- error(loc, "undefined identifier `%s`", p);
+ if (!(sc && sc.inCfile))
+ {
+ if (const n = importHint(id.toString()))
+ error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr);
+ else if (auto s2 = sc.search_correct(id))
+ error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
+ else if (const q = Scope.search_correct_C(id))
+ error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
+ else if ((id == Id.This && sc.getStructClassScope()) ||
+ (id == Id._super && sc.getClassScope()))
+ error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p);
+ else
+ error(mt.loc, "undefined identifier `%s`", p);
+ }
+ else {
+ if (const n = cIncludeHint(id.toString()))
+ error(loc, "`%s` is not defined, perhaps `#include %.*s` ?", p, cast(int)n.length, n.ptr);
+ else if (auto s2 = sc.search_correct(id))
+ error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
+ else
+ error(loc, "undefined identifier `%s`", p);
+ }
pt = Type.terror;
return;
@@ -1934,7 +1945,19 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)
Expression e;
Type t;
Dsymbol s;
- mtype.index.resolve(loc, sc, e, t, s);
+ Loc indexLoc;
+
+ switch (mtype.index.ty)
+ {
+ case Tident: indexLoc = mtype.index.isTypeIdentifier().loc; break;
+ case Tinstance: indexLoc = mtype.index.isTypeInstance().loc; break;
+ case Ttypeof: indexLoc = mtype.index.isTypeTypeof().loc; break;
+ case Treturn: indexLoc = mtype.index.isTypeReturn().loc; break;
+ case Tmixin: indexLoc = mtype.index.isTypeMixin().loc; break;
+ default: indexLoc = mtype.loc;
+ }
+
+ mtype.index.resolve(indexLoc, sc, e, t, s);
// https://issues.dlang.org/show_bug.cgi?id=15478
if (s)
@@ -2737,7 +2760,11 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)
Expression e;
Dsymbol s;
//printf("TypeIdentifier::semantic(%s)\n", mtype.toChars());
- mtype.resolve(loc, sc, e, t, s);
+ if (mtype.loc != Loc.initial)
+ mtype.resolve(mtype.loc, sc, e, t, s);
+ else
+ mtype.resolve(loc, sc, e, t, s);
+
if (t)
{
//printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco);
@@ -3428,8 +3455,10 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla
}
Dsymbol s = null;
- if (mt.ty == Tstruct || mt.ty == Tclass || mt.ty == Tenum)
- s = mt.toDsymbol(null);
+ auto derefType = mt.isTypePointer() ? mt.nextOf() : mt;
+
+ if (derefType.isTypeStruct() || derefType.isTypeClass() || derefType.isTypeEnum())
+ s = derefType.toDsymbol(null);
if (s)
s = s.search_correct(ident);
if (s && !symbolIsVisible(scope_, s))
@@ -3439,18 +3468,21 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla
return ErrorExp.get();
if (s)
- error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars());
+ {
+ error(loc, "no property `%s` for type `%s`", ident.toErrMsg(), mt.toErrMsg());
+ errorSupplemental(s.loc, "did you mean `%s`?", ident == s.ident ? s.toPrettyChars() : s.toErrMsg());
+ }
else if (ident == Id.opCall && mt.ty == Tclass)
- error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars());
+ error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toErrMsg(), mt.toErrMsg(), mt.toPrettyChars());
else if (const n = importHint(ident.toString()))
- error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr);
+ error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toErrMsg(), mt.toErrMsg(), cast(int)n.length, n.ptr);
else
{
if (src)
{
error(loc, "no property `%s` for `%s` of type `%s`",
- ident.toChars(), src.toChars(), mt.toPrettyChars(true));
+ ident.toErrMsg(), src.toErrMsg(), mt.toPrettyChars(true));
auto s2 = scope_.search_correct(ident);
// UFCS
if (s2 && s2.isFuncDeclaration)
@@ -3458,30 +3490,17 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla
if (s2.ident == ident)
{
errorSupplemental(s2.loc, "cannot call %s `%s` with UFCS because it is not declared at module scope",
- s2.kind(), s2.toChars());
+ s2.kind(), s2.toErrMsg());
}
else
errorSupplemental(s2.loc, "did you mean %s `%s`?",
- s2.kind(), s2.toChars());
- }
- else if (src.type.ty == Tpointer)
- {
- // structPtr.field
- auto tn = (cast(TypeNext) src.type).nextOf();
- if (auto as = tn.isAggregate())
- {
- if (auto s3 = as.search_correct(ident))
- {
- errorSupplemental(s3.loc, "did you mean %s `%s`?",
- s3.kind(), s3.toChars());
- }
- }
+ s2.kind(), s2.toErrMsg());
}
}
else
- error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
+ error(loc, "no property `%s` for type `%s`", ident.toErrMsg(), mt.toPrettyChars(true));
- if (auto dsym = mt.toDsymbol(scope_))
+ if (auto dsym = derefType.toDsymbol(scope_))
{
if (auto sym = dsym.isAggregateDeclaration())
{
@@ -3507,7 +3526,7 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla
}
}
errorSupplemental(dsym.loc, "%s `%s` defined here",
- dsym.kind, dsym.toChars());
+ dsym.kind, dsym.toErrMsg());
}
}
@@ -6704,6 +6723,7 @@ STC parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarati
// Check escaping through `this`
if (tthis && tthis.isMutable())
{
+ import dmd.dsymbolsem : hasPointers;
foreach (VarDeclaration v; isAggregate(tthis).fields)
{
if (v.hasPointers())
@@ -6714,6 +6734,7 @@ STC parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarati
// Check escaping through nested context
if (outerVars && tf.isMutable())
{
+ import dmd.dsymbolsem : hasPointers;
foreach (VarDeclaration v; *outerVars)
{
if (v.hasPointers())
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index 026b12fb93e1..160d37846f29 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -908,7 +908,7 @@ public:
}
}
- if (cd->isAbstract ())
+ if (dmd::isAbstract (cd))
flags |= ClassFlags::isAbstract;
for (ClassDeclaration *bcd = cd; bcd; bcd = bcd->baseClass)
@@ -919,7 +919,7 @@ public:
for (size_t i = 0; i < bcd->members->length; i++)
{
Dsymbol *sm = (*bcd->members)[i];
- if (sm->hasPointers ())
+ if (dmd::hasPointers (sm))
goto Lhaspointers;
}
}
diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d
index 1593eb6acd34..e2f36b01c94a 100644
--- a/gcc/testsuite/gdc.dg/asm1.d
+++ b/gcc/testsuite/gdc.dg/asm1.d
@@ -11,7 +11,7 @@ void parse1()
void parse2()
{
- asm
+ asm
{
"" : : "g" (1 ? 2 : 3);
"" : : "g" (1 ? 2 : :) 3;
@@ -22,11 +22,7 @@ void parse2()
void parse3()
{
- asm { "" [; }
- // { dg-error "expression expected, not ';'" "" { target *-*-* } .-1 }
- // { dg-error "found 'End of File' when expecting ','" "" { target *-*-* } .-2 }
- // { dg-error "found 'End of File' when expecting ']'" "" { target *-*-* } .-3 }
- // { dg-error "found 'End of File' when expecting ';'" "" { target *-*-* } .-4 }
+ asm { "" [; } // { dg-error "found '\\\[' when expecting ':'" }
}
void parse4()
@@ -68,9 +64,9 @@ void semantic2()
void semantic3()
{
- asm
+ asm
{
- unknown; // { dg-error "undefined identifier 'unknown'" }
+ unknown; // { dg-error "expected string literal or expression in parentheses" }
}
}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
index f6aaf3b2a4ae..fb78ec76bca7 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
+++ b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
@@ -4,3 +4,16 @@ int squared(int a)
{
return a * a;
}
+
+/* test case for issue #21094 */
+typedef enum upng_error {
+ UPNG_EOK = 0, /* success (no error) */
+ UPNG_ENOMEM = 1, /* memory allocation failed */
+ UPNG_ENOTFOUND = 2, /* resource not found (file missing) */
+ UPNG_ENOTPNG = 3, /* image data does not have a PNG header */
+ UPNG_EMALFORMED = 4, /* image data is not a valid PNG image */
+ UPNG_EUNSUPPORTED = 5, /* critical PNG chunk type is not supported */
+ UPNG_EUNINTERLACED = 6, /* image interlacing is not supported */
+ UPNG_EUNFORMAT = 7, /* image color format is not supported */
+ UPNG_EPARAM = 8 /* invalid parameter to method call */
+} upng_error;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c b/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c
new file mode 100644
index 000000000000..cd173151dbff
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c
@@ -0,0 +1,74 @@
+// https://github.com/dlang/dmd/issues/18127
+union struct_or_union {
+ int x;
+};
+
+struct S_n_fields {
+ int x, y;
+};
+
+struct S_types {
+ float x;
+};
+
+struct S_names {
+ float x;
+};
+
+struct B {
+ int x;
+};
+
+struct S_b {
+ struct B b;
+};
+
+struct S_contains_anon_named {
+ struct {
+ int x;
+ } a;
+};
+
+struct S_contains_anon_unnamed {
+ struct {
+ int x;
+ };
+};
+
+struct S_bitfields_mismatch1 {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+struct S_bitfields_mismatch2 {
+ unsigned x;
+ unsigned y: 1;
+};
+
+struct S_bitfields_widths {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+
+struct S_bitfields_anon {
+ unsigned x: 3;
+ unsigned : 1;
+};
+
+struct S_alignas {
+ _Alignas(8) float x;
+};
+struct S_aligned {
+ float x;
+}__attribute__((aligned(8)));
+
+struct __attribute__((packed)) S_pack_1 {
+ float x;
+ char c;
+};
+#pragma pack(push)
+#pragma pack(1)
+struct S_pack_2 {
+ float x;
+ char c;
+};
+#pragma pack(pop)
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c b/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c
new file mode 100644
index 000000000000..cd173151dbff
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c
@@ -0,0 +1,74 @@
+// https://github.com/dlang/dmd/issues/18127
+union struct_or_union {
+ int x;
+};
+
+struct S_n_fields {
+ int x, y;
+};
+
+struct S_types {
+ float x;
+};
+
+struct S_names {
+ float x;
+};
+
+struct B {
+ int x;
+};
+
+struct S_b {
+ struct B b;
+};
+
+struct S_contains_anon_named {
+ struct {
+ int x;
+ } a;
+};
+
+struct S_contains_anon_unnamed {
+ struct {
+ int x;
+ };
+};
+
+struct S_bitfields_mismatch1 {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+struct S_bitfields_mismatch2 {
+ unsigned x;
+ unsigned y: 1;
+};
+
+struct S_bitfields_widths {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+
+struct S_bitfields_anon {
+ unsigned x: 3;
+ unsigned : 1;
+};
+
+struct S_alignas {
+ _Alignas(8) float x;
+};
+struct S_aligned {
+ float x;
+}__attribute__((aligned(8)));
+
+struct __attribute__((packed)) S_pack_1 {
+ float x;
+ char c;
+};
+#pragma pack(push)
+#pragma pack(1)
+struct S_pack_2 {
+ float x;
+ char c;
+};
+#pragma pack(pop)
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp20344.c b/gcc/testsuite/gdc.test/compilable/imports/imp20344.c
new file mode 100644
index 000000000000..56ac79c930c3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp20344.c
@@ -0,0 +1,2 @@
+// https://github.com/dlang/dmd/issues/20334
+#define X "X"
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp20499.c b/gcc/testsuite/gdc.test/compilable/imports/imp20499.c
new file mode 100644
index 000000000000..7ae74906f73c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp20499.c
@@ -0,0 +1,8 @@
+// https://github.com/dlang/dmd/issues/20499
+typedef struct Foo {
+ int x;
+} *pFoo;
+
+struct Bar {
+ struct Foo foo;
+};
diff --git a/gcc/testsuite/gdc.test/compilable/test18127.d b/gcc/testsuite/gdc.test/compilable/test18127.d
new file mode 100644
index 000000000000..3d6b454a2be1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test18127.d
@@ -0,0 +1,5 @@
+// https://github.com/dlang/dmd/issues/18127
+// EXTRA_FILES: imports/imp18127a.c imports/imp18127b.c
+
+import imports.imp18127a;
+import imports.imp18127b;
diff --git a/gcc/testsuite/gdc.test/compilable/test20344.d b/gcc/testsuite/gdc.test/compilable/test20344.d
new file mode 100644
index 000000000000..26ee9a3269e5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20344.d
@@ -0,0 +1,14 @@
+// https://github.com/dlang/dmd/issues/20334
+// EXTRA_FILES: imports/imp20344.c
+import imports.imp20344;
+string s = X;
+const(char)* p = X;
+
+void takes_string(string){ }
+void takes_char_star(const(char)*){ }
+
+
+void test20344(){
+ takes_string(X);
+ takes_char_star(X);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test20499.d b/gcc/testsuite/gdc.test/compilable/test20499.d
new file mode 100644
index 000000000000..3263aed66b62
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20499.d
@@ -0,0 +1,3 @@
+// https://github.com/dlang/dmd/issues/20499
+// EXTRA_FILES: imports/imp20499.c
+import imports.imp20499;
diff --git a/gcc/testsuite/gdc.test/compilable/test3004.d b/gcc/testsuite/gdc.test/compilable/test3004.d
index 23ec46f29055..664452ef4e68 100644
--- a/gcc/testsuite/gdc.test/compilable/test3004.d
+++ b/gcc/testsuite/gdc.test/compilable/test3004.d
@@ -1,7 +1,7 @@
// https://issues.dlang.org/show_bug.cgi?id=3004
/*
REQUIRED_ARGS: -ignore -v
-TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|library|function object|function core|\s*$)")
+TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|library|function object|function core|\s*$)")
TEST_OUTPUT:
---
pragma GNU_attribute (__error)
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff3.d b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
index 89228a9bc4ab..08aa3b03d11d 100644
--- a/gcc/testsuite/gdc.test/compilable/testcstuff3.d
+++ b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
@@ -2,3 +2,22 @@
import imports.cstuff3;
static assert(squared(4) == 16);
+
+/* test case for issue #21094 */
+string enum_to_str(E)(E v) if (is(E == enum))
+{
+ final switch (v) with(E)
+ {
+ static foreach (m; __traits(allMembers, E))
+ {
+ case mixin(m):
+ return m;
+ }
+ }
+}
+
+void testEnumSwitch()
+{
+ auto str = enum_to_str(UPNG_EOK);
+ assert(str == "UPNG_EOK");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/uda_lambda.d b/gcc/testsuite/gdc.test/compilable/uda_lambda.d
new file mode 100644
index 000000000000..df331747a7f1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/uda_lambda.d
@@ -0,0 +1,3 @@
+enum UDA;
+int fun() @UDA => 7;
+static assert(fun() == 7);
diff --git a/gcc/testsuite/gdc.test/compilable/vcg-ast.d b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
index 9197441affea..bcb7256723c6 100644
--- a/gcc/testsuite/gdc.test/compilable/vcg-ast.d
+++ b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
@@ -75,3 +75,14 @@ template imported()
}
alias myImport = imported!();
+
+// https://github.com/dlang/dmd/issues/21105
+
+enum compiles = __traits(compiles,{
+ int[] arr;
+ arr ~= 1;
+});
+enum isexp = is(typeof({
+ int[] arr;
+ arr ~= 1;
+}));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b23686.d b/gcc/testsuite/gdc.test/fail_compilation/b23686.d
index 4c2a5bd026d2..5838f5c8e10c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b23686.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b23686.d
@@ -4,7 +4,7 @@ TEST_OUTPUT:
fail_compilation/b23686.d(107): Error: undefined identifier `eFN1`, did you mean template `eFN0()()`?
fail_compilation/b23686.d(107): Error: `mixin(_error_)` does not give a valid type
fail_compilation/b23686.d(115): while looking for match for `eload!(int, 1)`
-fail_compilation/b23686.d(121): Error: undefined identifier `FNwtf`
+fail_compilation/b23686.d-mixin-121(121): Error: undefined identifier `FNwtf`
fail_compilation/b23686.d(121): Error: `mixin(_error_)` does not give a valid type
fail_compilation/b23686.d(126): while looking for match for `load!"wtf"`
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d b/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d
index 44c237f144f8..56e28e1ce7bb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d
@@ -2,10 +2,12 @@
/*
TEST_OUTPUT:
---
-fail_compilation/checkimports2.d(25): Error: no property `X` for type `checkimports2.B`, did you mean `imports.imp2.X`?
-fail_compilation/checkimports2.d(25): while evaluating: `static assert((B).X == 0)`
-fail_compilation/checkimports2.d(26): Error: no property `Y` for type `checkimports2.B`, did you mean `imports.imp2.Y`?
-fail_compilation/checkimports2.d(26): while evaluating: `static assert((B).Y == 2)`
+fail_compilation/checkimports2.d(27): Error: no property `X` for type `checkimports2.B`
+fail_compilation/imports/imp2.d(3): did you mean `imports.imp2.X`?
+fail_compilation/checkimports2.d(27): while evaluating: `static assert((B).X == 0)`
+fail_compilation/checkimports2.d(28): Error: no property `Y` for type `checkimports2.B`
+fail_compilation/imports/imp2.d(4): did you mean `imports.imp2.Y`?
+fail_compilation/checkimports2.d(28): while evaluating: `static assert((B).Y == 2)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10405.d b/gcc/testsuite/gdc.test/fail_compilation/diag10405.d
deleted file mode 100644
index 28da8af93ad1..000000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10405.d
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/diag10405.d(10): Error: cannot return non-void from `void` function
----
-*/
-
-void main()
-{
- return 10;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag20888.d b/gcc/testsuite/gdc.test/fail_compilation/diag20888.d
index 84af42533fcc..d030a98ec2c2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag20888.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag20888.d
@@ -13,12 +13,12 @@ fail_compilation/diag20888.d(49): Error: return value `callback` of type `int de
fail_compilation/diag20888.d(54): Error: return value `() => 3755` of type `int function() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted
fail_compilation/diag20888.d(54): Did you intend to call the function pointer?
fail_compilation/diag20888.d(59): Error: `return` expression expected
-fail_compilation/diag20888.d(64): Error: cannot return non-void from `void` function
fail_compilation/diag20888.d(70): Error: return value `() => i` of type `int delegate() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted
fail_compilation/diag20888.d(70): Did you intend to call the delegate?
---
*/
+
int alpha(int function() callback)
{
return callback;
@@ -59,10 +59,10 @@ int theta()
return;
}
-void iota()
-{
- return 0xEAB;
-}
+
+
+
+
int kappa()
{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23384.d b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d
index 1fa4da5ffb9e..9cb17c00d74f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag23384.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d
@@ -4,8 +4,8 @@
TEST_OUTPUT:
---
fail_compilation/diag23384.d(28): Error: function `diag23384.Derived.fun(B b)` is not callable using argument types `(A)`
-fail_compilation/diag23384.d(28): function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun`
-fail_compilation/diag23384.d(28): add `alias fun = diag23384.Base.fun` to `diag23384.Derived`'s body to merge the overload sets
+fail_compilation/diag23384.d(28): Note: function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun`
+fail_compilation/diag23384.d(28): Add `alias fun = diag23384.Base.fun;` to `diag23384.Derived`'s body to merge the overload sets
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9679.d b/gcc/testsuite/gdc.test/fail_compilation/diag9679.d
index 22e94e575969..50b8717adf31 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9679.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9679.d
@@ -3,13 +3,14 @@ TEST_OUTPUT:
---
fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
-fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n`
-fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?
-fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref`
-fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to local variable `i`
+fail_compilation/diag9679.d(94): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent
+fail_compilation/diag9679.d(100): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent
+fail_compilation/diag9679.d(16): Error: rvalue `1` cannot be assigned to `ref n`
+fail_compilation/diag9679.d(17): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?
+fail_compilation/diag9679.d(18): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref`
+fail_compilation/diag9679.d(25): Error: returning `r` escapes a reference to local variable `i`
---
*/
-
void main()
{
if (ref n = 1) {}
@@ -60,7 +61,6 @@ fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must
---
*/
-
void test5()
{
ref int r5;
@@ -90,8 +90,11 @@ void test9()
auto ref int y = void;
}
-void testKeywordOrder()(ref auto int x, auto const ref float y) {}
-void testKeywordOrder()
+void testKeywordOrder()(ref auto int x, auto const ref float y) {};
+ref auto int testKeywordOrder()
{
ref auto int x = 3;
+ return 3;
}
+
+auto { ref int autoFromScope() => 3; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d b/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d
new file mode 100644
index 000000000000..ea144b2c9db2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d
@@ -0,0 +1,17 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/diag_ptr_conversion.d(15): Error: cannot implicitly convert `const(int)*` to `int*`
+fail_compilation/diag_ptr_conversion.d(15): Note: Converting const to mutable requires an explicit cast (`cast(int*)`).
+fail_compilation/diag_ptr_conversion.d(16): Error: cannot implicitly convert `int*` to `float*`
+fail_compilation/diag_ptr_conversion.d(16): Note: Pointer types point to different base types (`int` vs `float`)
+---
+*/
+
+void testPointerConversions()
+{
+ int* p;
+ const(int)* cp = p;
+ p = cp;
+ float* f = p;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d b/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d
new file mode 100644
index 000000000000..9c04e9a324f6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d
@@ -0,0 +1,18 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation\enum_auto_increment.d(17): Error: cannot automatically assign value to enum member `enum_auto_increment.A2.d` because base type `A1` is an enum; provide an explicit value
+---
+*/
+
+enum A1 : int
+{
+ a,
+ b,
+}
+
+enum A2 : A1
+{
+ c,
+ d,
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail109.d b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
index 003e65f9b807..94f951f9f953 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail109.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
@@ -34,9 +34,7 @@ enum E1 : short
/* https://issues.dlang.org/show_bug.cgi?id=14950
TEST_OUTPUT:
---
-fail_compilation/fail109.d(50): Error: cannot check `fail109.B.end` value for overflow
-fail_compilation/fail109.d(50): Error: comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType`
-fail_compilation/fail109.d(50): Error: enum member `fail109.B.end` initialization with `B.start+1` causes overflow for type `C`
+fail_compilation\fail109.d(48): Error: cannot automatically assign value to enum member `fail109.B.end` because base type `C` is an enum; provide an explicit value
---
*/
enum C
@@ -53,10 +51,10 @@ enum B
/* https://issues.dlang.org/show_bug.cgi?id=11849
TEST_OUTPUT:
---
-fail_compilation/fail109.d(72): Error: enum member `fail109.RegValueType1a.Unknown` is forward referenced looking for `.max`
-fail_compilation/fail109.d(79): Error: enum member `fail109.RegValueType1b.Unknown` is forward referenced looking for `.max`
-fail_compilation/fail109.d(84): Error: enum member `fail109.RegValueType2a.Unknown` is forward referenced looking for `.min`
-fail_compilation/fail109.d(91): Error: enum member `fail109.RegValueType2b.Unknown` is forward referenced looking for `.min`
+fail_compilation/fail109.d(70): Error: enum member `fail109.RegValueType1a.Unknown` is forward referenced looking for `.max`
+fail_compilation/fail109.d(77): Error: enum member `fail109.RegValueType1b.Unknown` is forward referenced looking for `.max`
+fail_compilation/fail109.d(82): Error: enum member `fail109.RegValueType2a.Unknown` is forward referenced looking for `.min`
+fail_compilation/fail109.d(89): Error: enum member `fail109.RegValueType2b.Unknown` is forward referenced looking for `.min`
---
*/
@@ -94,7 +92,7 @@ enum RegValueType2b : DWORD
/*
TEST_OUTPUT:
---
-fail_compilation/fail109.d(107): Error: enum member `fail109.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
+fail_compilation/fail109.d(105): Error: enum member `fail109.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11714.d b/gcc/testsuite/gdc.test/fail_compilation/fail11714.d
index abc47087ffaa..f36f3e5831e9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11714.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11714.d
@@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail11714.d(14): Error: variable `fail11714.c` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.
-fail_compilation/fail11714.d(21): Error: variable `fail11714.s` is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead.
+fail_compilation/fail11714.d(16): Error: variable `fail11714.c` is a thread-local class and cannot have a static initializer
+fail_compilation/fail11714.d(16): use `static this()` to initialize instead
+fail_compilation/fail11714.d(23): Error: variable `fail11714.s` is a thread-local pointer to struct and cannot have a static initializer
+fail_compilation/fail11714.d(23): use `static this()` to initialize instead
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
index 8e5f9800a816..aec716556a4f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail15361.d(8): Error: unexpected `(` after `errorize`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression
+fail_compilation/fail15361.d(9): Error: unexpected `(` after `errorize`, inside `is` expression
+fail_compilation/fail15361.d(9): try enclosing the contents of `is` with a `typeof` expression
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d b/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d
index 4b209685ca44..4cbd591cbf82 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d
@@ -1,6 +1,6 @@
/*
REQUIRED_ARGS: -v
-TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|\s*$)")
+TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|\s*$)")
TEST_OUTPUT:
---
fail_compilation/fail15616b.d(44): Error: none of the overloads of `foo` are callable using argument types `(double)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16.d b/gcc/testsuite/gdc.test/fail_compilation/fail16.d
index 4602d3de3bd6..ce021a95b859 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail16.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail16.d
@@ -2,8 +2,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail16.d(19): Error: function declaration without return type. (Note that constructors are always named `this`)
-fail_compilation/fail16.d(19): Error: variable name expected after type `bar!(typeof(X))(X)`, not `;`
+fail_compilation/fail16.d(20): Error: function declaration without return type
+fail_compilation/fail16.d(20): Note that constructors are always named `this`
+fail_compilation/fail16.d(20): Error: variable name expected after type `bar!(typeof(X))(X)`, not `;`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail163.d b/gcc/testsuite/gdc.test/fail_compilation/fail163.d
index 7f8f028fa52d..590bf23931c9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail163.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail163.d
@@ -14,7 +14,8 @@ void test1()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(24): Error: cannot implicitly convert expression `p` of type `const(int***)` to `const(int)***`
+fail_compilation/fail163.d(25): Error: cannot implicitly convert `const(int***)` to `const(int)***`
+fail_compilation/fail163.d(25): Note: Converting const to mutable requires an explicit cast (`cast(int*)`).
---
*/
void test2()
@@ -27,7 +28,7 @@ void test2()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(37): Error: cannot modify `const` expression `p`
+fail_compilation/fail163.d(38): Error: cannot modify `const` expression `p`
---
*/
void test3()
@@ -40,7 +41,7 @@ void test3()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(50): Error: cannot implicitly convert expression `cp` of type `const(int)***[]` to `const(uint***)[]`
+fail_compilation/fail163.d(51): Error: cannot implicitly convert expression `cp` of type `const(int)***[]` to `const(uint***)[]`
---
*/
void test4()
@@ -53,7 +54,7 @@ void test4()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(63): Error: cannot modify `const` expression `*p`
+fail_compilation/fail163.d(64): Error: cannot modify `const` expression `*p`
---
*/
void test5()
@@ -66,8 +67,8 @@ void test5()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(76): Error: cannot implicitly convert expression `& x` of type `int*` to `immutable(int)*`
-fail_compilation/fail163.d(77): Error: cannot modify `immutable` expression `*p`
+fail_compilation/fail163.d(77): Error: cannot implicitly convert expression `& x` of type `int*` to `immutable(int)*`
+fail_compilation/fail163.d(78): Error: cannot modify `immutable` expression `*p`
---
*/
void test6()
@@ -80,7 +81,8 @@ void test6()
/*
TEST_OUTPUT:
---
-fail_compilation/fail163.d(89): Error: cannot implicitly convert expression `& x` of type `const(int)*` to `int*`
+fail_compilation/fail163.d(91): Error: cannot implicitly convert `const(int)*` to `int*`
+fail_compilation/fail163.d(91): Note: Converting const to mutable requires an explicit cast (`cast(int*)`).
---
*/
void test7()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
index bf4b189f6ebc..f5fc27f1a89d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
@@ -3,11 +3,14 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail18219.d(17): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
-fail_compilation/fail18219.d(18): Error: no property `Bar` for type `a18219.AST`
+fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST`
+fail_compilation/imports/b18219.d(3): did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(21): Error: no property `Bar` for type `a18219.AST`
fail_compilation/imports/a18219.d(3): struct `AST` defined here
-fail_compilation/fail18219.d(19): Error: no property `fun` for type `AST`, did you mean `b18219.fun`?
-fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(22): Error: no property `fun` for type `AST`
+fail_compilation/imports/b18219.d(15): did you mean `b18219.fun`?
+fail_compilation/fail18219.d(23): Error: no property `Foobar` for type `AST`
+fail_compilation/imports/b18219.d(3): did you mean `b18219.Foobar`?
---
*/
import imports.a18219;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
index c1abd0df90af..e617249ed713 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
@@ -5,10 +5,10 @@ fail_compilation/fail19103.d(14): Error: no property `puts` for `new C` of type
fail_compilation/fail19103.d(26): class `C` defined here
fail_compilation/fail19103.d(16): Error: no property `puts` for `s1` of type `fail19103.S1`
fail_compilation/fail19103.d(30): struct `S1` defined here
-fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`?
+fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2`
+$p:druntime/import/core/stdc/stdio.d$($n$): did you mean `core.stdc.stdio.puts`?
---
*/
-
void main()
{
(new C).puts("OK."); // Error: no property puts for type test.C, did you mean core.stdc.stdio.puts(T...)(T args)?
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index 78c596390b56..a5d4499f3fff 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -21,7 +21,7 @@ fail_compilation/fail196.d(44): expression: `";\n assert(s == "`
fail_compilation/fail196.d(45): Error: found `}` when expecting `;` following expression
fail_compilation/fail196.d(45): expression: `xxx`
fail_compilation/fail196.d(47): Error: found `<` when expecting `;` following expression
-fail_compilation/fail196.d(45): expression: `");\n\n s = q" < foo`
+fail_compilation/fail196.d(47): expression: `");\n\n s = q" < foo`
fail_compilation/fail196.d(48): Error: found `foo` when expecting `;` following expression
fail_compilation/fail196.d(47): expression: `xxx >> ";\n assert(s == "`
fail_compilation/fail196.d(48): Error: found `<` instead of statement
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21547.d b/gcc/testsuite/gdc.test/fail_compilation/fail21547.d
index 7a6a44a4a133..440a301de514 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21547.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21547.d
@@ -3,8 +3,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail21547.d(32): Error: struct `Bar` has constructors, cannot use `{ initializers }`, use `Bar( initializers )` instead
-fail_compilation/fail21547.d(33): Error: struct `Bar1` has constructors, cannot use `{ initializers }`, use `Bar1( initializers )` instead
+fail_compilation/fail21547.d(34): Error: Cannot use struct initializer syntax for struct `Bar` because it has a constructor
+fail_compilation/fail21547.d(34): Use `Bar( arguments )` instead of `{ initializers }`
+fail_compilation/fail21547.d(35): Error: Cannot use struct initializer syntax for struct `Bar1` because it has a constructor
+fail_compilation/fail21547.d(35): Use `Bar1( arguments )` instead of `{ initializers }`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23439.d b/gcc/testsuite/gdc.test/fail_compilation/fail23439.d
index b070e581a4a7..6f16bc134366 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail23439.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23439.d
@@ -2,7 +2,8 @@
// PERMUTE_ARGS: -lowmem
/* TEST_OUTPUT:
---
-fail_compilation/fail23439.d(13): Error: variable `fail23439.ice23439` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.
+fail_compilation/fail23439.d(14): Error: variable `fail23439.ice23439` is a thread-local class and cannot have a static initializer
+fail_compilation/fail23439.d(14): use `static this()` to initialize instead
---
*/
class C23439
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail305.d b/gcc/testsuite/gdc.test/fail_compilation/fail305.d
deleted file mode 100644
index aef1624a07ca..000000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail305.d
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail305.d(10): Error: cannot return non-void from `void` function
----
-*/
-
-void main()
-{
- return "a";
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail336.d b/gcc/testsuite/gdc.test/fail_compilation/fail336.d
index 9df207120b36..8fb9857d4dc4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail336.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail336.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail336.d(16): Error: struct `S` has constructors, cannot use `{ initializers }`, use `S( initializers )` instead
+fail_compilation/fail336.d(17): Error: Cannot use struct initializer syntax for struct `S` because it has a constructor
+fail_compilation/fail336.d(17): Use `S( arguments )` instead of `{ initializers }`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail347.d b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
index c56acf5642cd..996990bd4001 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail347.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
@@ -3,16 +3,16 @@ EXTRA_FILES: imports/fail347a.d
TEST_OUTPUT:
---
fail_compilation/fail347.d(26): Error: undefined identifier `bbr`, did you mean variable `bar`?
-fail_compilation/fail347.d(27): Error: no property `ofo` for type `S`, did you mean `fail347.S.foo`?
-fail_compilation/fail347.d(29): Error: no property `fool` for `sp` of type `fail347.S*`
-fail_compilation/fail347.d(20): did you mean variable `foo`?
+fail_compilation/fail347.d(27): Error: no property `ofo` for type `S`
+fail_compilation/fail347.d(20): did you mean `foo`?
+fail_compilation/fail347.d(29): Error: no property `fool` for type `S*`
+fail_compilation/fail347.d(20): did you mean `foo`?
fail_compilation/fail347.d(30): Error: undefined identifier `strlenx`, did you mean function `strlen`?
fail_compilation/fail347.d(31): Error: no property `strlenx` for `"hello"` of type `string`
fail_compilation/imports/fail347a.d(3): did you mean function `strlen`?
---
*/
-//import core.stdc.string;
import imports.fail347a;
struct S
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail41.d b/gcc/testsuite/gdc.test/fail_compilation/fail41.d
deleted file mode 100644
index 6d8939505399..000000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail41.d
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail41.d(17): Error: cannot return non-void from `void` function
----
-*/
-
-class MyClass
-{
-}
-
-MyClass[char[]] myarray;
-
-void fn()
-{
- foreach (MyClass mc; myarray)
- return mc;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail98.d b/gcc/testsuite/gdc.test/fail_compilation/fail98.d
index 7541d3718c7b..20b18d19db5b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail98.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail98.d
@@ -1,7 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail98.d(17): Error: cannot implicitly convert expression `256` of type `int` to `E`
+fail_compilation/fail98.d(20): Error: cannot implicitly convert expression `256` of type `int` to `E`
+fail_compilation/fail98.d(21): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD1` because base type `E` is an enum; provide an explicit value
+fail_compilation/fail98.d(22): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD2` because base type `E` is an enum; provide an explicit value
+fail_compilation/fail98.d(23): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD3` because base type `E` is an enum; provide an explicit value
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d b/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d
index 79242b163eea..ebd36a7cc1d2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d
@@ -16,7 +16,7 @@ fail_compilation/fail_pretty_errors.d(44): Error: mixin `fail_pretty_errors.test
^
fail_compilation/fail_pretty_errors.d(50): Error: invalid array operation `"" + ""` (possible missing [])
auto x = ""+"";
- ^
+ ^
fail_compilation/fail_pretty_errors.d(50): did you mean to concatenate (`"" ~ ""`) instead ?
fail_compilation/fail_pretty_errors.d(53): Error: cannot implicitly convert expression `1111` of type `int` to `byte`
byte ɑ = 1111;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d b/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d
index b6c3bc906a15..749d98f9bd0c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d
@@ -1,14 +1,15 @@
/* TEST_OUTPUT:
---
-fail_compilation/failcontracts.d(17): Error: missing `{ ... }` for function literal
-fail_compilation/failcontracts.d(17): Error: semicolon expected following auto declaration, not `bode`
-fail_compilation/failcontracts.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
-fail_compilation/failcontracts.d(18): Error: variable name expected after type `test1()`, not `bode`
-fail_compilation/failcontracts.d(18): Error: semicolon expected following function declaration, not `bode`
+fail_compilation/failcontracts.d(18): Error: missing `{ ... }` for function literal
+fail_compilation/failcontracts.d(18): Error: semicolon expected following auto declaration, not `bode`
+fail_compilation/failcontracts.d(19): Error: function declaration without return type
+fail_compilation/failcontracts.d(19): Note that constructors are always named `this`
+fail_compilation/failcontracts.d(19): Error: variable name expected after type `test1()`, not `bode`
fail_compilation/failcontracts.d(19): Error: semicolon expected following function declaration, not `bode`
-fail_compilation/failcontracts.d(21): Error: unexpected `(` in declarator
-fail_compilation/failcontracts.d(21): Error: found `T` when expecting `)`
-fail_compilation/failcontracts.d(21): Error: expected `{`, not `;` for enum declaration
+fail_compilation/failcontracts.d(20): Error: semicolon expected following function declaration, not `bode`
+fail_compilation/failcontracts.d(22): Error: unexpected `(` in declarator
+fail_compilation/failcontracts.d(22): Error: found `T` when expecting `)`
+fail_compilation/failcontracts.d(22): Error: expected `{`, not `;` for enum declaration
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix19613.d b/gcc/testsuite/gdc.test/fail_compilation/fix19613.d
new file mode 100644
index 000000000000..beca56fd7091
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix19613.d
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` cannot override `final` function `fix19613.A.a`
+fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` does not override any function
+fail_compilation/fix19613.d(15): Did you mean to override `void fix19613.A.a(string)`?
+---
+*/
+
+class A {
+ final void a(int) {}
+ void a(string) {}
+}
+class B : A {
+ override void a(int) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20075.d b/gcc/testsuite/gdc.test/fail_compilation/fix20075.d
new file mode 100644
index 000000000000..00f229d326b3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix20075.d
@@ -0,0 +1,21 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix20075.d(15): Error: none of the overloads of `this` can construct an immutable object with argument types `(int*)`. Expected `immutable(int*)`
+fail_compilation/fix20075.d(11): Candidate is: `fix20075.Foo.this(immutable(int*) a) immutable`
+---
+*/
+
+struct Foo {
+ @disable this();
+ immutable this(immutable int* a) {}
+}
+
+immutable(Foo) getFoo(int* a) {
+ return immutable Foo(a);
+}
+
+void main() {
+ int x;
+ auto foo = getFoo(&x);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20318.d b/gcc/testsuite/gdc.test/fail_compilation/fix20318.d
new file mode 100644
index 000000000000..f32030001278
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix20318.d
@@ -0,0 +1,46 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix20318.d(16): Error: cannot implicitly convert expression `c` of type `const(Bar)` to `Bar` because struct `Bar` contains pointers or references
+fail_compilation/fix20318.d(20): Error: cannot implicitly convert expression `complex_c` of type `const(ComplexBar)` to `ComplexBar` because struct `ComplexBar` contains pointers or references
+---
+*/
+
+void main() {
+ // This should work - struct without pointers
+ const Foo a;
+ Foo b = a; // This is okay
+
+ // This should fail with improved diagnostic message
+ const Bar c;
+ Bar d = c; // Error with improved diagnostic message
+
+ // Test with a more complex struct with nested pointers
+ const ComplexBar complex_c;
+ ComplexBar complex_d = complex_c; // Give improved error message
+}
+
+struct Foo {
+ int value;
+}
+
+struct Bar {
+ void* ptr;
+}
+
+// Simple struct without pointers
+struct Simple {
+ int value;
+}
+
+// Struct with a pointer
+struct WithPointer {
+ int* ptr;
+}
+
+// Complex struct that contains another struct with pointers
+struct ComplexBar {
+ Simple simple; // This is fine
+ int data; // This is fine
+ WithPointer nested; // This field prevents implicit conversion
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20867.d b/gcc/testsuite/gdc.test/fail_compilation/fix20867.d
new file mode 100644
index 000000000000..0ccad0980317
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix20867.d
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix20867.d(14): Error: cannot use `final switch` on enum `E` while it is being defined
+---
+*/
+
+// Test case from Issue #20867
+enum E
+{
+ a = 3,
+ b = () {
+ E e;
+ final switch (e) // This should error out instead of segfaulting
+ {
+ case E.a: break;
+ }
+ return 4;
+ } ()
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21042.d b/gcc/testsuite/gdc.test/fail_compilation/fix21042.d
new file mode 100644
index 000000000000..b2b224e5196e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix21042.d
@@ -0,0 +1,15 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix21042.d(14): Error: template `gun` is not callable using argument types `!()(int)`
+fail_compilation/fix21042.d(14): no parameter named `x`
+fail_compilation/fix21042.d(10): Candidate is: `gun(T)(T a)`
+---
+*/
+
+void gun(T)(T a) {}
+
+void main()
+{
+ gun(x: 1); // (no explanation) --> (no parameter named `x`)
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21165.d b/gcc/testsuite/gdc.test/fail_compilation/fix21165.d
new file mode 100644
index 000000000000..1d38013b4df0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix21165.d
@@ -0,0 +1,30 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix21165.d(12): Error: undefined identifier `foo`
+fail_compilation/fix21165.d(16): Error: undefined identifier `foo`
+fail_compilation/fix21165.d(21): Error: undefined identifier `foo`
+fail_compilation/fix21165.d(30): Error: undefined identifier `foo`
+---
+*/
+
+// Test case from Issue #21165
+foo
+f() {}
+
+// Test case from Issue #21171
+foo
+bar;
+
+// Test case from Issue #21169
+void fun(
+ foo x
+) {}
+
+// Test case from Issue #21168
+enum plusOne(int x) = x + 1;
+
+alias fooPlusOne =
+ plusOne
+ !
+ foo;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21166.d b/gcc/testsuite/gdc.test/fail_compilation/fix21166.d
new file mode 100644
index 000000000000..24dbf8b4675c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix21166.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fix21166.d(12): Error: invalid array operation `"foo" + "bar"` (possible missing [])
+fail_compilation/fix21166.d(12): did you mean to concatenate (`"foo" ~ "bar"`) instead ?
+---
+*/
+
+// Test case for https://github.com/dlang/dmd/issues/21166
+auto r =
+ "foo"
+ +
+ "bar";
diff --git a/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d
new file mode 100644
index 000000000000..8d6e6959f29b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d
@@ -0,0 +1,27 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/hidden_ctor.d(25): Error: constructor `hidden_ctor.B.this(string s)` is not callable using argument types `()`
+fail_compilation/hidden_ctor.d(25): Note: constructor `hidden_ctor.B.this` hides base class constructor `hidden_ctor.A.this`
+---
+*/
+
+class A {
+ int a;
+
+ this() {
+ this.a = 1;
+ }
+}
+class B : A {
+ string b;
+
+ this(string s) {
+ super();
+ this.b = s;
+ }
+}
+void main() {
+ auto b = new B();
+ b = new B("Hi, Mom!");
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11153.d b/gcc/testsuite/gdc.test/fail_compilation/ice11153.d
index 826bd8cd7ec1..936d987c1528 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11153.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11153.d
@@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice11153.d(11): Error: function declaration without return type. (Note that constructors are always named `this`)
-fail_compilation/ice11153.d(11): Error: variable name expected after type `foo()`, not `{`
+fail_compilation/ice11153.d(12): Error: function declaration without return type
+fail_compilation/ice11153.d(12): Note that constructors are always named `this`
+fail_compilation/ice11153.d(12): Error: variable name expected after type `foo()`, not `{`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
index 6d60fc43c1b2..2770676294c2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d
@@ -1,7 +1,8 @@
/* TEST_OUTPUT:
---
-fail_compilation/ice19755.d(11): Error: no property `x` for `self` of type `ice19755.Thunk!int*`
-fail_compilation/ice19755.d(16): Error: template instance `ice19755.Thunk!int` error instantiating
+fail_compilation/ice19755.d(12): Error: no property `x` for `self` of type `ice19755.Thunk!int*`
+fail_compilation/ice19755.d(8): struct `Thunk` defined here
+fail_compilation/ice19755.d(17): Error: template instance `ice19755.Thunk!int` error instantiating
---
*/
struct Thunk(Dummy) {
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c
new file mode 100644
index 000000000000..2ef629e3b5b2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c
@@ -0,0 +1,83 @@
+// https://github.com/dlang/dmd/issues/18127
+// union in here, struct in other
+union struct_or_union {
+ int x;
+};
+
+// mismatching number of fields
+struct S_n_fields {
+ int x, y;
+};
+
+// mismatched types
+struct S_types {
+ float x;
+};
+
+// mismatched names
+struct S_names {
+ float x;
+};
+
+struct B {
+ int x;
+};
+
+// Contains a struct that is incompatible
+struct S_b {
+ struct B b;
+};
+
+// mismatched anonymous struct
+struct S_contains_anon_named {
+ struct {
+ int x;
+ } a;
+};
+
+struct S_contains_anon_unnamed {
+ struct {
+ int x;
+ };
+};
+
+// bitfields
+struct S_bitfields_mismatch1 {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+struct S_bitfields_mismatch2 {
+ unsigned x;
+ unsigned y: 1;
+};
+
+struct S_bitfields_widths {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+
+struct S_bitfields_anon {
+ unsigned x: 3;
+ unsigned : 1;
+};
+
+// mismatched alignment
+struct S_alignas {
+ _Alignas(8) float x;
+};
+struct S_aligned {
+ float x;
+}__attribute__((aligned(8)));
+
+// mismatched packing
+struct __attribute__((packed)) S_pack_1 {
+ float x;
+ char c;
+};
+#pragma pack(push)
+#pragma pack(1)
+struct S_pack_2 {
+ float x;
+ char c;
+};
+#pragma pack(pop)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c
new file mode 100644
index 000000000000..3cbbf7a9a638
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c
@@ -0,0 +1,80 @@
+// https://github.com/dlang/dmd/issues/18127
+// struct in here, union in other
+struct struct_or_union {
+ int x;
+};
+
+// mismatching number of fields
+struct S_n_fields {
+ int x;
+};
+
+// mismatched types
+struct S_types {
+ int x;
+};
+
+// mismatched names
+struct S_names {
+ float y;
+};
+
+struct B {
+ float x;
+};
+
+// Contains a struct that is incompatible
+struct S_b {
+ struct B b;
+};
+
+// mismatched anonymous struct
+struct S_contains_anon_named {
+ struct {
+ float x;
+ } a;
+};
+
+struct S_contains_anon_unnamed {
+ struct {
+ float x;
+ };
+};
+
+// bitfields
+struct S_bitfields_mismatch1 {
+ unsigned x: 3;
+ unsigned y;
+};
+struct S_bitfields_mismatch2 {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+
+struct S_bitfields_widths {
+ unsigned x: 3;
+ unsigned y: 2;
+};
+
+struct S_bitfields_anon {
+ unsigned x: 3;
+ unsigned y: 1;
+};
+
+// mismatched alignment
+struct S_alignas {
+ float x;
+};
+struct S_aligned {
+ float x;
+}__attribute__((aligned(4)));
+
+// mismatched packing
+struct S_pack_1 {
+ float x;
+ char c;
+};
+struct S_pack_2 {
+ float x;
+ char c;
+};
diff --git a/gcc/testsuite/gdc.test/fail_compilation/lookup.d b/gcc/testsuite/gdc.test/fail_compilation/lookup.d
index fe752f2f4d74..db7eedab30ac 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/lookup.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/lookup.d
@@ -2,10 +2,12 @@
EXTRA_FILES: imports/imp1.d imports/imp2.d
TEST_OUTPUT:
---
-fail_compilation/lookup.d(24): Error: no property `X` for type `lookup.B`, did you mean `imports.imp2.X`?
-fail_compilation/lookup.d(24): while evaluating: `static assert((B).X == 0)`
-fail_compilation/lookup.d(25): Error: no property `Y` for type `lookup.B`, did you mean `imports.imp2.Y`?
-fail_compilation/lookup.d(25): while evaluating: `static assert((B).Y == 2)`
+fail_compilation/lookup.d(26): Error: no property `X` for type `lookup.B`
+fail_compilation/imports/imp2.d(3): did you mean `imports.imp2.X`?
+fail_compilation/lookup.d(26): while evaluating: `static assert((B).X == 0)`
+fail_compilation/lookup.d(27): Error: no property `Y` for type `lookup.B`
+fail_compilation/imports/imp2.d(4): did you mean `imports.imp2.Y`?
+fail_compilation/lookup.d(27): while evaluating: `static assert((B).Y == 2)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
index db8bf5968ddc..103c6b2a0473 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
@@ -1,9 +1,9 @@
/* TEST_OUTPUT:
---
-fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F;
-` of type `void`
+fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F;` of type `void`
---
*/
+
mixin template Foo() { }
void main()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
index 125ebcc926e5..761e1d4c78c1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
@@ -1,26 +1,27 @@
/*
TEST_OUTPUT:
---
-fail_compilation/named_arguments_error.d(37): Error: function `f` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(37): parameter `x` assigned twice
-fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here
fail_compilation/named_arguments_error.d(38): Error: function `f` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(38): argument `4` goes past end of parameter list
-fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(38): parameter `x` assigned twice
+fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here
fail_compilation/named_arguments_error.d(39): Error: function `f` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(39): parameter `y` assigned twice
-fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(39): argument `4` goes past end of parameter list
+fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here
fail_compilation/named_arguments_error.d(40): Error: function `f` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(40): no parameter named `a`
-fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here
-fail_compilation/named_arguments_error.d(41): Error: function `g` is not callable using argument types `(int, int)`
-fail_compilation/named_arguments_error.d(41): missing argument for parameter #1: `int x`
-fail_compilation/named_arguments_error.d(33): `named_arguments_error.g(int x, int y, int z = 3)` declared here
-fail_compilation/named_arguments_error.d(43): Error: no named argument `element` allowed for array dimension
-fail_compilation/named_arguments_error.d(44): Error: no named argument `number` allowed for scalar
-fail_compilation/named_arguments_error.d(45): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string`
-fail_compilation/named_arguments_error.d(46): Error: template `tempfun` is not callable using argument types `!()(int, int)`
-fail_compilation/named_arguments_error.d(49): Candidate is: `tempfun(T, U)(T t, U u)`
+fail_compilation/named_arguments_error.d(40): parameter `y` assigned twice
+fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(41): Error: function `f` is not callable using argument types `(int, int, int)`
+fail_compilation/named_arguments_error.d(41): no parameter named `a`
+fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(42): Error: function `g` is not callable using argument types `(int, int)`
+fail_compilation/named_arguments_error.d(42): missing argument for parameter #1: `int x`
+fail_compilation/named_arguments_error.d(34): `named_arguments_error.g(int x, int y, int z = 3)` declared here
+fail_compilation/named_arguments_error.d(44): Error: no named argument `element` allowed for array dimension
+fail_compilation/named_arguments_error.d(45): Error: no named argument `number` allowed for scalar
+fail_compilation/named_arguments_error.d(46): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string`
+fail_compilation/named_arguments_error.d(47): Error: template `tempfun` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_error.d(47): argument `1` goes past end of parameter list
+fail_compilation/named_arguments_error.d(50): Candidate is: `tempfun(T, U)(T t, U u)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
index 6d8a70a2c469..a73fd3cb2e6f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
@@ -1,12 +1,15 @@
/*
TEST_OUTPUT:
---
-fail_compilation/named_arguments_ifti_error.d(17): Error: template `f` is not callable using argument types `!()(int, int)`
-fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)`
-fail_compilation/named_arguments_ifti_error.d(18): Error: template `f` is not callable using argument types `!()(int, int)`
-fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)`
-fail_compilation/named_arguments_ifti_error.d(19): Error: template `f` is not callable using argument types `!()(int)`
-fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)`
+fail_compilation/named_arguments_ifti_error.d(20): Error: template `f` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_ifti_error.d(20): parameter `x` assigned twice
+fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)`
+fail_compilation/named_arguments_ifti_error.d(21): Error: template `f` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_ifti_error.d(21): argument `3` goes past end of parameter list
+fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)`
+fail_compilation/named_arguments_ifti_error.d(22): Error: template `f` is not callable using argument types `!()(int)`
+fail_compilation/named_arguments_ifti_error.d(22): missing argument for parameter #1: `T x`
+fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
index 17daa96358b1..f1a469b5445f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
@@ -94,3 +94,33 @@ int[] bar13702(bool b) @nogc
auto aux = 1 ~ [2]; // error
return aux;
}
+
+/********** Enum and pointer types ***************/
+// https://github.com/dlang/dmd/issues/21052
+/*
+TEST_OUTPUT:
+---
+fail_compilation/nogc3.d(111): Error: this array literal causes a GC allocation in `@nogc` function `f`
+fail_compilation/nogc3.d(112): Error: this array literal causes a GC allocation in `@nogc` function `f`
+---
+*/
+
+void f() @nogc
+{
+ enum DA : int[] { a = [1,2,3] }
+ DA da = DA.a;
+ int i = *cast(int*)cast(char[4])['0', '0', '0', '0'];
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/nogc3.d(125): Error: this array literal causes a GC allocation in `@nogc` function `g`
+---
+*/
+
+// https://github.com/dlang/dmd/issues/21054
+void g() @nogc
+{
+ int[] x = (int[2]).init[];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d b/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d
new file mode 100644
index 000000000000..bcced1b9bff2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d
@@ -0,0 +1,37 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/nonvoid_return.d(15): Error: cannot return non-void from `void` function
+fail_compilation/nonvoid_return.d(18): Error: cannot return non-void from `void` function
+fail_compilation/nonvoid_return.d(29): Error: cannot return non-void from `void` function
+fail_compilation/nonvoid_return.d(32): Error: undefined identifier `NONEXISTENT`
+---
+*/
+
+
+
+void main()
+{
+ return 10;
+}
+
+void fs() => "a";
+
+class MyClass
+{
+}
+
+MyClass[char[]] myarray;
+
+void fn()
+{
+ foreach (MyClass mc; myarray)
+ return mc;
+}
+
+auto err() { NONEXISTENT++; }
+
+// Because `err` contains an error, it fails to infer void and gets an error return type
+// Don't print the 'cannot return non-void' error in this case
+
+void fe() => err;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
index ec6bd3ebce99..b49417436a53 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
@@ -117,7 +117,7 @@ TEST_OUTPUT:
---
fail_compilation/noreturn2.d(130): Error: cannot create instance of interface `I`
fail_compilation/noreturn2.d(133): Error: can only throw class objects derived from `Throwable`, not type `int[]`
-fail_compilation/noreturn2.d(138): Error: undefined identifier `UnkownException`
+fail_compilation/noreturn2.d(139): Error: undefined identifier `UnkownException`
---
+/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/powinline.d b/gcc/testsuite/gdc.test/fail_compilation/powinline.d
new file mode 100644
index 000000000000..11ebacd16aaa
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/powinline.d
@@ -0,0 +1,38 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/powinline.d(25): Error: cannot implicitly convert expression `(a + 5.0) ^^ 2L` of type `double` to `int`
+fail_compilation/powinline.d(26): Error: cannot implicitly convert expression `(1.0 / foo()) ^^ 2L` of type `double` to `int`
+fail_compilation/powinline.d(31): Error: void has no value
+fail_compilation/powinline.d(31): Error: incompatible types for `(5.0) * (bar())`: `double` and `void`
+fail_compilation/powinline.d(37): Error: cannot modify `immutable` expression `a`
+---
+*/
+
+double foo()
+{
+ return 5.0;
+}
+
+void bar()
+{
+ return;
+}
+
+void test1()
+{
+ double a = 2.0;
+ int b = (a + 5.0) ^^ 2.0;
+ b = (1 / foo()) ^^ 2.0;
+}
+
+void test2()
+{
+ double a = (5.0 * bar()) ^^ 2.0;
+}
+
+void test3()
+{
+ immutable double a = 3.0;
+ (a ^^= 2.0) = 6;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
index 438fdd76e1b0..8802469de2c4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
@@ -55,7 +55,9 @@ TEST_OUTPUT:
---
fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function
fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape
+fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a`
fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory
+fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
---
*/
@@ -87,3 +89,11 @@ void bar4003() @safe
{
int[][] a = [makeSA()[]];
}
+
+// https://github.com/dlang/dmd/issues/20901
+int* f20901() @safe
+{
+ int i = 3;
+ auto x = &[&i][0]; // Should error, i is escaped into allocated memory
+ return *x;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d b/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d
new file mode 100644
index 000000000000..560bc344242c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d
@@ -0,0 +1,43 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/seq_assign.d(28): Error: cannot assign `int` to expression sequence `(int)`
+fail_compilation/seq_assign.d(29): Error: cannot implicitly convert expression `s` of type `string` to `int`
+fail_compilation/seq_assign.d(30): Error: cannot modify constant `2`
+fail_compilation/seq_assign.d(31): Error: mismatched sequence lengths, 1 and 2
+fail_compilation/seq_assign.d(35): Error: mismatched sequence lengths, 1 and 2
+fail_compilation/seq_assign.d(36): Error: cannot implicitly convert expression `__t_field_0` of type `string` to `int`
+fail_compilation/seq_assign.d(40): Error: cannot assign `IntString` to expression sequence `(string, int)`
+fail_compilation/seq_assign.d(42): Error: cannot implicitly convert expression `AliasSeq!(b, c)` of type `(int, int)` to `IntString`
+---
+*/
+
+alias Seq(A...) = A;
+
+struct IntString
+{
+ Seq!(int, string) expand;
+ alias this = expand;
+}
+
+void main()
+{
+ int b, c;
+ string s;
+
+ Seq!(b,) = 1; // RHS not seq
+ Seq!(b,) = Seq!(s,); // b type error
+ Seq!(2,) = Seq!(1,); // not lvalue
+ Seq!(b,) = Seq!(1, 2); // too many
+
+ auto t = Seq!("two", 3);
+ Seq!(s, b) = t; // OK
+ Seq!(b,) = t; // too many
+ Seq!(b, c) = t; // b type error
+
+ IntString t2;
+ Seq!(b, s) = t2; // OK
+ t = t2; // type mismatch
+ t2 = Seq!(b, s); // OK
+ t2 = Seq!(b, c); // c wrong type
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15989.d b/gcc/testsuite/gdc.test/fail_compilation/test15989.d
index 38ca33126724..85b74bfad583 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15989.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15989.d
@@ -1,9 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test15989.d(39): Error: variable `test15989.main.ctRegex` : Unable to initialize enum with class or pointer to struct. Use static const variable instead.
-fail_compilation/test15989.d(48): Error: variable `test15989.test.c` : Unable to initialize enum with class or pointer to struct. Use static const variable instead.
-fail_compilation/test15989.d(49): Error: cannot use non-constant CTFE pointer in an initializer `new int(3)`
+fail_compilation/test15989.d(41): Error: variable `test15989.main.ctRegex` : Unable to initialize enum with class or pointer to struct
+fail_compilation/test15989.d(41): use static const variable instead
+fail_compilation/test15989.d(50): Error: variable `test15989.test.c` : Unable to initialize enum with class or pointer to struct
+fail_compilation/test15989.d(50): use static const variable instead
+fail_compilation/test15989.d(51): Error: cannot use non-constant CTFE pointer in an initializer `new int(3)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18127.d b/gcc/testsuite/gdc.test/fail_compilation/test18127.d
new file mode 100644
index 000000000000..ec0487cd8925
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test18127.d
@@ -0,0 +1,106 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/imports/imp18127b.c(3): Error: struct `struct_or_union` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(3): previously declared here
+fail_compilation/imports/imp18127b.c(3): `imp18127b.struct_or_union` is a struct while `imp18127a.struct_or_union` is a union
+fail_compilation/imports/imp18127b.c(3): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(8): Error: struct `S_n_fields` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(8): previously declared here
+fail_compilation/imports/imp18127b.c(8): `imp18127b.S_n_fields` has 1 field(s) while `imp18127a.S_n_fields` has 2 field(s)
+fail_compilation/imports/imp18127b.c(8): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(13): Error: struct `S_types` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(13): previously declared here
+fail_compilation/imports/imp18127b.c(14): Field 0 differs in type
+fail_compilation/imports/imp18127b.c(14): typeof(x): int
+fail_compilation/imports/imp18127a.c(14): typeof(x): float
+fail_compilation/imports/imp18127b.c(13): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(18): Error: struct `S_names` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(18): previously declared here
+fail_compilation/imports/imp18127b.c(19): Field 0 differs in name
+fail_compilation/imports/imp18127b.c(19): y
+fail_compilation/imports/imp18127a.c(19): x
+fail_compilation/imports/imp18127b.c(18): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(22): Error: struct `B` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(22): previously declared here
+fail_compilation/imports/imp18127b.c(23): Field 0 differs in type
+fail_compilation/imports/imp18127b.c(23): typeof(x): float
+fail_compilation/imports/imp18127a.c(23): typeof(x): int
+fail_compilation/imports/imp18127b.c(22): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(27): Error: struct `S_b` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(27): previously declared here
+fail_compilation/imports/imp18127b.c(27): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(33): Error: struct `(anonymous struct)` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(33): previously declared here
+fail_compilation/imports/imp18127b.c(34): Field 0 differs in type
+fail_compilation/imports/imp18127b.c(34): typeof(x): float
+fail_compilation/imports/imp18127a.c(34): typeof(x): int
+fail_compilation/imports/imp18127b.c(32): Error: struct `S_contains_anon_named` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(32): previously declared here
+fail_compilation/imports/imp18127b.c(35): Field 0 differs in type
+fail_compilation/imports/imp18127b.c(35): typeof(a): (anonymous struct)
+fail_compilation/imports/imp18127a.c(35): typeof(a): (anonymous struct)
+fail_compilation/imports/imp18127b.c(32): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(38): Error: struct `S_contains_anon_unnamed` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(38): previously declared here
+fail_compilation/imports/imp18127b.c(40): Field 0 differs in type
+fail_compilation/imports/imp18127b.c(40): typeof(x): float
+fail_compilation/imports/imp18127a.c(40): typeof(x): int
+fail_compilation/imports/imp18127b.c(38): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(45): Error: struct `S_bitfields_mismatch1` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(45): previously declared here
+fail_compilation/imports/imp18127b.c(47): Field 1 differs in being a bitfield
+fail_compilation/imports/imp18127b.c(47): `imp18127b.S_bitfields_mismatch1.y` is not a bitfield
+fail_compilation/imports/imp18127a.c(47): `imp18127a.S_bitfields_mismatch1.y` is a bitfield
+fail_compilation/imports/imp18127b.c(45): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(49): Error: struct `S_bitfields_mismatch2` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(49): previously declared here
+fail_compilation/imports/imp18127b.c(50): Field 0 differs in being a bitfield
+fail_compilation/imports/imp18127b.c(50): `imp18127b.S_bitfields_mismatch2.x` *is a bitfield
+fail_compilation/imports/imp18127a.c(50): `imp18127a.S_bitfields_mismatch2.x` is not a bitfield
+fail_compilation/imports/imp18127b.c(49): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(54): Error: struct `S_bitfields_widths` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(54): previously declared here
+fail_compilation/imports/imp18127b.c(56): Field 1 differs in bitfield width
+fail_compilation/imports/imp18127b.c(56): `imp18127b.S_bitfields_widths.y`: 2
+fail_compilation/imports/imp18127a.c(56): `imp18127a.S_bitfields_widths.y`: 1
+fail_compilation/imports/imp18127b.c(54): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(59): Error: struct `S_bitfields_anon` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(59): previously declared here
+fail_compilation/imports/imp18127b.c(61): Field 1 differs in name
+fail_compilation/imports/imp18127b.c(61): y
+fail_compilation/imports/imp18127a.c(61): (anonymous)
+fail_compilation/imports/imp18127b.c(59): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(65): Error: struct `S_alignas` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(65): previously declared here
+fail_compilation/imports/imp18127b.c(66): Field 0 differs in alignment or packing
+fail_compilation/imports/imp18127b.c(66): `imp18127b.S_alignas.x` alignment: default
+fail_compilation/imports/imp18127a.c(66): `imp18127a.S_alignas.x` alignment: 8
+fail_compilation/imports/imp18127b.c(65): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(68): Error: struct `S_aligned` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(68): previously declared here
+fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` has different alignment or packing
+fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` alignment: 4
+fail_compilation/imports/imp18127a.c(68): `imp18127a.S_aligned` alignment: 8
+fail_compilation/imports/imp18127b.c(68): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(73): Error: struct `S_pack_1` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(73): previously declared here
+fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` has different alignment or packing
+fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` alignment: default
+fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` alignment: 1
+fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` packed: false
+fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` packed: true
+fail_compilation/imports/imp18127b.c(73): C structs with the same name from different imports are merged
+fail_compilation/imports/imp18127b.c(77): Error: struct `S_pack_2` already exists with an incompatible definition.
+fail_compilation/imports/imp18127a.c(79): previously declared here
+fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` has different alignment or packing
+fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` alignment: default
+fail_compilation/imports/imp18127a.c(79): `imp18127a.S_pack_2` alignment: 1
+fail_compilation/imports/imp18127b.c(77): C structs with the same name from different imports are merged
+---
+*/
+
+// https://github.com/dlang/dmd/issues/18127
+
+import imports.imp18127a;
+import imports.imp18127b;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19661.d b/gcc/testsuite/gdc.test/fail_compilation/test19661.d
index 369c0a862495..712721487caa 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test19661.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test19661.d
@@ -2,7 +2,8 @@
EXTRA_FILES: imports/imp19661.d
TEST_OUTPUT:
---
-fail_compilation/test19661.d(11): Error: variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.
+fail_compilation/test19661.d(12): Error: variables cannot be initialized with an expression of type `void`
+fail_compilation/test19661.d(12): only `= void;` is allowed, which prevents default initialization
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20489.d b/gcc/testsuite/gdc.test/fail_compilation/test20489.d
new file mode 100644
index 000000000000..1cd5350959c5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20489.d
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test20489.d(19): Error: function `pure nothrow @nogc @safe int test20489.D.f(int delegate(int) pure nothrow @nogc @safe body)` does not override any function, did you mean to override `pure nothrow @nogc @safe int test20489.B.f(scope int delegate(int) pure nothrow @nogc @safe)`?
+fail_compilation/test20489.d(19): Did you intend to override:
+fail_compilation/test20489.d(19): `pure nothrow @nogc @safe int test20489.B.f(scope int delegate(int) pure nothrow @nogc @safe)`
+fail_compilation/test20489.d(19): Parameter 1 is missing `scope`
+---
+*/
+
+// Test case for https://github.com/dlang/dmd/issues/20489
+// Improved error message on override mismatches
+
+class B {
+ pure nothrow @nogc @safe int f(scope int delegate(int) pure nothrow @nogc @safe) { return 0; }
+}
+
+class D : B {
+ override pure nothrow @nogc @safe int f(int delegate(int) pure nothrow @nogc @safe body) { return 0; }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21215.d b/gcc/testsuite/gdc.test/fail_compilation/test21215.d
new file mode 100644
index 000000000000..5efa315723c2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21215.d
@@ -0,0 +1,35 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test21215.d(13): Error: `y` is not a member of `S`
+fail_compilation/test21215.d(18): Error: `xhs` is not a member of `S`, did you mean variable `xsh`?
+fail_compilation/test21215.d(28): Error: `y` is not a member of `S`
+fail_compilation/test21215.d(32): Error: `yashu` is not a member of `S`
+---
+*/
+struct S { int xsh; }
+
+void test() {
+ auto s1 = S(
+ y:
+ 1
+ );
+
+ auto s2 = S(
+ xhs:
+ 1
+ );
+
+ auto s3 = S(
+ xsh: 1
+ );
+
+ auto s4 = S(
+ xsh: 1,
+ y: 2
+ );
+
+ auto s5 = S(
+ yashu:
+ 2
+ );
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21304.d b/gcc/testsuite/gdc.test/fail_compilation/test21304.d
new file mode 100644
index 000000000000..9789e2b9c956
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21304.d
@@ -0,0 +1,6 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test21304.d(6): Error: undefined identifier `unknown`
+---
+*/
+int[unknown] values = [1, 2, 3];
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21317.d b/gcc/testsuite/gdc.test/fail_compilation/test21317.d
new file mode 100644
index 000000000000..39b3963799eb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21317.d
@@ -0,0 +1,39 @@
+module dmd.compiler.test.fail_compilation.test21317;
+
+/* TEST_OUTPUT:
+---
+fail_compilation/test21317.d(16): Error: `writeln` is not defined, perhaps `import std.stdio;` ?
+fail_compilation/test21317.d(21): Error: undefined identifier `Zero`, did you mean variable `zero`?
+fail_compilation/test21317.d(25): Error: undefined identifier `NULL`, did you mean `null`?
+fail_compilation/test21317.d(31): Error: undefined identifier `this`, did you mean `typeof(this)`?
+fail_compilation/test21317.d(38): Error: undefined identifier `unknown`
+---
+*/
+
+// Weird formatting is intended to check the loc
+
+int[
+ writeln
+ ] arr1;
+
+int zero = 0;
+int [
+ Zero
+ ] arr2;
+
+int [
+ NULL
+ ] arr3;
+
+struct S4
+{
+ enum E4 :
+ this
+ {
+ fail,
+ }
+}
+
+int [
+ unknown
+ ] arr5;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
index 1173d14480d0..a0ade760fe52 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
@@ -5,7 +5,7 @@ TEST_OUTPUT:
---
fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo`
fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo`
-fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct a `immutable` object with argument types `(immutable(Foo!int))`
+fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct an immutable object with argument types `(immutable(Foo!int))`. Expected `immutable(immutable(Foo!int))`
fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)`
fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)`
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d b/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d
new file mode 100644
index 000000000000..bd3ff49e0e36
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d
@@ -0,0 +1,7 @@
+/+
+TEST_OUTPUT:
+---
+fail_compilation/uda_lambda.d(7): Error: declaration expected, not `=>`
+---
++/
+@a => 7 int b;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/union_conv.d b/gcc/testsuite/gdc.test/fail_compilation/union_conv.d
index f08809c48500..134da36ecdbf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/union_conv.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/union_conv.d
@@ -2,7 +2,7 @@
REQUIRED_ARGS: -preview=fixImmutableConv
TEST_OUTPUT:
---
-fail_compilation/union_conv.d(18): Error: cannot implicitly convert expression `c` of type `const(U)` to `U`
+fail_compilation/union_conv.d(18): Error: cannot implicitly convert expression `c` of type `const(U)` to `U` because union `U` contains pointers or references
---
*/
diff --git a/gcc/testsuite/gdc.test/runnable/placenew.d b/gcc/testsuite/gdc.test/runnable/placenew.d
index d90d10a5e744..834a1f76bcbf 100644
--- a/gcc/testsuite/gdc.test/runnable/placenew.d
+++ b/gcc/testsuite/gdc.test/runnable/placenew.d
@@ -93,6 +93,47 @@ void test6()
/*************************************************/
+struct S7
+{
+ int x = 10;
+ int y = 20;
+}
+
+void test7()
+{
+ S7 t = void;
+ new (t) S7(10,20);
+ assert(t.x == 10 && t.y == 20);
+}
+
+/*************************************************/
+// https://github.com/dlang/dmd/issues/21203
+
+struct Y8
+{
+ int a;
+ this() @disable; // default disabled
+ this(int i) { a = i; }
+}
+
+struct S8
+{
+ Y8 m;
+
+ this(int x)
+ {
+ new(m) Y8(x); // initialise `m`
+ }
+}
+
+void test8()
+{
+ S8 s = S8(3);
+ assert(s.m.a == 3);
+}
+
+/*************************************************/
+
int main()
{
test1();
@@ -101,6 +142,8 @@ int main()
test4();
test5();
test6();
+ test7();
+ test8();
return 0;
}
diff --git a/gcc/testsuite/gdc.test/runnable/powinline.d b/gcc/testsuite/gdc.test/runnable/powinline.d
new file mode 100644
index 000000000000..92d1c04e5564
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/powinline.d
@@ -0,0 +1,64 @@
+/*
+REQUIRED_ARGS: -betterC
+RUN_OUTPUT:
+---
+Success
+---
+*/
+import core.stdc.stdio;
+
+void test1()
+{
+ enum real Two = 2.0;
+ static assert(Two^^3 == 8.0);
+}
+
+void test2()
+{
+ double x = 5.0;
+ assert(x^^-1 == 1/x);
+ x = -1.0;
+ assert(x^^1 == x);
+ assert((x += 3) ^^ 2.0 == 4.0);
+ assert((x) ^^ 2.0 == 4.0);
+ assert((x *= 5) ^^ 2.0 == (x * x));
+ assert(x^^-1 == 1.0 / x);
+ assert((x^^-1) ^^ 0.0 == 1.0);
+}
+
+void test3()
+{
+ int x = 6;
+ assert(x ^^ 0 == 1);
+ assert((x += 3) ^^ 2 == 81);
+ assert(x ^^ 2 == (x ^^ 1) * (x ^^ 1));
+ static assert(4.0 ^^ -1 == 0.25);
+}
+
+void test4()
+{
+ // Test that LHS side effects are evaluated.
+ int count = 0;
+ double x()
+ {
+ count++;
+ return 8.0;
+ }
+ assert(x ^^ -1 == 1.0 / 8.0);
+ assert(count == 1);
+ assert(x ^^ 0 == 1.0);
+ assert(count == 2);
+ assert(x ^^ 1 == 8.0);
+ assert(count == 3);
+ assert(x ^^ 2 == 64.0);
+ assert(count == 4);
+}
+
+extern(C) void main()
+{
+ test1();
+ test2();
+ test3();
+ test4();
+ printf("Success\n");
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testaa2.d b/gcc/testsuite/gdc.test/runnable/testaa2.d
index e1abcb4418c5..3d199d984125 100644
--- a/gcc/testsuite/gdc.test/runnable/testaa2.d
+++ b/gcc/testsuite/gdc.test/runnable/testaa2.d
@@ -307,6 +307,26 @@ void testinenum()
assert("one" in aa);
}
+// https://github.com/dlang/dmd/issues/21258
+void test21258()
+{
+ alias AliasSeq(TList...) = TList;
+
+ struct S { int x; } // use a local type to not generate required TypeInfo elsewhere
+ foreach (T; AliasSeq!(S[int]))
+ enum E { a = T.init, } // bug report uses bad syntax here, but this crashed, too
+}
+
+// https://github.com/dlang/dmd/issues/21207
+void test21207()
+{
+ struct S { int x; } // use a local type to not generate required TypeInfo elsewhere
+ enum aa = ["baz": S(7)];
+
+ void foo(S[string] x = aa) { }
+ foo();
+}
+
/************************************************/
int main()
@@ -318,6 +338,7 @@ int main()
test3825x();
testinout();
testinenum();
+ test21258();
printf("Success\n");
return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/testinvariant.d b/gcc/testsuite/gdc.test/runnable/testinvariant.d
index 0ce855719117..11b8829b9fce 100644
--- a/gcc/testsuite/gdc.test/runnable/testinvariant.d
+++ b/gcc/testsuite/gdc.test/runnable/testinvariant.d
@@ -228,8 +228,52 @@ void test16384()
assert(s == "needs to be thrown2");
}
-
/***************************************************/
+// Fix: https://github.com/dlang/dmd/issues/20924 (invariant not called on extern(C++) classes)
+
+extern(C++) class C
+{
+ invariant { assert(0); }
+ void f() {}
+}
+
+extern(D) class D
+{
+ invariant { assert(0); }
+ void f() {}
+}
+
+void test20924()
+{
+ import core.exception : AssertError;
+ // Test extern(C++) class invariant
+ try
+ {
+ auto c = new C();
+ c.f(); // Trigger invariant
+ assert(false, "Failed: invariant in extern(C++) class not checked");
+ }
+ catch (AssertError e)
+ {
+ // Expected behavior - invariant was checked
+ return;
+ }
+ assert(0, "Invariant in extern(C++) class was not checked");
+
+ // Test extern(D) class invariant
+ try
+ {
+ auto d = new D();
+ d.f(); // Trigger invariant
+ assert(false, "Failed: invariant in extern(D) class not checked");
+ }
+ catch (AssertError e)
+ {
+ // Expected behavior - invariant was checked
+ return;
+ }
+ assert(0, "Invariant in extern(D) class was not checked");
+}
void main()
{
@@ -238,4 +282,5 @@ void main()
test16384();
test13113();
test13147();
+ test20924();
}
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 840f8dd4f9d9..62d90e5770b5 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-09ed02ce56ea5bf3e59f21ee0390cd85eb8bfaa7
+1017635a9636ef6a7a4bda35b1e091875d829871
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4c8d65b76f5f..0e9b71bfa5d2 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -297,8 +297,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/sys/mman.d core/sys/linux/sys/mount.d \
core/sys/linux/sys/prctl.d core/sys/linux/sys/procfs.d \
core/sys/linux/sys/signalfd.d core/sys/linux/sys/socket.d \
- core/sys/linux/sys/sysinfo.d core/sys/linux/sys/time.d \
- core/sys/linux/sys/xattr.d core/sys/linux/termios.d \
+ core/sys/linux/sys/syscall.d core/sys/linux/sys/sysinfo.d \
+ core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \
+ core/sys/linux/syscall.d core/sys/linux/termios.d \
core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \
core/sys/linux/uinput.d core/sys/linux/unistd.d
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index a6bbb76c216b..8543c6e53edc 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -385,8 +385,9 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
core/sys/linux/sys/mman.lo core/sys/linux/sys/mount.lo \
core/sys/linux/sys/prctl.lo core/sys/linux/sys/procfs.lo \
core/sys/linux/sys/signalfd.lo core/sys/linux/sys/socket.lo \
- core/sys/linux/sys/sysinfo.lo core/sys/linux/sys/time.lo \
- core/sys/linux/sys/xattr.lo core/sys/linux/termios.lo \
+ core/sys/linux/sys/syscall.lo core/sys/linux/sys/sysinfo.lo \
+ core/sys/linux/sys/time.lo core/sys/linux/sys/xattr.lo \
+ core/sys/linux/syscall.lo core/sys/linux/termios.lo \
core/sys/linux/time.lo core/sys/linux/timerfd.lo \
core/sys/linux/tipc.lo core/sys/linux/uinput.lo \
core/sys/linux/unistd.lo
@@ -981,8 +982,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/sys/mman.d core/sys/linux/sys/mount.d \
core/sys/linux/sys/prctl.d core/sys/linux/sys/procfs.d \
core/sys/linux/sys/signalfd.d core/sys/linux/sys/socket.d \
- core/sys/linux/sys/sysinfo.d core/sys/linux/sys/time.d \
- core/sys/linux/sys/xattr.d core/sys/linux/termios.d \
+ core/sys/linux/sys/syscall.d core/sys/linux/sys/sysinfo.d \
+ core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \
+ core/sys/linux/syscall.d core/sys/linux/termios.d \
core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \
core/sys/linux/uinput.d core/sys/linux/unistd.d
@@ -1756,9 +1758,11 @@ core/sys/linux/sys/prctl.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/procfs.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/signalfd.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/socket.lo: core/sys/linux/sys/$(am__dirstamp)
+core/sys/linux/sys/syscall.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/sysinfo.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/time.lo: core/sys/linux/sys/$(am__dirstamp)
core/sys/linux/sys/xattr.lo: core/sys/linux/sys/$(am__dirstamp)
+core/sys/linux/syscall.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/termios.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/time.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/timerfd.lo: core/sys/linux/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
index 27c8b99d2cbf..b1247891e69c 100644
--- a/libphobos/libdruntime/core/int128.d
+++ b/libphobos/libdruntime/core/int128.d
@@ -36,6 +36,12 @@ else
else private enum Cent_alignment = (size_t.sizeof * 2);
}
+version (X86_64)
+{
+ version (GNU) version = GNU_OR_LDC_X86_64;
+ version (LDC) version = GNU_OR_LDC_X86_64;
+}
+
/**
* 128 bit integer type.
* See_also: $(REF Int128, std,int128).
@@ -189,10 +195,8 @@ Cent sar1(Cent c)
*/
pure
Cent shl(Cent c, uint n)
+in (n < Ubits * 2)
{
- if (n >= Ubits * 2)
- return Zero;
-
if (n >= Ubits)
{
c.hi = c.lo << (n - Ubits);
@@ -216,10 +220,8 @@ Cent shl(Cent c, uint n)
*/
pure
Cent shr(Cent c, uint n)
+in (n < Ubits * 2)
{
- if (n >= Ubits * 2)
- return Zero;
-
if (n >= Ubits)
{
c.lo = c.hi >> (n - Ubits);
@@ -243,18 +245,13 @@ Cent shr(Cent c, uint n)
*/
pure
Cent sar(Cent c, uint n)
+in (n < Ubits * 2)
{
const signmask = -(c.hi >> (Ubits - 1));
const signshift = (Ubits * 2) - n;
c = shr(c, n);
- // Sign extend all bits beyond the precision of Cent.
- if (n >= Ubits * 2)
- {
- c.hi = signmask;
- c.lo = signmask;
- }
- else if (signshift >= Ubits * 2)
+ if (signshift == Ubits * 2)
{
}
else if (signshift >= Ubits)
@@ -317,6 +314,8 @@ pure
Cent rol(Cent c, uint n)
{
n &= Ubits * 2 - 1;
+ if (n == 0)
+ return c;
Cent l = shl(c, n);
Cent r = shr(c, Ubits * 2 - n);
return or(l, r);
@@ -334,6 +333,8 @@ pure
Cent ror(Cent c, uint n)
{
n &= Ubits * 2 - 1;
+ if (n == 0)
+ return c;
Cent r = shr(c, n);
Cent l = shl(c, Ubits * 2 - n);
return or(r, l);
@@ -458,6 +459,55 @@ Cent mul(Cent c1, Cent c2)
return ret;
}
+/****************************
+ * Multiply 64-bit operands u1 * u2 in 128-bit precision.
+ * Params:
+ * u1 = operand 1
+ * u2 = operand 2
+ * Returns:
+ * u1 * u2 in 128-bit precision
+ */
+pure
+Cent mul(ulong u1, ulong u2)
+{
+ if (!__ctfe)
+ {
+ version (GNU_OR_LDC_X86_64)
+ {
+ Cent ret = void;
+ asm pure @trusted nothrow @nogc
+ {
+ "mulq %3"
+ : "=a"(ret.lo), "=d"(ret.hi)
+ : "a"(u1), "r"(u2)
+ : "cc";
+ }
+ return ret;
+ }
+ else version (D_InlineAsm_X86_64)
+ {
+ U lo = void;
+ U hi = void;
+ asm pure @trusted nothrow @nogc
+ {
+ mov RAX, u1;
+ mul u2;
+ mov lo, RAX;
+ mov hi, RDX;
+ }
+ return Cent(lo: lo, hi: hi);
+ }
+ }
+
+ return mul(Cent(lo: u1), Cent(lo: u2));
+}
+
+unittest
+{
+ assert(mul(3, 42) == Cent(lo: 126));
+ assert(mul(1L << 60, 1 << 10) == Cent(hi: 1 << 6));
+}
+
/****************************
* Unsigned divide c1 / c2.
@@ -490,63 +540,6 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
// Based on "Unsigned Doubleword Division" in Hacker's Delight
import core.bitop;
- // Divides a 128-bit dividend by a 64-bit divisor.
- // The result must fit in 64 bits.
- static U udivmod128_64(Cent c1, U c2, out U modulus)
- {
- // We work in base 2^^32
- enum base = 1UL << 32;
- enum divmask = (1UL << (Ubits / 2)) - 1;
- enum divshift = Ubits / 2;
-
- // Check for overflow and divide by 0
- if (c1.hi >= c2)
- {
- modulus = 0UL;
- return ~0UL;
- }
-
- // Computes [num1 num0] / den
- static uint udiv96_64(U num1, uint num0, U den)
- {
- // Extract both digits of the denominator
- const den1 = cast(uint)(den >> divshift);
- const den0 = cast(uint)(den & divmask);
- // Estimate ret as num1 / den1, and then correct it
- U ret = num1 / den1;
- const t2 = (num1 % den1) * base + num0;
- const t1 = ret * den0;
- if (t1 > t2)
- ret -= (t1 - t2 > den) ? 2 : 1;
- return cast(uint)ret;
- }
-
- // Determine the normalization factor. We multiply c2 by this, so that its leading
- // digit is at least half base. In binary this means just shifting left by the number
- // of leading zeros, so that there's a 1 in the MSB.
- // We also shift number by the same amount. This cannot overflow because c1.hi < c2.
- const shift = (Ubits - 1) - bsr(c2);
- c2 <<= shift;
- U num2 = c1.hi;
- num2 <<= shift;
- num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63);
- c1.lo <<= shift;
-
- // Extract the low digits of the numerator (after normalizing)
- const num1 = cast(uint)(c1.lo >> divshift);
- const num0 = cast(uint)(c1.lo & divmask);
-
- // Compute q1 = [num2 num1] / c2
- const q1 = udiv96_64(num2, num1, c2);
- // Compute the true (partial) remainder
- const rem = num2 * base + num1 - q1 * c2;
- // Compute q0 = [rem num0] / c2
- const q0 = udiv96_64(rem, num0, c2);
-
- modulus = (rem * base + num0 - q0 * c2) >> shift;
- return (cast(U)q1 << divshift) | q0;
- }
-
// Special cases
if (!tst(c2))
{
@@ -576,7 +569,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
if (q1)
c1.hi = c1.hi % c2.lo;
Cent rem;
- const q0 = udivmod128_64(c1, c2.lo, rem.lo);
+ const q0 = udivmod(c1, c2.lo, rem.lo);
modulus = rem;
const Cent ret = { lo:q0, hi:q1 };
return ret;
@@ -597,7 +590,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
// Get quotient from divide unsigned operation.
U rem_ignored;
- const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) };
+ const Cent q1 = { lo:udivmod(u1, v1, rem_ignored) };
// Undo normalization and division of c1 by 2.
Cent quotient = shr(shl(q1, shift), 63);
@@ -624,6 +617,107 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
return quotient;
}
+/****************************
+ * Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits.
+ * The remainder after division is stored to modulus.
+ * Params:
+ * c1 = dividend
+ * c2 = divisor
+ * modulus = set to c1 % c2
+ * Returns:
+ * quotient c1 / c2
+ */
+pure
+U udivmod(Cent c1, U c2, out U modulus)
+{
+ import core.bitop;
+
+ if (!__ctfe)
+ {
+ version (GNU_OR_LDC_X86_64)
+ {
+ U ret = void;
+ asm pure @trusted nothrow @nogc
+ {
+ "divq %4"
+ : "=a"(ret), "=d"(modulus)
+ : "a"(c1.lo), "d"(c1.hi), "r"(c2)
+ : "cc";
+ }
+ return ret;
+ }
+ else version (D_InlineAsm_X86_64)
+ {
+ const lo = c1.lo;
+ const hi = c1.hi;
+ U mod = void;
+ U ret = void;
+ asm pure @trusted nothrow @nogc
+ {
+ mov RAX, lo;
+ mov RDX, hi;
+ div c2;
+ mov mod, RDX; // DMD bug: cannot use modulus directly
+ mov ret, RAX;
+ }
+ modulus = mod;
+ return ret;
+ }
+ }
+
+ // We work in base 2^^32
+ enum base = 1UL << 32;
+ enum divmask = (1UL << (Ubits / 2)) - 1;
+ enum divshift = Ubits / 2;
+
+ // Check for overflow and divide by 0
+ if (c1.hi >= c2)
+ {
+ modulus = 0UL;
+ return ~0UL;
+ }
+
+ // Computes [num1 num0] / den
+ static uint udiv96_64(U num1, uint num0, U den)
+ {
+ // Extract both digits of the denominator
+ const den1 = cast(uint)(den >> divshift);
+ const den0 = cast(uint)(den & divmask);
+ // Estimate ret as num1 / den1, and then correct it
+ U ret = num1 / den1;
+ const t2 = (num1 % den1) * base + num0;
+ const t1 = ret * den0;
+ if (t1 > t2)
+ ret -= (t1 - t2 > den) ? 2 : 1;
+ return cast(uint)ret;
+ }
+
+ // Determine the normalization factor. We multiply c2 by this, so that its leading
+ // digit is at least half base. In binary this means just shifting left by the number
+ // of leading zeros, so that there's a 1 in the MSB.
+ // We also shift number by the same amount. This cannot overflow because c1.hi < c2.
+ const shift = (Ubits - 1) - bsr(c2);
+ c2 <<= shift;
+ U num2 = c1.hi;
+ num2 <<= shift;
+ num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63);
+ c1.lo <<= shift;
+
+ // Extract the low digits of the numerator (after normalizing)
+ const num1 = cast(uint)(c1.lo >> divshift);
+ const num0 = cast(uint)(c1.lo & divmask);
+
+ // Compute q1 = [num2 num1] / c2
+ const q1 = udiv96_64(num2, num1, c2);
+ // Compute the true (partial) remainder
+ const rem = num2 * base + num1 - q1 * c2;
+ // Compute q0 = [rem num0] / c2
+ const q0 = udiv96_64(rem, num0, c2);
+
+ modulus = (rem * base + num0 - q0 * c2) >> shift;
+ return (cast(U)q1 << divshift) | q0;
+}
+
/****************************
* Signed divide c1 / c2.
@@ -893,18 +987,14 @@ unittest
assert(shl(C10,0) == C10);
assert(shl(C10,Ubits) == C10_0);
assert(shl(C10,1) == C20);
- assert(shl(C10,Ubits * 2) == C0);
assert(shr(C10_0,0) == C10_0);
assert(shr(C10_0,Ubits) == C10);
assert(shr(C10_0,Ubits - 1) == C20);
assert(shr(C10_0,Ubits + 1) == C5);
- assert(shr(C10_0,Ubits * 2) == C0);
assert(sar(C10_0,0) == C10_0);
assert(sar(C10_0,Ubits) == C10);
assert(sar(C10_0,Ubits - 1) == C20);
assert(sar(C10_0,Ubits + 1) == C5);
- assert(sar(C10_0,Ubits * 2) == C0);
- assert(sar(Cm1,Ubits * 2) == Cm1);
assert(shl1(C10) == C20);
assert(shr1(C10_0) == C5_0);
@@ -916,7 +1006,6 @@ unittest
assert(udiv(C10,C2) == C5);
assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0);
assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1);
- assert(udivmod(C10,C0, modulus) == Cm1); assert(modulus == C0);
assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2);
assert(udiv(mul(C90_30, C2), C2) == C90_30);
assert(udiv(mul(C90_30, C2), C90_30) == C2);
@@ -961,4 +1050,6 @@ unittest
assert(rol(ror(C7_9, 5), 5) == C7_9);
assert(rol(C7_9, 1) == rol1(C7_9));
assert(ror(C7_9, 1) == ror1(C7_9));
+ assert(rol(C7_9, 0) == C7_9);
+ assert(ror(C7_9, 0) == C7_9);
}
diff --git a/libphobos/libdruntime/core/internal/array/capacity.d b/libphobos/libdruntime/core/internal/array/capacity.d
index 10ce2c65c958..11bd357d7c27 100644
--- a/libphobos/libdruntime/core/internal/array/capacity.d
+++ b/libphobos/libdruntime/core/internal/array/capacity.d
@@ -9,64 +9,314 @@
*/
module core.internal.array.capacity;
-// HACK: `nothrow` and `pure` is faked.
-private extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure;
-private extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure;
-
-/*
- * This template is needed because there need to be a `_d_arraysetlengthTTrace!Tarr` instance for every
- * `_d_arraysetlengthT!Tarr`. By wrapping both of these functions inside of this template we force the
- * compiler to create a instance of both function for every type that is used.
- */
-
-/// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace`
-template _d_arraysetlengthTImpl(Tarr : T[], T)
+debug (PRINTF) import core.stdc.stdio : printf;
+debug (VALGRIND) import etc.valgrind.valgrind;
+
+// for now, all GC array functions are not exposed via core.memory.
+extern(C) {
+ bool gc_expandArrayUsed(void[] slice, size_t newUsed, bool atomic) nothrow pure;
+ size_t gc_reserveArrayCapacity(void[] slice, size_t request, bool atomic) nothrow pure;
+ bool gc_shrinkArrayUsed(void[] slice, size_t existingUsed, bool atomic) nothrow pure;
+}
+/**
+Set the array capacity.
+
+If the array capacity isn't currently large enough
+to hold the requested capacity (in number of elements), then the array is
+resized/reallocated to the appropriate size.
+
+Pass in a requested capacity of 0 to get the current capacity.
+
+Params:
+ T = the type of the elements in the array (this should be unqualified)
+ newcapacity = requested new capacity
+ p = pointer to array to set. Its `length` is left unchanged.
+ isshared = true if the underlying data is shared
+
+Returns: the number of elements that can actually be stored once the resizing is done
+*/
+size_t _d_arraysetcapacityPureNothrow(T)(size_t newcapacity, void[]* p, bool isshared) pure nothrow @trusted
+do
+{
+ alias PureNothrowType = size_t function(size_t, void[]*, bool) pure nothrow @trusted;
+ return (cast(PureNothrowType) &_d_arraysetcapacity!T)(newcapacity, p, isshared);
+}
+
+size_t _d_arraysetcapacity(T)(size_t newcapacity, void[]* p, bool isshared) @trusted
+in
+{
+ assert(!(*p).length || (*p).ptr);
+}
+do
+{
+ import core.checkedint : mulu;
+ import core.exception : onOutOfMemoryError;
+ import core.stdc.string : memcpy, memset;
+ import core.internal.array.utils: __typeAttrs;
+ import core.internal.lifetime : __doPostblit;
+
+ import core.memory : GC;
+
+ alias BlkAttr = GC.BlkAttr;
+
+ auto size = T.sizeof;
+ bool overflow = false;
+ const reqsize = mulu(size, newcapacity, overflow);
+ if (overflow)
+ {
+ onOutOfMemoryError();
+ assert(0);
+ }
+
+ // step 1, see if we can ensure the capacity is valid in-place
+ auto datasize = (*p).length * size;
+ auto curCapacity = gc_reserveArrayCapacity((*p).ptr[0 .. datasize], reqsize, isshared);
+ if (curCapacity != 0) // in-place worked!
+ return curCapacity / size;
+
+ if (reqsize <= datasize) // requested size is less than array size, the current array satisfies
+ // the request. But this is not an appendable GC array, so return 0.
+ return 0;
+
+ // step 2, if reserving in-place doesn't work, allocate a new array with at
+ // least the requested allocated size.
+ auto attrs = __typeAttrs!T((*p).ptr) | BlkAttr.APPENDABLE;
+
+ // use this static enum to avoid recomputing TypeInfo for every call.
+ static enum ti = typeid(T);
+ auto ptr = GC.malloc(reqsize, attrs, ti);
+ if (ptr is null)
+ {
+ onOutOfMemoryError();
+ assert(0);
+ }
+
+ // copy the data over.
+ // note that malloc will have initialized the data we did not request to 0.
+ memcpy(ptr, (*p).ptr, datasize);
+
+ // handle postblit
+ __doPostblit!T(cast(T[])ptr[0 .. datasize]);
+
+ if (!(attrs & BlkAttr.NO_SCAN))
+ {
+ // need to memset the newly requested data, except for the data that
+ // malloc returned that we didn't request.
+ void* endptr = ptr + reqsize;
+ void* begptr = ptr + datasize;
+
+ // sanity check
+ assert(endptr >= begptr);
+ memset(begptr, 0, endptr - begptr);
+ }
+
+ *p = ptr[0 .. (*p).length];
+
+ // set up the correct length. Note that we need to do this here, because
+ // the GC malloc will automatically set the used size to what we requested.
+ gc_shrinkArrayUsed(ptr[0 .. datasize], reqsize, isshared);
+
+ curCapacity = gc_reserveArrayCapacity(ptr[0 .. datasize], 0, isshared);
+ assert(curCapacity);
+ return curCapacity / size;
+}
+
+/**
+Resize a dynamic array by setting its `.length` property.
+
+Newly created elements are initialized based on their default value.
+If the array's elements initialize to `0`, memory is zeroed out. Otherwise, elements are explicitly initialized.
+
+This function handles memory allocation, expansion, and initialization while maintaining array integrity.
+
+---
+void main()
+{
+ int[] a = [1, 2];
+ a.length = 3; // Gets lowered to `_d_arraysetlengthT!(int)(a, 3, false)`
+}
+---
+
+Params:
+ arr = The array to resize.
+ newlength = The new value for the array's `.length`.
+
+Returns:
+ The resized array with updated length and properly initialized elements.
+
+Throws:
+ OutOfMemoryError if allocation fails.
+*/
+size_t _d_arraysetlengthT(Tarr : T[], T)(return ref scope Tarr arr, size_t newlength) @trusted
+{
+ import core.internal.traits : Unqual;
+
+ // Check if the type is shared
+ enum isShared = is(T == shared);
+
+ // Unqualify the type to remove `const`, `immutable`, `shared`, etc.
+ alias UnqT = Unqual!T;
+
+ // Cast the array to the unqualified type
+ auto unqual_arr = cast(UnqT[]) arr;
+
+ // Call the implementation with the unqualified array and sharedness flag
+ size_t result = _d_arraysetlengthT_(unqual_arr, newlength, isShared);
+
+ arr = cast(Tarr) unqual_arr;
+ // Return the result
+ return result;
+}
+
+private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, size_t newlength, bool isShared) @trusted
{
- private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!";
-
- /**
- * Resize dynamic array
- * Params:
- * arr = the array that will be resized, taken as a reference
- * newlength = new length of array
- * Returns:
- * The new length of the array
- * Bugs:
- * The safety level of this function is faked. It shows itself as `@trusted pure nothrow` to not break existing code.
- */
- size_t _d_arraysetlengthT(return scope ref Tarr arr, size_t newlength) @trusted pure nothrow
+ import core.checkedint : mulu;
+ import core.exception : onFinalizeError, onOutOfMemoryError;
+ import core.stdc.string : memcpy, memset;
+ import core.internal.traits : hasElaborateCopyConstructor, Unqual;
+ import core.lifetime : emplace;
+ import core.memory;
+ import core.internal.lifetime : __doPostblit;
+
+ alias BlkAttr = GC.BlkAttr;
+ alias UnqT = Unqual!T;
+
+ debug(PRINTF)
+ {
+ printf("_d_arraysetlengthT(arr.ptr = %p, arr.length = %zd, newlength = %zd)\n",
+ arr.ptr, arr.length, newlength);
+ }
+
+ // If the new length is less than or equal to the current length, just truncate the array
+ if (newlength <= arr.length)
+ {
+ arr = arr[0 .. newlength];
+ return newlength;
+ }
+
+ enum sizeelem = T.sizeof;
+ enum hasPostblit = __traits(hasMember, T, "__postblit");
+ enum hasEnabledPostblit = hasPostblit && !__traits(isDisabled, T.__postblit);
+
+ bool overflow = false;
+ const newsize = mulu(sizeelem, newlength, overflow);
+ if (overflow)
{
- version (DigitalMars) pragma(inline, false);
- version (D_TypeInfo)
+ onOutOfMemoryError();
+ assert(0);
+ }
+
+ debug(PRINTF) printf("newsize = %zx\n", newsize);
+
+ uint gcAttrs = BlkAttr.APPENDABLE;
+ static if (is(T == struct) && __traits(hasMember, T, "xdtor"))
+ {
+ gcAttrs |= BlkAttr.FINALIZE;
+ }
+
+ if (!arr.ptr)
+ {
+ assert(arr.length == 0);
+ void* ptr = GC.malloc(newsize, gcAttrs);
+ if (!ptr)
+ {
+ onOutOfMemoryError();
+ assert(0);
+ }
+
+ static if (__traits(isZeroInit, T))
+ {
+ memset(ptr, 0, newsize);
+ }
+ else static if (hasElaborateCopyConstructor!T && !hasPostblit)
{
- auto ti = typeid(Tarr);
+ foreach (i; 0 .. newlength)
+ emplace(cast(UnqT*) ptr + i, UnqT.init); // safe default construction
+ }
+ else
+ {
+ auto temp = UnqT.init;
+ foreach (i; 0 .. newlength)
+ memcpy(cast(UnqT*) ptr + i, cast(const void*)&temp, T.sizeof);
+
+ static if (hasEnabledPostblit)
+ __doPostblit!T((cast(T*) ptr)[0 .. newlength]);
+ }
+
+ arr = (cast(T*) ptr)[0 .. newlength];
+ return newlength;
+ }
- static if (__traits(isZeroInit, T))
- ._d_arraysetlengthT(ti, newlength, cast(void[]*)&arr);
- else
- ._d_arraysetlengthiT(ti, newlength, cast(void[]*)&arr);
+ size_t oldsize = arr.length * sizeelem;
- return arr.length;
+ auto newdata = cast(void*) arr.ptr;
+
+ if (!gc_expandArrayUsed(newdata[0 .. oldsize], newsize, isShared))
+ {
+ newdata = GC.malloc(newsize, gcAttrs);
+ if (!newdata)
+ {
+ onOutOfMemoryError();
+ assert(0);
+ }
+ static if (hasElaborateCopyConstructor!T && !hasPostblit)
+ {
+ // Use emplace for types with copy constructors but not postblit
+ foreach (i; 0 .. arr.length)
+ emplace(cast(UnqT*)newdata + i, arr[i]); // safe copy
}
else
- assert(0, errorMessage);
+ {
+ memcpy(newdata, cast(const(void)*)arr.ptr, oldsize);
+
+ // Postblit handling for types with postblit, but ensure it compiles
+ static if (hasEnabledPostblit)
+ __doPostblit!T((cast(T*) (cast(ubyte*)newdata))[0 .. arr.length]);
+ }
+ }
+
+ // Handle initialization based on whether the type requires zero-init
+ static if (__traits(isZeroInit, T))
+ memset(cast(void*) (cast(ubyte*)newdata + oldsize), 0, newsize - oldsize);
+ else static if (hasElaborateCopyConstructor!T && !hasPostblit)
+ {
+ foreach (i; 0 .. newlength - arr.length)
+ emplace(cast(UnqT*) (cast(ubyte*)newdata + oldsize) + i, UnqT.init);
+ }
+ else
+ {
+ auto temp = UnqT.init;
+ foreach (i; 0 .. newlength - arr.length)
+ memcpy(cast(UnqT*) (cast(ubyte*)newdata + oldsize) + i, cast(const void*)&temp, T.sizeof);
+
+ static if (hasEnabledPostblit)
+ __doPostblit!T((cast(T*) (cast(ubyte*)newdata + oldsize))[0 .. newlength - arr.length]);
}
- version (D_ProfileGC)
+ arr = (cast(T*) newdata)[0 .. newlength];
+ return newlength;
+}
+
+version (D_ProfileGC)
+{
+ enum errorMessage = "Cannot resize arrays";
+ import core.internal.array.utils : _d_HookTraceImpl;
+
+ // Function wrapper around the hook, so it’s callable
+ size_t _d_arraysetlengthTTrace(Tarr : T[], T)(
+ return ref scope Tarr arr,
+ size_t newlength,
+ string file = __FILE__,
+ int line = __LINE__,
+ string func = __FUNCTION__
+ ) @trusted
{
- import core.internal.array.utils : _d_HookTraceImpl;
-
- /**
- * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity).
- * Bugs:
- * This function template was ported from a much older runtime hook that bypassed safety,
- * purity, and throwabilty checks. To prevent breaking existing code, this function template
- * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
- */
- alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage);
+ alias Hook = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT!Tarr, errorMessage);
+ return Hook(arr, newlength, file, line, func);
}
}
+// @safe unittest remains intact
@safe unittest
{
struct S
@@ -75,13 +325,13 @@ template _d_arraysetlengthTImpl(Tarr : T[], T)
}
int[] arr;
- _d_arraysetlengthTImpl!(typeof(arr))._d_arraysetlengthT(arr, 16);
+ _d_arraysetlengthT!(typeof(arr))(arr, 16);
assert(arr.length == 16);
foreach (int i; arr)
assert(i == int.init);
shared S[] arr2;
- _d_arraysetlengthTImpl!(typeof(arr2))._d_arraysetlengthT(arr2, 16);
+ _d_arraysetlengthT!(typeof(arr2))(arr2, 16);
assert(arr2.length == 16);
foreach (s; arr2)
assert(s == S.init);
diff --git a/libphobos/libdruntime/core/internal/array/concatenation.d b/libphobos/libdruntime/core/internal/array/concatenation.d
index 13ec5fad40fd..fab2a5a9b7c1 100644
--- a/libphobos/libdruntime/core/internal/array/concatenation.d
+++ b/libphobos/libdruntime/core/internal/array/concatenation.d
@@ -19,7 +19,8 @@ module core.internal.array.concatenation;
*/
Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
{
- import core.internal.array.capacity : _d_arraysetlengthTImpl;
+ import core.exception : onOutOfMemoryError;
+ import core.internal.array.utils : __arrayAlloc;
import core.internal.traits : hasElaborateCopyConstructor, Unqual;
import core.lifetime : copyEmplace;
import core.stdc.string : memcpy;
@@ -27,37 +28,27 @@ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
Tret res;
size_t totalLen;
- alias T = typeof(res[0]);
- enum elemSize = T.sizeof;
- enum hasPostblit = __traits(hasPostblit, T);
+ alias T = typeof(res[0]); // Element type of the result array
+ alias UnqT = Unqual!T; // Unqualified version of T (strips const/immutable)
+ enum elemSize = T.sizeof; // Size of each element
+ enum hasPostblit = __traits(hasPostblit, T); // Whether T has a postblit constructor
+ // Compute total length of the resulting array
static foreach (from; froms)
- static if (is (typeof(from) : T))
- totalLen++;
+ static if (is(typeof(from) : T))
+ totalLen++; // Single element contributes one to length
else
- totalLen += from.length;
+ totalLen += from.length; // Arrays contribute their full length
if (totalLen == 0)
- return res;
+ return res; // Return an empty array if no elements are present
- // We cannot use this, because it refuses to work if the array type has disabled default construction.
- // res.length = totalLen;
- // Call the runtime function directly instead.
- // TODO: once `__arrayAlloc` is templated, call that instead.
- version (D_ProfileGC)
- {
- // TODO: forward file, line, name from _d_arraycatnTXTrace
- _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace(
- res, totalLen, __FILE__, __LINE__, __FUNCTION__);
- }
- else
- {
- _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen);
- }
+ // Allocate memory for mutable arrays using __arrayAlloc
+ res = cast(Tret) __arrayAlloc!(UnqT)(elemSize * totalLen);
+
+ if (res.ptr is null)
+ onOutOfMemoryError(); // Abort if allocation fails
- /* Currently, if both a postblit and a cpctor are defined, the postblit is
- * used. If this changes, the condition below will have to be adapted.
- */
static if (hasElaborateCopyConstructor!T && !hasPostblit)
{
size_t i = 0;
@@ -73,16 +64,16 @@ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
}
else
{
- auto resptr = cast(Unqual!T *) res;
+ auto resptr = cast(UnqT *) res;
foreach (ref from; froms)
static if (is (typeof(from) : T))
- memcpy(resptr++, cast(Unqual!T *) &from, elemSize);
+ memcpy(resptr++, cast(UnqT *) &from, elemSize);
else
{
const len = from.length;
if (len)
{
- memcpy(resptr, cast(Unqual!T *) from, len * elemSize);
+ memcpy(resptr, cast(UnqT *) from, len * elemSize);
resptr += len;
}
}
diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d
index 40e5a61bbded..76811ef3ffd0 100644
--- a/libphobos/libdruntime/core/internal/array/construction.d
+++ b/libphobos/libdruntime/core/internal/array/construction.d
@@ -505,7 +505,7 @@ version (D_ProfileGC)
* Returns:
* newly allocated array
*/
-Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted
+Tarr _d_newarraymTX(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false) @trusted
{
debug(PRINTF) printf("_d_newarraymTX(dims.length = %zd)\n", dims.length);
@@ -520,7 +520,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
auto dim = dims[0];
- debug(PRINTF) printf("__allocateInnerArray(UnqT = %s, dim = %lu, ndims = %lu\n", UnqT.stringof.ptr, dim, dims.length);
+ debug(PRINTF) printf("__allocateInnerArray(UnqT = %s, dim = %u, ndims = %u)\n", UnqT.stringof.ptr, cast(uint)dim, cast(uint)dims.length);
if (dims.length == 1)
{
auto r = _d_newarrayT!UnqT(dim, isShared);
@@ -602,7 +602,7 @@ version (D_ProfileGC)
/**
* TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction).
*/
- Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted
+ Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted
{
version (D_TypeInfo)
{
diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d
index deaae3f95da6..1d105e6ebf19 100644
--- a/libphobos/libdruntime/core/internal/array/utils.d
+++ b/libphobos/libdruntime/core/internal/array/utils.d
@@ -156,3 +156,28 @@ void[] __arrayAlloc(T)(size_t arrSize) @trusted
return ptr[0 .. arrSize];
return null;
}
+
+uint __typeAttrs(T)(void *copyAttrsFrom = null)
+{
+ import core.internal.traits : hasIndirections, hasElaborateDestructor;
+ import core.memory : GC;
+
+ alias BlkAttr = GC.BlkAttr;
+
+ if (copyAttrsFrom)
+ {
+ // try to copy attrs from the given block
+ auto info = GC.query(copyAttrsFrom);
+ if (info.base)
+ return info.attr;
+ }
+
+ uint attrs = 0;
+ static if (!hasIndirections!T)
+ attrs |= BlkAttr.NO_SCAN;
+
+ static if (is(T == struct) && hasElaborateDestructor!T)
+ attrs |= BlkAttr.FINALIZE;
+
+ return attrs;
+}
diff --git a/libphobos/libdruntime/core/internal/lifetime.d b/libphobos/libdruntime/core/internal/lifetime.d
index a7446debae65..fd78de221d11 100644
--- a/libphobos/libdruntime/core/internal/lifetime.d
+++ b/libphobos/libdruntime/core/internal/lifetime.d
@@ -202,3 +202,22 @@ void swap(T)(ref T lhs, ref T rhs)
moveEmplace(rhs, lhs);
moveEmplace(tmp, rhs);
}
+
+void __doPostblit(T)(T[] arr)
+{
+ // infer static postblit type, run postblit if any
+ static if (__traits(hasPostblit, T))
+ {
+ static if (__traits(isStaticArray, T) && is(T : E[], E))
+ __doPostblit(cast(E[]) arr);
+ else static if (!__traits(compiles, arr[0].__xpostblit))
+ {
+ alias Unqual_T = Unqual!T;
+ foreach (ref elem; (() @trusted => cast(Unqual_T[]) arr)())
+ elem.__xpostblit();
+ }
+ else
+ foreach (ref elem; arr)
+ elem.__xpostblit();
+ }
+}
diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d
index ce77d5c1e6b2..7d42d5c8c023 100644
--- a/libphobos/libdruntime/core/stdc/fenv.d
+++ b/libphobos/libdruntime/core/stdc/fenv.d
@@ -440,6 +440,11 @@ else version (CRuntime_Musl)
}
alias uint fexcept_t;
}
+ else version (RICV64)
+ {
+ alias uint fenv_t;
+ alias uint fexcept_t;
+ }
else
{
static assert(false, "Architecture not supported.");
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 1f384f9cbd46..5b78d6f61f36 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -1509,51 +1509,51 @@ extern (D)
{
//int isgreater(real-floating x, real-floating y);
///
- pure int isgreater(float x, float y) { return x > y; }
+ pure int isgreater()(float x, float y) { return x > y; }
///
- pure int isgreater(double x, double y) { return x > y; }
+ pure int isgreater()(double x, double y) { return x > y; }
///
- pure int isgreater(real x, real y) { return x > y; }
+ pure int isgreater()(real x, real y) { return x > y; }
//int isgreaterequal(real-floating x, real-floating y);
///
- pure int isgreaterequal(float x, float y) { return x >= y; }
+ pure int isgreaterequal()(float x, float y) { return x >= y; }
///
- pure int isgreaterequal(double x, double y) { return x >= y; }
+ pure int isgreaterequal()(double x, double y) { return x >= y; }
///
- pure int isgreaterequal(real x, real y) { return x >= y; }
+ pure int isgreaterequal()(real x, real y) { return x >= y; }
//int isless(real-floating x, real-floating y);
///
- pure int isless(float x, float y) { return x < y; }
+ pure int isless()(float x, float y) { return x < y; }
///
- pure int isless(double x, double y) { return x < y; }
+ pure int isless()(double x, double y) { return x < y; }
///
- pure int isless(real x, real y) { return x < y; }
+ pure int isless()(real x, real y) { return x < y; }
//int islessequal(real-floating x, real-floating y);
///
- pure int islessequal(float x, float y) { return x <= y; }
+ pure int islessequal()(float x, float y) { return x <= y; }
///
- pure int islessequal(double x, double y) { return x <= y; }
+ pure int islessequal()(double x, double y) { return x <= y; }
///
- pure int islessequal(real x, real y) { return x <= y; }
+ pure int islessequal()(real x, real y) { return x <= y; }
//int islessgreater(real-floating x, real-floating y);
///
- pure int islessgreater(float x, float y) { return x != y && !isunordered(x, y); }
+ pure int islessgreater()(float x, float y) { return x != y && !isunordered(x, y); }
///
- pure int islessgreater(double x, double y) { return x != y && !isunordered(x, y); }
+ pure int islessgreater()(double x, double y) { return x != y && !isunordered(x, y); }
///
- pure int islessgreater(real x, real y) { return x != y && !isunordered(x, y); }
+ pure int islessgreater()(real x, real y) { return x != y && !isunordered(x, y); }
//int isunordered(real-floating x, real-floating y);
///
- pure int isunordered(float x, float y) { return isnan(x) || isnan(y); }
+ pure int isunordered()(float x, float y) { return isnan(x) || isnan(y); }
///
- pure int isunordered(double x, double y) { return isnan(x) || isnan(y); }
+ pure int isunordered()(double x, double y) { return isnan(x) || isnan(y); }
///
- pure int isunordered(real x, real y) { return isnan(x) || isnan(y); }
+ pure int isunordered()(real x, real y) { return isnan(x) || isnan(y); }
}
/* MS define some functions inline.
diff --git a/libphobos/libdruntime/core/stdc/stdarg.d b/libphobos/libdruntime/core/stdc/stdarg.d
index 0ba1ebe34e38..c694dfb3ac3f 100644
--- a/libphobos/libdruntime/core/stdc/stdarg.d
+++ b/libphobos/libdruntime/core/stdc/stdarg.d
@@ -316,7 +316,7 @@ else version (LDC)
}
else version (DigitalMars)
{
- void va_end(va_list ap) {}
+ void va_end()(va_list ap) {}
}
diff --git a/libphobos/libdruntime/core/sys/bionic/err.d b/libphobos/libdruntime/core/sys/bionic/err.d
index e2756e10c91b..a14f21bb1ec1 100644
--- a/libphobos/libdruntime/core/sys/bionic/err.d
+++ b/libphobos/libdruntime/core/sys/bionic/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.bionic.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/bionic/string.d b/libphobos/libdruntime/core/sys/bionic/string.d
index 10a5610ac449..9430a7bab4e3 100644
--- a/libphobos/libdruntime/core/sys/bionic/string.d
+++ b/libphobos/libdruntime/core/sys/bionic/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.bionic.string;
diff --git a/libphobos/libdruntime/core/sys/darwin/err.d b/libphobos/libdruntime/core/sys/darwin/err.d
index d96c790f3b66..19b51626a167 100644
--- a/libphobos/libdruntime/core/sys/darwin/err.d
+++ b/libphobos/libdruntime/core/sys/darwin/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.darwin.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index ac988b58f0d4..14bae215cde7 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.darwin.string;
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/err.d b/libphobos/libdruntime/core/sys/dragonflybsd/err.d
index c3693f85f5ea..7f7cf9467fa0 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/err.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.dragonflybsd.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/string.d b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
index 1a85ba606a19..c15bb9268e58 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/string.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.dragonflybsd.string;
diff --git a/libphobos/libdruntime/core/sys/freebsd/err.d b/libphobos/libdruntime/core/sys/freebsd/err.d
index 8937e0ec7057..5cb443a6f8a2 100644
--- a/libphobos/libdruntime/core/sys/freebsd/err.d
+++ b/libphobos/libdruntime/core/sys/freebsd/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.freebsd.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/freebsd/string.d b/libphobos/libdruntime/core/sys/freebsd/string.d
index 459e9115878e..ba7b3c019d90 100644
--- a/libphobos/libdruntime/core/sys/freebsd/string.d
+++ b/libphobos/libdruntime/core/sys/freebsd/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.freebsd.string;
diff --git a/libphobos/libdruntime/core/sys/linux/err.d b/libphobos/libdruntime/core/sys/linux/err.d
index c3752de52070..d346a0805ff4 100644
--- a/libphobos/libdruntime/core/sys/linux/err.d
+++ b/libphobos/libdruntime/core/sys/linux/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.linux.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/linux/linux/if_packet.d b/libphobos/libdruntime/core/sys/linux/linux/if_packet.d
index b50b6a339140..6dd95808d61c 100644
--- a/libphobos/libdruntime/core/sys/linux/linux/if_packet.d
+++ b/libphobos/libdruntime/core/sys/linux/linux/if_packet.d
@@ -169,7 +169,7 @@ struct tpacket_hdr
}
enum TPACKET_ALIGNMENT = 16;
-size_t TPACKET_ALIGN(size_t x) { return (x + TPACKET_ALIGNMENT - 1) &~ (TPACKET_ALIGNMENT - 1); }
+size_t TPACKET_ALIGN()(size_t x) { return (x + TPACKET_ALIGNMENT - 1) &~ (TPACKET_ALIGNMENT - 1); }
enum TPACKET_HDRLEN = TPACKET_ALIGN(tpacket_hdr.sizeof) + sockaddr_ll.sizeof;
struct tpacket2_hdr
diff --git a/libphobos/libdruntime/core/sys/linux/netinet/in_.d b/libphobos/libdruntime/core/sys/linux/netinet/in_.d
index 1b428f5aeccc..f3c23572fb2c 100644
--- a/libphobos/libdruntime/core/sys/linux/netinet/in_.d
+++ b/libphobos/libdruntime/core/sys/linux/netinet/in_.d
@@ -82,28 +82,28 @@ version (linux_libc)
enum IPPORT_USERRESERVED = 5000;
- extern(D) bool IN_CLASSA(in_addr_t i) pure @safe { return (i & 0x80000000) == 0; }
+ extern(D) bool IN_CLASSA()(in_addr_t i) pure @safe { return (i & 0x80000000) == 0; }
enum IN_CLASSA_NET = 0xff000000;
enum IN_CLASSA_NSHIFT = 24;
enum IN_CLASSA_HOST = 0xffffffff & ~IN_CLASSA_NET;
enum IN_CLASSA_MAX = 128;
- extern(D) bool IN_CLASSB(in_addr_t i) pure @safe { return (i & 0xc0000000) == 0x80000000; }
+ extern(D) bool IN_CLASSB()(in_addr_t i) pure @safe { return (i & 0xc0000000) == 0x80000000; }
enum IN_CLASSB_NET = 0xffff0000;
enum IN_CLASSB_NSHIFT = 16;
enum IN_CLASSB_HOST = 0xffffffff & ~IN_CLASSB_NET;
enum IN_CLASSB_MAX = 65536;
- extern(D) bool IN_CLASSC(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xc0000000; }
+ extern(D) bool IN_CLASSC()(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xc0000000; }
enum IN_CLASSC_NET = 0xffffff00;
enum IN_CLASSC_NSHIFT = 8;
enum IN_CLASSC_HOST = 0xffffffff & ~IN_CLASSC_NET;
- extern(D) bool IN_CLASSD(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xe0000000; }
- extern(D) bool IN_MULTICAST(in_addr_t i) { return IN_CLASSD(i); }
+ extern(D) bool IN_CLASSD()(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xe0000000; }
+ extern(D) bool IN_MULTICAST()(in_addr_t i) { return IN_CLASSD(i); }
- extern(D) bool IN_EXPERIMENTAL(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xe0000000; }
- extern(D) bool IN_BADCLASS(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xf0000000; }
+ extern(D) bool IN_EXPERIMENTAL()(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xe0000000; }
+ extern(D) bool IN_BADCLASS()(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xf0000000; }
enum IN_LOOPBACKNET = 127;
diff --git a/libphobos/libdruntime/core/sys/linux/perf_event.d b/libphobos/libdruntime/core/sys/linux/perf_event.d
index 0ad072974d5c..f8bedfb81bd9 100644
--- a/libphobos/libdruntime/core/sys/linux/perf_event.d
+++ b/libphobos/libdruntime/core/sys/linux/perf_event.d
@@ -13,82 +13,13 @@ nothrow:
import core.sys.posix.sys.ioctl;
import core.sys.posix.unistd;
-version (HPPA) version = HPPA_Any;
-version (HPPA64) version = HPPA_Any;
-version (PPC) version = PPC_Any;
-version (PPC64) version = PPC_Any;
-version (RISCV32) version = RISCV_Any;
-version (RISCV64) version = RISCV_Any;
-version (S390) version = IBMZ_Any;
-version (SPARC) version = SPARC_Any;
-version (SPARC64) version = SPARC_Any;
-version (SystemZ) version = IBMZ_Any;
-
-version (X86_64)
-{
- version (D_X32)
- enum __NR_perf_event_open = 0x40000000 + 298;
- else
- enum __NR_perf_event_open = 298;
-}
-else version (X86)
-{
- enum __NR_perf_event_open = 336;
-}
-else version (ARM)
-{
- enum __NR_perf_event_open = 364;
-}
-else version (AArch64)
-{
- enum __NR_perf_event_open = 241;
-}
-else version (HPPA_Any)
-{
- enum __NR_perf_event_open = 318;
-}
-else version (IBMZ_Any)
-{
- enum __NR_perf_event_open = 331;
-}
-else version (MIPS32)
-{
- enum __NR_perf_event_open = 4333;
-}
-else version (MIPS64)
-{
- version (MIPS_N32)
- enum __NR_perf_event_open = 6296;
- else version (MIPS_N64)
- enum __NR_perf_event_open = 5292;
- else
- static assert(0, "Architecture not supported");
-}
-else version (PPC_Any)
-{
- enum __NR_perf_event_open = 319;
-}
-else version (RISCV_Any)
-{
- enum __NR_perf_event_open = 241;
-}
-else version (SPARC_Any)
-{
- enum __NR_perf_event_open = 327;
-}
-else version (LoongArch64)
-{
- enum __NR_perf_event_open = 241;
-}
-else
-{
- static assert(0, "Architecture not supported");
-}
-extern (C) extern long syscall(long __sysno, ...);
static long perf_event_open(perf_event_attr* hw_event, pid_t pid, int cpu, int group_fd, ulong flags)
{
- return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
+ import core.sys.linux.unistd : syscall;
+ import core.sys.linux.syscall : __NR_perf_event_open;
+ return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
}
+
/*
* User-space ABI bits:
*/
diff --git a/libphobos/libdruntime/core/sys/linux/sched.d b/libphobos/libdruntime/core/sys/linux/sched.d
index 5cd512e82630..0a940db65ed4 100644
--- a/libphobos/libdruntime/core/sys/linux/sched.d
+++ b/libphobos/libdruntime/core/sys/linux/sched.d
@@ -41,31 +41,31 @@ private // helpers
/* Macros */
/* Basic access functions. */
- size_t __CPUELT(size_t cpu) pure
+ size_t __CPUELT()(size_t cpu) pure
{
return cpu / __NCPUBITS;
}
- cpu_mask __CPUMASK(size_t cpu) pure
+ cpu_mask __CPUMASK()(size_t cpu) pure
{
return 1UL << (cpu % __NCPUBITS);
}
- cpu_set_t* __CPU_ALLOC(size_t count)
+ cpu_set_t* __CPU_ALLOC()(size_t count)
{
return cast(cpu_set_t*) malloc(__CPU_ALLOC_SIZE(count));
}
- size_t __CPU_ALLOC_SIZE(size_t count) pure
+ size_t __CPU_ALLOC_SIZE()(size_t count) pure
{
return ((count + __NCPUBITS - 1) / __NCPUBITS) * cpu_mask.sizeof;
}
- void __CPU_FREE(cpu_set_t* set)
+ void __CPU_FREE()(cpu_set_t* set)
{
free(cast(void*) set);
}
- cpu_mask __CPU_SET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure
+ cpu_mask __CPU_SET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure
{
if (cpu < 8 * setsize)
{
@@ -76,14 +76,14 @@ private // helpers
return 0;
}
- bool __CPU_ISSET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure
+ bool __CPU_ISSET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure
{
if (cpu < 8 * setsize)
return (cpusetp.__bits[__CPUELT(cpu)] & __CPUMASK(cpu)) != 0;
return false;
}
- int __CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure
+ int __CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure
{
int s = 0;
foreach (i; cpusetp.__bits[0 .. (setsize / cpu_mask.sizeof)])
@@ -103,37 +103,37 @@ struct cpu_set_t
/// Access macros for 'cpu_set' (missing a lot of them)
-cpu_set_t* CPU_ALLOC(size_t count)
+cpu_set_t* CPU_ALLOC()(size_t count)
{
return __CPU_ALLOC(count);
}
-size_t CPU_ALLOC_SIZE(size_t count) pure
+size_t CPU_ALLOC_SIZE()(size_t count) pure
{
return __CPU_ALLOC_SIZE(count);
}
-void CPU_FREE(cpu_set_t* set)
+void CPU_FREE()(cpu_set_t* set)
{
__CPU_FREE(set);
}
-cpu_mask CPU_SET(size_t cpu, cpu_set_t* cpusetp) pure
+cpu_mask CPU_SET()(size_t cpu, cpu_set_t* cpusetp) pure
{
return __CPU_SET_S(cpu, cpu_set_t.sizeof, cpusetp);
}
-bool CPU_ISSET(size_t cpu, cpu_set_t* cpusetp) pure
+bool CPU_ISSET()(size_t cpu, cpu_set_t* cpusetp) pure
{
return __CPU_ISSET_S(cpu, cpu_set_t.sizeof, cpusetp);
}
-int CPU_COUNT(cpu_set_t* cpusetp) pure
+int CPU_COUNT()(cpu_set_t* cpusetp) pure
{
return __CPU_COUNT_S(cpu_set_t.sizeof, cpusetp);
}
-int CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure
+int CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure
{
return __CPU_COUNT_S(setsize, cpusetp);
}
diff --git a/libphobos/libdruntime/core/sys/linux/string.d b/libphobos/libdruntime/core/sys/linux/string.d
index a8da39824612..7288231730d1 100644
--- a/libphobos/libdruntime/core/sys/linux/string.d
+++ b/libphobos/libdruntime/core/sys/linux/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.linux.string;
diff --git a/libphobos/libdruntime/core/sys/linux/sys/syscall.d b/libphobos/libdruntime/core/sys/linux/sys/syscall.d
new file mode 100644
index 000000000000..9e313e15c93d
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/linux/sys/syscall.d
@@ -0,0 +1,127 @@
+/**
+ * D header file for GNU/Linux
+ *
+ * $(LINK2 https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sys/syscall.h, glibc sys/syscall.h)
+ */
+
+module core.sys.linux.sys.syscall;
+
+version (linux):
+extern (C):
+@nogc:
+nothrow:
+
+version (HPPA) version = HPPA_Any;
+version (HPPA64) version = HPPA_Any;
+version (PPC) version = PPC_Any;
+version (PPC64) version = PPC_Any;
+version (RISCV32) version = RISCV_Any;
+version (RISCV64) version = RISCV_Any;
+version (S390) version = IBMZ_Any;
+version (SPARC) version = SPARC_Any;
+version (SPARC64) version = SPARC_Any;
+version (SystemZ) version = IBMZ_Any;
+
+/+
+ Check out the following links for handy tables:
+
+ - <https://gpages.juszkiewicz.com.pl/syscalls-table/syscalls.html>
+ - <https://github.com/hrw/syscalls-table>
+ +/
+
+// <asm/unistd.h>
+// List the numbers of the system calls the system knows.
+version (X86_64)
+{
+ version (D_X32)
+ {
+ private enum __X32_SYSCALL_BIT = 0x40000000;
+
+ enum __NR_getrandom = __X32_SYSCALL_BIT + 318;
+ enum __NR_perf_event_open = __X32_SYSCALL_BIT + 298;
+ }
+ else
+ {
+ enum __NR_getrandom = 318;
+ enum __NR_perf_event_open = 298;
+ }
+}
+else version (X86)
+{
+ enum __NR_getrandom = 355;
+ enum __NR_perf_event_open = 336;
+}
+else version (ARM)
+{
+ enum __NR_getrandom = 384;
+ enum __NR_perf_event_open = 364;
+}
+else version (AArch64)
+{
+ enum __NR_getrandom = 278;
+ enum __NR_perf_event_open = 241;
+}
+else version (HPPA_Any)
+{
+ enum __NR_getrandom = 339;
+ enum __NR_perf_event_open = 318;
+}
+else version (IBMZ_Any)
+{
+ enum __NR_getrandom = 349;
+ enum __NR_perf_event_open = 331;
+}
+else version (MIPS32)
+{
+ enum __NR_getrandom = 4353;
+ enum __NR_perf_event_open = 4333;
+}
+else version (MIPS64)
+{
+ version (MIPS_N32)
+ {
+ enum __NR_getrandom = 6317;
+ enum __NR_perf_event_open = 6296;
+ }
+ else version (MIPS_N64)
+ {
+ enum __NR_getrandom = 5313;
+ enum __NR_perf_event_open = 5292;
+ }
+ else
+ static assert(0, "Architecture not supported");
+}
+else version (PPC_Any)
+{
+ enum __NR_getrandom = 359;
+ enum __NR_perf_event_open = 319;
+}
+else version (RISCV_Any)
+{
+ enum __NR_getrandom = 278;
+ enum __NR_perf_event_open = 241;
+}
+else version (SPARC_Any)
+{
+ enum __NR_getrandom = 347;
+ enum __NR_perf_event_open = 327;
+}
+else version (LoongArch64)
+{
+ enum __NR_getrandom = 278;
+ enum __NR_perf_event_open = 241;
+}
+else version (Xtensa)
+{
+ enum __NR_getrandom = 338;
+ enum __NR_perf_event_open = 327;
+}
+else
+{
+ static assert(0, "Architecture not supported");
+}
+
+// <bits/syscall.h>
+// Defines SYS_* names for the __NR_* numbers of known names.
+enum SYS_getrandom = __NR_getrandom;
+enum SYS_perf_event_open = __NR_perf_event_open;
diff --git a/libphobos/libdruntime/core/sys/linux/sys/time.d b/libphobos/libdruntime/core/sys/linux/sys/time.d
index 4b56229687c7..9eb48f1c5ef7 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/time.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/time.d
@@ -23,7 +23,7 @@ version (linux):
*/
extern (D) pure @safe @nogc nothrow {
- void timeradd(const timeval* a, const timeval* b,
+ void timeradd()(const timeval* a, const timeval* b,
timeval* result)
{
result.tv_sec = a.tv_sec + b.tv_sec;
@@ -35,7 +35,7 @@ extern (D) pure @safe @nogc nothrow {
}
}
- void timersub(const timeval* a, const timeval* b,
+ void timersub()(const timeval* a, const timeval* b,
timeval *result)
{
result.tv_sec = a.tv_sec - b.tv_sec;
@@ -46,12 +46,12 @@ extern (D) pure @safe @nogc nothrow {
}
}
- void timerclear(timeval* tvp)
+ void timerclear()(timeval* tvp)
{
(tvp.tv_sec = tvp.tv_usec = 0);
}
- int timerisset(timeval* tvp)
+ int timerisset()(timeval* tvp)
{
return cast(int) (tvp.tv_sec || tvp.tv_usec);
}
diff --git a/libphobos/libdruntime/core/sys/linux/syscall.d b/libphobos/libdruntime/core/sys/linux/syscall.d
new file mode 100644
index 000000000000..84d03e75fb1a
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/linux/syscall.d
@@ -0,0 +1,14 @@
+/**
+ * D header file for GNU/Linux
+ *
+ * $(LINK2 https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/syscall.h, glibc syscall.h)
+ */
+
+module core.sys.linux.syscall;
+
+version (linux):
+extern (C):
+@nogc:
+nothrow:
+
+public import core.sys.linux.sys.syscall;
diff --git a/libphobos/libdruntime/core/sys/linux/unistd.d b/libphobos/libdruntime/core/sys/linux/unistd.d
index 548870268dbf..3194ec2962c6 100644
--- a/libphobos/libdruntime/core/sys/linux/unistd.d
+++ b/libphobos/libdruntime/core/sys/linux/unistd.d
@@ -7,6 +7,8 @@ extern(C):
nothrow:
@nogc:
+import core.stdc.config : c_long;
+
// Additional seek constants for sparse file handling
// from Linux's unistd.h, stdio.h, and linux/fs.h
// (see http://man7.org/linux/man-pages/man2/lseek.2.html)
@@ -25,3 +27,6 @@ void exit_group(int status);
/// Close all open file descriptors greater or equal to `lowfd`
void closefrom(int lowfd);
+
+/// Invoke system call number `sysno`, passing it the remaining arguments.
+c_long syscall(c_long sysno, ...);
diff --git a/libphobos/libdruntime/core/sys/netbsd/err.d b/libphobos/libdruntime/core/sys/netbsd/err.d
index 44eb66adc2fc..399ddea989a8 100644
--- a/libphobos/libdruntime/core/sys/netbsd/err.d
+++ b/libphobos/libdruntime/core/sys/netbsd/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.netbsd.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/netbsd/string.d b/libphobos/libdruntime/core/sys/netbsd/string.d
index f1281da275b7..d83d22d56dd8 100644
--- a/libphobos/libdruntime/core/sys/netbsd/string.d
+++ b/libphobos/libdruntime/core/sys/netbsd/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.netbsd.string;
diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d b/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d
index 3901ea9703ba..ded053a36e49 100644
--- a/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d
+++ b/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.netbsd.sys.featuretest;
diff --git a/libphobos/libdruntime/core/sys/openbsd/err.d b/libphobos/libdruntime/core/sys/openbsd/err.d
index b4676140e382..271f2c4bfc63 100644
--- a/libphobos/libdruntime/core/sys/openbsd/err.d
+++ b/libphobos/libdruntime/core/sys/openbsd/err.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.openbsd.err;
import core.stdc.stdarg : va_list;
diff --git a/libphobos/libdruntime/core/sys/openbsd/string.d b/libphobos/libdruntime/core/sys/openbsd/string.d
index 4480c94ac37b..e0c33be9d678 100644
--- a/libphobos/libdruntime/core/sys/openbsd/string.d
+++ b/libphobos/libdruntime/core/sys/openbsd/string.d
@@ -3,7 +3,7 @@
*
* Copyright: Copyright © 2019, The D Language Foundation
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
- * Authors: Ernesto Castellotti
+ * Authors: Emily Castellotti
*/
module core.sys.openbsd.string;
diff --git a/libphobos/libdruntime/core/sys/posix/netdb.d b/libphobos/libdruntime/core/sys/posix/netdb.d
index 70a5fe1901f3..4713f4b49559 100644
--- a/libphobos/libdruntime/core/sys/posix/netdb.d
+++ b/libphobos/libdruntime/core/sys/posix/netdb.d
@@ -153,7 +153,7 @@ version (CRuntime_Glibc)
int h_addrtype;
int h_length;
char** h_addr_list;
- char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -237,7 +237,7 @@ else version (Darwin)
int h_addrtype;
int h_length;
char** h_addr_list;
- char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -321,7 +321,7 @@ else version (FreeBSD)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -405,7 +405,7 @@ else version (NetBSD)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -512,7 +512,7 @@ else version (OpenBSD)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -608,7 +608,7 @@ else version (DragonFlyBSD)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -706,7 +706,7 @@ else version (Solaris)
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -793,7 +793,7 @@ else version (CRuntime_Bionic)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -874,7 +874,7 @@ else version (CRuntime_Musl)
int h_addrtype;
int h_length;
char** h_addr_list;
- char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
@@ -952,7 +952,7 @@ else version (CRuntime_UClibc)
int h_addrtype;
int h_length;
char** h_addr_list;
- extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard
+ extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard
}
struct netent
diff --git a/libphobos/libdruntime/core/sys/posix/netinet/in_.d b/libphobos/libdruntime/core/sys/posix/netinet/in_.d
index 5818ee6e22b6..09a4a5e07d10 100644
--- a/libphobos/libdruntime/core/sys/posix/netinet/in_.d
+++ b/libphobos/libdruntime/core/sys/posix/netinet/in_.d
@@ -547,7 +547,7 @@ version (CRuntime_Glibc)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -555,7 +555,7 @@ version (CRuntime_Glibc)
(cast(uint32_t*) addr)[3] == 0;
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -563,29 +563,29 @@ version (CRuntime_Glibc)
(cast(uint32_t*) addr)[3] == htonl( 1 );
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure
{
return (cast(uint8_t*) addr)[0] == 0xff;
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure
{
return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 );
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure
{
return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 );
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
(cast(uint32_t*) addr)[2] == htonl( 0xffff );
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -593,31 +593,31 @@ version (CRuntime_Glibc)
ntohl( (cast(uint32_t*) addr)[3] ) > 1;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST(addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
@@ -670,7 +670,7 @@ else version (Darwin)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -678,7 +678,7 @@ else version (Darwin)
(cast(uint32_t*) addr)[3] == 0;
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -686,29 +686,29 @@ else version (Darwin)
(cast(uint32_t*) addr)[3] == ntohl( 1 );
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure
{
return addr.s6_addr[0] == 0xff;
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure
{
return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure
{
return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
(cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff );
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -717,31 +717,31 @@ else version (Darwin)
(cast(uint32_t*) addr)[3] != ntohl( 1 );
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST(addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
@@ -804,7 +804,7 @@ else version (FreeBSD)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -812,7 +812,7 @@ else version (FreeBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -820,7 +820,7 @@ else version (FreeBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -829,58 +829,58 @@ else version (FreeBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
@@ -943,7 +943,7 @@ else version (NetBSD)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -951,7 +951,7 @@ else version (NetBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -959,7 +959,7 @@ else version (NetBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -968,58 +968,58 @@ else version (NetBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
@@ -1082,7 +1082,7 @@ else version (OpenBSD)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1090,7 +1090,7 @@ else version (OpenBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1098,7 +1098,7 @@ else version (OpenBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1107,58 +1107,58 @@ else version (OpenBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
@@ -1221,7 +1221,7 @@ else version (DragonFlyBSD)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1229,7 +1229,7 @@ else version (DragonFlyBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1237,7 +1237,7 @@ else version (DragonFlyBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
@@ -1246,58 +1246,58 @@ else version (DragonFlyBSD)
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
@@ -1350,67 +1350,67 @@ else version (Solaris)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] != 0) &&
(a.s6_addr32[3] != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x01;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x02;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x05;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x08;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x0e;
}
@@ -1640,7 +1640,7 @@ else version (CRuntime_UClibc)
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()( in6_addr* addr) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -1648,7 +1648,7 @@ else version (CRuntime_UClibc)
(cast(uint32_t*) addr)[3] == 0;
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK()( in6_addr* addr) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -1656,29 +1656,29 @@ else version (CRuntime_UClibc)
(cast(uint32_t*) addr)[3] == htonl( 1 );
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST()( in6_addr* addr) pure
{
return (cast(uint8_t*) addr)[0] == 0xff;
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL()( in6_addr* addr) pure
{
return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 );
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL()( in6_addr* addr) pure
{
return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 );
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED()( in6_addr* addr) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
(cast(uint32_t*) addr)[2] == htonl( 0xffff );
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT()( in6_addr* addr) pure
{
return (cast(uint32_t*) addr)[0] == 0 &&
(cast(uint32_t*) addr)[1] == 0 &&
@@ -1686,7 +1686,7 @@ else version (CRuntime_UClibc)
ntohl( (cast(uint32_t*) addr)[3] ) > 1;
}
- extern (D) int IN6_ARE_ADDR_EQUAL( in6_addr* a, in6_addr* b ) pure
+ extern (D) int IN6_ARE_ADDR_EQUAL()( in6_addr* a, in6_addr* b) pure
{
return (cast(uint32_t*) a)[0] == (cast(uint32_t*) b)[0] &&
(cast(uint32_t*) a)[1] == (cast(uint32_t*) b)[1] &&
@@ -1694,31 +1694,31 @@ else version (CRuntime_UClibc)
(cast(uint32_t*) a)[3] == (cast(uint32_t*) b)[3];
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( in6_addr* addr) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( in6_addr* addr) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( in6_addr* addr) pure
{
return IN6_IS_ADDR_MULTICAST(addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( in6_addr* addr) pure
{
return IN6_IS_ADDR_MULTICAST( addr) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()( in6_addr* addr) pure
{
return IN6_IS_ADDR_MULTICAST( addr ) &&
((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index e3d80fb02180..bdc68687d0f6 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -179,7 +179,7 @@ else version (linux)
int __libc_current_sigrtmax();
}
- @property int SIGRTMIN() nothrow @nogc {
+ @property int SIGRTMIN()() nothrow @nogc {
__gshared int sig = -1;
if (sig == -1) {
sig = __libc_current_sigrtmin();
@@ -187,7 +187,7 @@ else version (linux)
return sig;
}
- @property int SIGRTMAX() nothrow @nogc {
+ @property int SIGRTMAX()() nothrow @nogc {
__gshared int sig = -1;
if (sig == -1) {
sig = __libc_current_sigrtmax();
@@ -1012,12 +1012,12 @@ version (linux)
} _sifields_t _sifields;
nothrow @nogc:
- @property ref pid_t si_pid() return { return _sifields._kill.si_pid; }
- @property ref uid_t si_uid() return { return _sifields._kill.si_uid; }
- @property ref void* si_addr() return { return _sifields._sigfault.si_addr; }
- @property ref int si_status() return { return _sifields._sigchld.si_status; }
- @property ref c_long si_band() return { return _sifields._sigpoll.si_band; }
- @property ref sigval si_value() return { return _sifields._rt.si_sigval; }
+ @property ref pid_t si_pid()() { return _sifields._kill.si_pid; }
+ @property ref uid_t si_uid()() { return _sifields._kill.si_uid; }
+ @property ref void* si_addr()() { return _sifields._sigfault.si_addr; }
+ @property ref int si_status()() { return _sifields._sigchld.si_status; }
+ @property ref c_long si_band()() { return _sifields._sigpoll.si_band; }
+ @property ref sigval si_value()() { return _sifields._rt.si_sigval; }
}
enum
@@ -2763,6 +2763,11 @@ else version (CRuntime_Musl)
enum MINSIGSTKSZ = 4096;
enum SIGSTKSZ = 16384;
}
+ else version (RISCV64)
+ {
+ enum MINSIGSTKSZ = 2048;
+ enum SIGSTKSZ = 8192;
+ }
else
static assert(0, "unimplemented");
diff --git a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
index caf3ebafb5a5..27584d357c4d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
@@ -61,7 +61,7 @@ version (linux)
(is(T == typeof(null)) ? 0 : T.sizeof << _IOC_SIZESHIFT);
}
- extern (D) int _IO(int type, int nr)
+ extern (D) int _IO()(int type, int nr)
{
return _IOC(_IOC_NONE, type, nr);
}
@@ -81,22 +81,22 @@ version (linux)
return _IOC!T(_IOC_READ | _IOC_WRITE, type, nr);
}
- extern (D) int _IOC_DIR(int nr)
+ extern (D) int _IOC_DIR()(int nr)
{
return (nr >> _IOC_DIRSHIFT) & _IOC_DIRMASK;
}
- extern (D) int _IOC_TYPE(int nr)
+ extern (D) int _IOC_TYPE()(int nr)
{
return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK;
}
- extern (D) int _IOC_NR(int nr)
+ extern (D) int _IOC_NR()(int nr)
{
return (nr >> _IOC_NRSHIFT) & _IOC_NRMASK;
}
- extern (D) int _IOC_SIZE(int nr)
+ extern (D) int _IOC_SIZE()(int nr)
{
return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK;
}
diff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d
index bd3425032521..c8a88bddc0ca 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/select.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/select.d
@@ -57,12 +57,12 @@ version (CRuntime_Glibc)
alias c_long __fd_mask;
enum uint __NFDBITS = 8 * __fd_mask.sizeof;
- extern (D) auto __FDELT( int d ) pure
+ extern (D) auto __FDELT()( int d ) pure
{
return d / __NFDBITS;
}
- extern (D) auto __FDMASK( int d ) pure
+ extern (D) auto __FDMASK()( int d ) pure
{
return cast(__fd_mask) 1 << ( d % __NFDBITS );
}
@@ -75,22 +75,22 @@ version (CRuntime_Glibc)
__fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
}
- extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
+ extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
}
- extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
+ extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure
{
return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
}
- extern (D) void FD_SET( int fd, fd_set* fdset ) pure
+ extern (D) void FD_SET()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
}
- extern (D) void FD_ZERO( fd_set* fdset ) pure
+ extern (D) void FD_ZERO()( fd_set* fdset ) pure
{
fdset.fds_bits[0 .. $] = 0;
}
@@ -148,22 +148,22 @@ else version (Darwin)
int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits;
}
- extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
+ extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS));
}
- extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
+ extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure
{
return (fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS))) != 0;
}
- extern (D) void FD_SET( int fd, fd_set* fdset ) pure
+ extern (D) void FD_SET()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS);
}
- extern (D) void FD_ZERO( fd_set* fdset ) pure
+ extern (D) void FD_ZERO()( fd_set* fdset ) pure
{
fdset.fds_bits[0 .. $] = 0;
}
@@ -187,27 +187,27 @@ else version (FreeBSD)
deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
- extern (D) __fd_mask __fdset_mask(uint n) pure
+ extern (D) __fd_mask __fdset_mask()(uint n) pure
{
return cast(__fd_mask) 1 << (n % _NFDBITS);
}
- extern (D) void FD_CLR( int n, fd_set* p ) pure
+ extern (D) void FD_CLR()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
- extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
+ extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure
{
return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
- extern (D) void FD_SET( int n, fd_set* p ) pure
+ extern (D) void FD_SET()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
- extern (D) void FD_ZERO( fd_set* p ) pure
+ extern (D) void FD_ZERO()( fd_set* p ) pure
{
fd_set *_p;
size_t _n;
@@ -237,27 +237,27 @@ else version (NetBSD)
deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
- extern (D) __fd_mask __fdset_mask(uint n) pure
+ extern (D) __fd_mask __fdset_mask()(uint n) pure
{
return cast(__fd_mask) 1 << (n % _NFDBITS);
}
- extern (D) void FD_CLR( int n, fd_set* p ) pure
+ extern (D) void FD_CLR()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
- extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
+ extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure
{
return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
- extern (D) void FD_SET( int n, fd_set* p ) pure
+ extern (D) void FD_SET()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
- extern (D) void FD_ZERO( fd_set* p ) pure
+ extern (D) void FD_ZERO()( fd_set* p ) pure
{
fd_set *_p;
size_t _n;
@@ -287,27 +287,27 @@ else version (OpenBSD)
deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
- extern (D) __fd_mask __fdset_mask(uint n) pure
+ extern (D) __fd_mask __fdset_mask()(uint n) pure
{
return cast(__fd_mask) 1 << (n % _NFDBITS);
}
- extern (D) void FD_CLR(int n, fd_set* p) pure
+ extern (D) void FD_CLR()(int n, fd_set* p) pure
{
p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
- extern (D) bool FD_ISSET(int n, const(fd_set)* p) pure
+ extern (D) bool FD_ISSET()(int n, const(fd_set)* p) pure
{
return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
- extern (D) void FD_SET(int n, fd_set* p) pure
+ extern (D) void FD_SET()(int n, fd_set* p) pure
{
p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
- extern (D) void FD_ZERO(fd_set* p) pure
+ extern (D) void FD_ZERO()(fd_set* p) pure
{
fd_set *_p = p;
size_t _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
@@ -335,27 +335,27 @@ else version (DragonFlyBSD)
deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
- extern (D) __fd_mask __fdset_mask(uint n) pure
+ extern (D) __fd_mask __fdset_mask()(uint n) pure
{
return cast(__fd_mask) 1 << (n % _NFDBITS);
}
- extern (D) void FD_CLR( int n, fd_set* p ) pure
+ extern (D) void FD_CLR()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
- extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
+ extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure
{
return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
- extern (D) void FD_SET( int n, fd_set* p ) pure
+ extern (D) void FD_SET()( int n, fd_set* p ) pure
{
p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
- extern (D) void FD_ZERO( fd_set* p ) pure
+ extern (D) void FD_ZERO()( fd_set* p ) pure
{
fd_set *_p;
size_t _n;
@@ -389,22 +389,22 @@ else version (Solaris)
c_long[(FD_SETSIZE + (FD_NFDBITS - 1)) / FD_NFDBITS] fds_bits;
}
- extern (D) void FD_SET(int __n, fd_set* __p) pure
+ extern (D) void FD_SET()(int __n, fd_set* __p) pure
{
__p.fds_bits[__n / FD_NFDBITS] |= 1UL << (__n % FD_NFDBITS);
}
- extern (D) void FD_CLR(int __n, fd_set* __p) pure
+ extern (D) void FD_CLR()(int __n, fd_set* __p) pure
{
__p.fds_bits[__n / FD_NFDBITS] &= ~(1UL << (__n % FD_NFDBITS));
}
- extern (D) bool FD_ISSET(int __n, const(fd_set)* __p) pure
+ extern (D) bool FD_ISSET()(int __n, const(fd_set)* __p) pure
{
return (__p.fds_bits[__n / FD_NFDBITS] & (1UL << (__n % FD_NFDBITS))) != 0;
}
- extern (D) void FD_ZERO(fd_set* __p) pure
+ extern (D) void FD_ZERO()(fd_set* __p) pure
{
__p.fds_bits[0 .. $] = 0;
}
@@ -419,12 +419,12 @@ else version (CRuntime_Bionic)
alias c_ulong __fd_mask;
enum uint __NFDBITS = 8 * __fd_mask.sizeof;
- extern (D) auto __FDELT( int d ) pure
+ extern (D) auto __FDELT()( int d ) pure
{
return d / __NFDBITS;
}
- extern (D) auto __FDMASK( int d ) pure
+ extern (D) auto __FDMASK()( int d ) pure
{
return cast(__fd_mask) 1 << ( d % __NFDBITS );
}
@@ -438,22 +438,22 @@ else version (CRuntime_Bionic)
}
// These functions are generated in assembly in bionic.
- extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
+ extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
}
- extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
+ extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure
{
return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
}
- extern (D) void FD_SET( int fd, fd_set* fdset ) pure
+ extern (D) void FD_SET()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
}
- extern (D) void FD_ZERO( fd_set* fdset ) pure
+ extern (D) void FD_ZERO()( fd_set* fdset ) pure
{
fdset.fds_bits[0 .. $] = 0;
}
@@ -471,12 +471,12 @@ else version (CRuntime_Musl)
{
enum uint __NFDBITS = 8 * fd_mask.sizeof;
- extern (D) auto __FDELT( int d ) pure
+ extern (D) auto __FDELT()( int d ) pure
{
return d / __NFDBITS;
}
- extern (D) auto __FDMASK( int d ) pure
+ extern (D) auto __FDMASK()( int d ) pure
{
return cast(fd_mask) 1 << ( d % __NFDBITS );
}
@@ -486,22 +486,22 @@ else version (CRuntime_Musl)
ulong[FD_SETSIZE / 8 / long.sizeof] fds_bits;
}
- extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
+ extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
}
- extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
+ extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure
{
return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
}
- extern (D) void FD_SET( int fd, fd_set* fdset ) pure
+ extern (D) void FD_SET()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
}
- extern (D) void FD_ZERO( fd_set* fdset ) pure
+ extern (D) void FD_ZERO()( fd_set* fdset ) pure
{
fdset.fds_bits[0 .. $] = 0;
}
@@ -517,12 +517,12 @@ else version (CRuntime_UClibc)
alias c_long __fd_mask;
enum uint __NFDBITS = 8 * __fd_mask.sizeof;
- extern (D) auto __FDELT( int d ) pure
+ extern (D) auto __FDELT()( int d ) pure
{
return d / __NFDBITS;
}
- extern (D) auto __FDMASK( int d ) pure
+ extern (D) auto __FDMASK()( int d ) pure
{
return cast(__fd_mask) 1 << ( d % __NFDBITS );
}
@@ -535,22 +535,22 @@ else version (CRuntime_UClibc)
__fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
}
- extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
+ extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
}
- extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
+ extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure
{
return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
}
- extern (D) void FD_SET( int fd, fd_set* fdset ) pure
+ extern (D) void FD_SET()( int fd, fd_set* fdset ) pure
{
fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
}
- extern (D) void FD_ZERO( fd_set* fdset ) pure
+ extern (D) void FD_ZERO()( fd_set* fdset ) pure
{
fdset.fds_bits[0 .. $] = 0;
}
diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d
index 12824373d586..5bdc22294c1d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d
@@ -233,12 +233,12 @@ version (linux)
extern (D)
{
- size_t CMSG_ALIGN( size_t len ) pure nothrow @nogc
+ size_t CMSG_ALIGN()( size_t len ) pure nothrow @nogc
{
return (len + size_t.sizeof - 1) & cast(size_t) (~(size_t.sizeof - 1));
}
- size_t CMSG_LEN( size_t len ) pure nothrow @nogc
+ size_t CMSG_LEN()( size_t len ) pure nothrow @nogc
{
return CMSG_ALIGN(cmsghdr.sizeof) + len;
}
@@ -668,13 +668,13 @@ else version (Darwin)
extern (D)
{
- socklen_t CMSG_ALIGN(socklen_t len) pure nothrow @nogc { return (len + socklen_t.sizeof - 1) & cast(socklen_t) (~(socklen_t.sizeof - 1)); }
- socklen_t CMSG_SPACE(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(len) + CMSG_ALIGN(cmsghdr.sizeof); }
- socklen_t CMSG_LEN(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(cmsghdr.sizeof) + len; }
+ socklen_t CMSG_ALIGN()(socklen_t len) pure nothrow @nogc { return (len + socklen_t.sizeof - 1) & cast(socklen_t) (~(socklen_t.sizeof - 1)); }
+ socklen_t CMSG_SPACE()(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(len) + CMSG_ALIGN(cmsghdr.sizeof); }
+ socklen_t CMSG_LEN()(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(cmsghdr.sizeof) + len; }
- inout(ubyte)* CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
+ inout(ubyte)* CMSG_DATA()( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
- inout(cmsghdr)* CMSG_FIRSTHDR( inout(msghdr)* mhdr ) pure nothrow @nogc
+ inout(cmsghdr)* CMSG_FIRSTHDR()( inout(msghdr)* mhdr ) pure nothrow @nogc
{
return ( cast(socklen_t)mhdr.msg_controllen >= cmsghdr.sizeof ? cast(inout(cmsghdr)*) mhdr.msg_control : cast(inout(cmsghdr)*) null );
}
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 328f620a42a2..ab79a4067509 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -1464,19 +1464,19 @@ version (CRuntime_Glibc)
private
{
- extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+ extern (D) bool S_ISTYPE()( mode_t mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
int utimensat(int dirfd, const char *pathname,
ref const(timespec)[2] times, int flags);
@@ -1501,19 +1501,19 @@ else version (Darwin)
private
{
- extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+ extern (D) bool S_ISTYPE()( mode_t mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
}
else version (FreeBSD)
{
@@ -1534,19 +1534,19 @@ else version (FreeBSD)
private
{
- extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+ extern (D) bool S_ISTYPE()( mode_t mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
// Since FreeBSD 11:
version (none)
@@ -1575,19 +1575,19 @@ else version (NetBSD)
private
{
- extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+ extern (D) bool S_ISTYPE()( mode_t mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
}
else version (OpenBSD)
{
@@ -1606,13 +1606,13 @@ else version (OpenBSD)
enum S_IXOTH = 0x1; // 0000001
enum S_IRWXO = 0x7; // 0000007
- extern (D) bool S_ISBLK(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; }
- extern (D) bool S_ISCHR(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; }
- extern (D) bool S_ISDIR(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; }
- extern (D) bool S_ISFIFO(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; }
- extern (D) bool S_ISREG(mode_t mode) { return (mode & S_IFMT) == S_IFREG; }
- extern (D) bool S_ISLNK(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; }
- extern (D) bool S_ISSOCK(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; }
+ extern (D) bool S_ISBLK()(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; }
+ extern (D) bool S_ISCHR()(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; }
+ extern (D) bool S_ISDIR()(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; }
+ extern (D) bool S_ISFIFO()(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; }
+ extern (D) bool S_ISREG()(mode_t mode) { return (mode & S_IFMT) == S_IFREG; }
+ extern (D) bool S_ISLNK()(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; }
+ extern (D) bool S_ISSOCK()(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; }
}
else version (DragonFlyBSD)
{
@@ -1633,19 +1633,19 @@ else version (DragonFlyBSD)
private
{
- extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+ extern (D) bool S_ISTYPE()( mode_t mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
}
else version (Solaris)
{
@@ -1666,21 +1666,21 @@ else version (Solaris)
private
{
- extern (D) bool S_ISTYPE(mode_t mode, uint mask)
+ extern (D) bool S_ISTYPE()(mode_t mode, uint mask)
{
return (mode & S_IFMT) == mask;
}
}
- extern (D) bool S_ISBLK(mode_t mode) { return S_ISTYPE(mode, S_IFBLK); }
- extern (D) bool S_ISCHR(mode_t mode) { return S_ISTYPE(mode, S_IFCHR); }
- extern (D) bool S_ISDIR(mode_t mode) { return S_ISTYPE(mode, S_IFDIR); }
- extern (D) bool S_ISFIFO(mode_t mode) { return S_ISTYPE(mode, S_IFIFO); }
- extern (D) bool S_ISREG(mode_t mode) { return S_ISTYPE(mode, S_IFREG); }
- extern (D) bool S_ISLNK(mode_t mode) { return S_ISTYPE(mode, S_IFLNK); }
- extern (D) bool S_ISSOCK(mode_t mode) { return S_ISTYPE(mode, S_IFSOCK); }
- extern (D) bool S_ISDOOR(mode_t mode) { return S_ISTYPE(mode, S_IFDOOR); }
- extern (D) bool S_ISPORT(mode_t mode) { return S_ISTYPE(mode, S_IFPORT); }
+ extern (D) bool S_ISBLK()(mode_t mode) { return S_ISTYPE(mode, S_IFBLK); }
+ extern (D) bool S_ISCHR()(mode_t mode) { return S_ISTYPE(mode, S_IFCHR); }
+ extern (D) bool S_ISDIR()(mode_t mode) { return S_ISTYPE(mode, S_IFDIR); }
+ extern (D) bool S_ISFIFO()(mode_t mode) { return S_ISTYPE(mode, S_IFIFO); }
+ extern (D) bool S_ISREG()(mode_t mode) { return S_ISTYPE(mode, S_IFREG); }
+ extern (D) bool S_ISLNK()(mode_t mode) { return S_ISTYPE(mode, S_IFLNK); }
+ extern (D) bool S_ISSOCK()(mode_t mode) { return S_ISTYPE(mode, S_IFSOCK); }
+ extern (D) bool S_ISDOOR()(mode_t mode) { return S_ISTYPE(mode, S_IFDOOR); }
+ extern (D) bool S_ISPORT()(mode_t mode) { return S_ISTYPE(mode, S_IFPORT); }
}
else version (CRuntime_Bionic)
{
@@ -1701,19 +1701,19 @@ else version (CRuntime_Bionic)
private
{
- extern (D) bool S_ISTYPE( uint mode, uint mask )
+ extern (D) bool S_ISTYPE()( uint mode, uint mask )
{
return ( mode & S_IFMT ) == mask;
}
}
- extern (D) bool S_ISBLK( uint mode ) { return S_ISTYPE( mode, S_IFBLK ); }
- extern (D) bool S_ISCHR( uint mode ) { return S_ISTYPE( mode, S_IFCHR ); }
- extern (D) bool S_ISDIR( uint mode ) { return S_ISTYPE( mode, S_IFDIR ); }
- extern (D) bool S_ISFIFO( uint mode ) { return S_ISTYPE( mode, S_IFIFO ); }
- extern (D) bool S_ISREG( uint mode ) { return S_ISTYPE( mode, S_IFREG ); }
- extern (D) bool S_ISLNK( uint mode ) { return S_ISTYPE( mode, S_IFLNK ); }
- extern (D) bool S_ISSOCK( uint mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+ extern (D) bool S_ISBLK()( uint mode ) { return S_ISTYPE( mode, S_IFBLK ); }
+ extern (D) bool S_ISCHR()( uint mode ) { return S_ISTYPE( mode, S_IFCHR ); }
+ extern (D) bool S_ISDIR()( uint mode ) { return S_ISTYPE( mode, S_IFDIR ); }
+ extern (D) bool S_ISFIFO()( uint mode ) { return S_ISTYPE( mode, S_IFIFO ); }
+ extern (D) bool S_ISREG()( uint mode ) { return S_ISTYPE( mode, S_IFREG ); }
+ extern (D) bool S_ISLNK()( uint mode ) { return S_ISTYPE( mode, S_IFLNK ); }
+ extern (D) bool S_ISSOCK()( uint mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
// Added since Lollipop
int utimensat(int dirfd, const char *pathname,
@@ -1740,19 +1740,19 @@ else version (CRuntime_Musl)
[...]
[diff truncated at 524288 bytes]
More information about the Gcc-cvs
mailing list