]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge upstream dmd, druntime 1017635a96, phobos 5a142da0a
authorIain Buclaw <ibuclaw@gdcproject.org>
Fri, 30 Jan 2026 09:25:49 +0000 (10:25 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Fri, 30 Jan 2026 10:24:27 +0000 (11:24 +0100)
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.

218 files changed:
gcc/d/decl.cc
gcc/d/dmd/MERGE
gcc/d/dmd/VERSION
gcc/d/dmd/aggregate.d
gcc/d/dmd/aggregate.h
gcc/d/dmd/arraytypes.d
gcc/d/dmd/arraytypes.h
gcc/d/dmd/attrib.d
gcc/d/dmd/attrib.h
gcc/d/dmd/cond.d
gcc/d/dmd/cond.h
gcc/d/dmd/cparse.d
gcc/d/dmd/cxxfrontend.d
gcc/d/dmd/dcast.d
gcc/d/dmd/dclass.d
gcc/d/dmd/declaration.d
gcc/d/dmd/declaration.h
gcc/d/dmd/delegatize.d
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dmodule.d
gcc/d/dmd/dscope.d
gcc/d/dmd/dstruct.d
gcc/d/dmd/dsymbol.d
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/enumsem.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/func.d
gcc/d/dmd/funcsem.d
gcc/d/dmd/hdrgen.d
gcc/d/dmd/iasmgcc.d
gcc/d/dmd/id.d
gcc/d/dmd/imphint.d
gcc/d/dmd/importc.d
gcc/d/dmd/initsem.d
gcc/d/dmd/location.d
gcc/d/dmd/mangle/package.d
gcc/d/dmd/mtype.d
gcc/d/dmd/mtype.h
gcc/d/dmd/nogc.d
gcc/d/dmd/nspace.d
gcc/d/dmd/nspace.h
gcc/d/dmd/optimize.d
gcc/d/dmd/parse.d
gcc/d/dmd/semantic2.d
gcc/d/dmd/semantic3.d
gcc/d/dmd/statementsem.d
gcc/d/dmd/template.h
gcc/d/dmd/templatesem.d
gcc/d/dmd/traits.d
gcc/d/dmd/typesem.d
gcc/d/typeinfo.cc
gcc/testsuite/gdc.dg/asm1.d
gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
gcc/testsuite/gdc.test/compilable/imports/imp18127a.c [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/imports/imp18127b.c [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/imports/imp20344.c [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/imports/imp20499.c [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test18127.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test20344.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test20499.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test3004.d
gcc/testsuite/gdc.test/compilable/testcstuff3.d
gcc/testsuite/gdc.test/compilable/uda_lambda.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/vcg-ast.d
gcc/testsuite/gdc.test/fail_compilation/b23686.d
gcc/testsuite/gdc.test/fail_compilation/checkimports2.d
gcc/testsuite/gdc.test/fail_compilation/diag10405.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/diag20888.d
gcc/testsuite/gdc.test/fail_compilation/diag23384.d
gcc/testsuite/gdc.test/fail_compilation/diag9679.d
gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail109.d
gcc/testsuite/gdc.test/fail_compilation/fail11714.d
gcc/testsuite/gdc.test/fail_compilation/fail15361.d
gcc/testsuite/gdc.test/fail_compilation/fail15616b.d
gcc/testsuite/gdc.test/fail_compilation/fail16.d
gcc/testsuite/gdc.test/fail_compilation/fail163.d
gcc/testsuite/gdc.test/fail_compilation/fail18219.d
gcc/testsuite/gdc.test/fail_compilation/fail19103.d
gcc/testsuite/gdc.test/fail_compilation/fail196.d
gcc/testsuite/gdc.test/fail_compilation/fail21547.d
gcc/testsuite/gdc.test/fail_compilation/fail23439.d
gcc/testsuite/gdc.test/fail_compilation/fail305.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail336.d
gcc/testsuite/gdc.test/fail_compilation/fail347.d
gcc/testsuite/gdc.test/fail_compilation/fail41.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail98.d
gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d
gcc/testsuite/gdc.test/fail_compilation/failcontracts.d
gcc/testsuite/gdc.test/fail_compilation/fix19613.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix20075.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix20318.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix20867.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix21042.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix21165.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fix21166.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/ice11153.d
gcc/testsuite/gdc.test/fail_compilation/ice19755.d
gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/lookup.d
gcc/testsuite/gdc.test/fail_compilation/mixinprop.d
gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
gcc/testsuite/gdc.test/fail_compilation/nogc3.d
gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
gcc/testsuite/gdc.test/fail_compilation/powinline.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/retscope3.d
gcc/testsuite/gdc.test/fail_compilation/seq_assign.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test15989.d
gcc/testsuite/gdc.test/fail_compilation/test18127.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test19661.d
gcc/testsuite/gdc.test/fail_compilation/test20489.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21215.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21304.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21317.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/union_conv.d
gcc/testsuite/gdc.test/runnable/placenew.d
gcc/testsuite/gdc.test/runnable/powinline.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/testaa2.d
gcc/testsuite/gdc.test/runnable/testinvariant.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/Makefile.am
libphobos/libdruntime/Makefile.in
libphobos/libdruntime/core/int128.d
libphobos/libdruntime/core/internal/array/capacity.d
libphobos/libdruntime/core/internal/array/concatenation.d
libphobos/libdruntime/core/internal/array/construction.d
libphobos/libdruntime/core/internal/array/utils.d
libphobos/libdruntime/core/internal/lifetime.d
libphobos/libdruntime/core/stdc/fenv.d
libphobos/libdruntime/core/stdc/math.d
libphobos/libdruntime/core/stdc/stdarg.d
libphobos/libdruntime/core/sys/bionic/err.d
libphobos/libdruntime/core/sys/bionic/string.d
libphobos/libdruntime/core/sys/darwin/err.d
libphobos/libdruntime/core/sys/darwin/string.d
libphobos/libdruntime/core/sys/dragonflybsd/err.d
libphobos/libdruntime/core/sys/dragonflybsd/string.d
libphobos/libdruntime/core/sys/freebsd/err.d
libphobos/libdruntime/core/sys/freebsd/string.d
libphobos/libdruntime/core/sys/linux/err.d
libphobos/libdruntime/core/sys/linux/linux/if_packet.d
libphobos/libdruntime/core/sys/linux/netinet/in_.d
libphobos/libdruntime/core/sys/linux/perf_event.d
libphobos/libdruntime/core/sys/linux/sched.d
libphobos/libdruntime/core/sys/linux/string.d
libphobos/libdruntime/core/sys/linux/sys/syscall.d [new file with mode: 0644]
libphobos/libdruntime/core/sys/linux/sys/time.d
libphobos/libdruntime/core/sys/linux/syscall.d [new file with mode: 0644]
libphobos/libdruntime/core/sys/linux/unistd.d
libphobos/libdruntime/core/sys/netbsd/err.d
libphobos/libdruntime/core/sys/netbsd/string.d
libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d
libphobos/libdruntime/core/sys/openbsd/err.d
libphobos/libdruntime/core/sys/openbsd/string.d
libphobos/libdruntime/core/sys/posix/netdb.d
libphobos/libdruntime/core/sys/posix/netinet/in_.d
libphobos/libdruntime/core/sys/posix/signal.d
libphobos/libdruntime/core/sys/posix/sys/ioctl.d
libphobos/libdruntime/core/sys/posix/sys/select.d
libphobos/libdruntime/core/sys/posix/sys/socket.d
libphobos/libdruntime/core/sys/posix/sys/stat.d
libphobos/libdruntime/core/sys/posix/sys/wait.d
libphobos/libdruntime/core/sys/solaris/err.d
libphobos/libdruntime/core/sys/windows/basetsd.d
libphobos/libdruntime/core/sys/windows/commctrl.d
libphobos/libdruntime/core/sys/windows/dde.d
libphobos/libdruntime/core/sys/windows/mmsystem.d
libphobos/libdruntime/core/sys/windows/ntdef.d
libphobos/libdruntime/core/sys/windows/ntsecapi.d
libphobos/libdruntime/core/sys/windows/oleauto.d
libphobos/libdruntime/core/sys/windows/shlobj.d
libphobos/libdruntime/core/sys/windows/stat.d
libphobos/libdruntime/core/sys/windows/threadaux.d
libphobos/libdruntime/core/sys/windows/vfw.d
libphobos/libdruntime/core/sys/windows/winbase.d
libphobos/libdruntime/core/sys/windows/wincrypt.d
libphobos/libdruntime/core/sys/windows/winnt.d
libphobos/libdruntime/core/sys/windows/winuser.d
libphobos/libdruntime/core/volatile.d
libphobos/libdruntime/object.d
libphobos/libdruntime/rt/lifetime.d
libphobos/libdruntime/rt/minfo.d
libphobos/src/MERGE
libphobos/src/Makefile.am
libphobos/src/Makefile.in
libphobos/src/std/algorithm/iteration.d
libphobos/src/std/algorithm/searching.d
libphobos/src/std/complex.d
libphobos/src/std/container/rbtree.d
libphobos/src/std/conv.d
libphobos/src/std/encoding.d
libphobos/src/std/file.d
libphobos/src/std/format/internal/write.d
libphobos/src/std/format/write.d
libphobos/src/std/functional.d
libphobos/src/std/internal/math/biguintcore.d
libphobos/src/std/internal/windows/bcrypt.d [deleted file]
libphobos/src/std/json.d
libphobos/src/std/math/algebraic.d
libphobos/src/std/math/exponential.d
libphobos/src/std/net/curl.d
libphobos/src/std/path.d
libphobos/src/std/random.d
libphobos/src/std/sumtype.d
libphobos/src/std/traits.d
libphobos/src/std/uuid.d
libphobos/src/std/variant.d

index c43270c61e2c94a815d01d855f6d9dbe0b785df0..0b915b5632a46eb398fe07a37ac1e68d8e6bb779 100644 (file)
@@ -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)));
index 58d19b4e951df74f48f5c4dfc988d400da22c64f..62d90e5770b5d58c127b0a718df0f874f6231a15 100644 (file)
@@ -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.
index e972d6e93a4d93c2a8779412bf4f62720139b03d..67e32f8d7ef1822a1a7ade3e259843c542fd3088 100644 (file)
@@ -1 +1 @@
-v2.111.0
+v2.112.0-beta.1
index 51d6fc45953946427ad92d2bd0c1b699d0e58616..6359674d4471adbb5398bf6e2cdae84d326d3b07 100644 (file)
@@ -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);
index 82f8aeca0808500bd231e572fa039e6aab5f2c22..d89755cea27ced17609bbf772b2acc7491971a9f 100644 (file)
@@ -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;
 
index 2cd446ea5ed798eb84ea57dca4ab707d0bb22c02..bed684b3a425ffdd04c14d9a7182472df7bd3887 100644 (file)
@@ -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);
index 28165f3ed8ea55e91bb5d70b6906cf9658a61f57..a06144332db5cdcbb307a851d24e8d579bbfafe4 100644 (file)
@@ -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;
index 1bfe7902a9201a11dc3064479d1f6840352e0a4c..a03e7bbdc0e5ce2c911c46655161ae96c7fa2722 100644 (file)
@@ -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)
index ef37e0adece1861a6cbd1b7e1a3ea471b5103e48..24d91abc62757c73acb5147c4fc9c05bff264dca 100644 (file)
@@ -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); }
 };
 
index 1b11a9f1803b5b4b60dd7189968c3e4358611b02..31c01f1853e6e0029d324069cbc6196e6312425e 100644 (file)
@@ -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;
index 174a8fb9aafcc393f6498c65f7faf4ebd1493445..0afa042f9daaaacf477bd3ef6947ece04aec67ae 100644 (file)
@@ -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); }
 };
index 1a2a1e9470ea2deac1195fd2eec1157b19161d01..70369ba20c7afb9f8df3fd5d4f199dfe6b5ebb6a 100644 (file)
@@ -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)
index 234b6523afbf51bf4be60a8b8924dc4615439aff..b61137ff20fa5925e087371ef6754dcfdc6eb811 100644 (file)
@@ -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);
index 86d2f0f07c3f9cfa6043cc781f95c03523c847f7..9e35dde296973baa6038bf26be4b981f4ca83662 100644 (file)
@@ -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)
         {
index 80d39fac4267585392a5f40e4ab2a6d0d067caeb..51ac939ade09f77cb96fb8c8b999b85c7572a555 100644 (file)
@@ -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.
index 4510927da711d592f04adb20fa7a1493fb7ff890..25e5c31dcc6fd32938b2d66d8529703b59cb8483 100644 (file)
@@ -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);
index c7e45526084d787dc5e02e7ee66d764ba59ab1a4..74ea20cb56f8dfc63fe42988b728cb4896c1503e 100644 (file)
@@ -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;
index 344130b5e31dff6041aa64a4ce899fe612e5a4e8..1f5dca66b598345ba8af8448d013891c62ea113a 100644 (file)
@@ -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;
index 13051db3789735e06bdd1b788e4e0e3288d9e20e..543c0e22e39f9212d03d0cd7c36e8b42a73d9263 100644 (file)
@@ -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;
index 0e0070aab5886ad16298b74eccedad354bd8bebb..33539d4bf0b803b758f551779dae299de25643a7 100644 (file)
@@ -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
  *
index 725a55e94184038e203cf652306ae44e6ed77790..c70e7d381b56623fd1b530c749181b82df0d40f7 100644 (file)
@@ -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;
index d07be2f131933eed36ea7b3727027ef93c7896cf..5aef3585cafe271c7ecbdfb5639e0c89a4f2a1f6 100644 (file)
@@ -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.
index 74ca9cbda4d338dd2ea5f3707d6871e4b3fa4430..e65068c7622b4eb056e1de5dc529534e1574bbde 100644 (file)
@@ -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; }
index 558d15608884f49b10c1233c5747502af34feb9c..77e7dabcb6cfac4e770148ed4a67858fec915787 100644 (file)
@@ -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);
 }
index acbac7a0e0476dd41b42e9a45ada295970b71719..43fb0b72e4ba6547432c86ca5cdb817a4557ef18 100644 (file)
@@ -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;
+}
index 215889574570e654c1e206f425b05134528e4f82..16e192da20ff75d46fa2521623e248d4bf79bcf4 100644 (file)
@@ -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
index 4f0d4e5f53f23cac683e6b9f9fade4f2329d715a..6d325e44c9641342900fcc3bb82122b085c8328d 100644 (file)
@@ -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)
index d65b163ee6683406bc00772e19e4d79d9010d48c..c29484d9e7bfe9841059b2bdbd26d64864ab19f6 100644 (file)
@@ -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();
index 3c8d90dd7eb61534133d6fa3b2c85a1125acb441..6b4298b3308b232aef0a515c14e9cd2fbc081550 100644 (file)
@@ -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); }
index b02f6ea64102c3de93bfa23b0e3ed91e6a6c5dbb..2576d7c0d056978c3de6062cfab8c86dfda88921 100644 (file)
@@ -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);
+    }
+}
index 064b67f960608ffd7e0840140a88c7adea54187b..6a573810a4b97f3f83dd5672ce2def0ec90d7b00 100644 (file)
@@ -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
index 1231496e41ab95a3d7575fd8455c2bc934b5cf13..10f6f154b2ff97f9d85543c0e809d3912539cec3 100644 (file)
@@ -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;
+}
index 61ff273c6b79fd87874bb23892f64a953f51a34c..0f8c8c67b927c32472945ac8796c7eade2793a68 100644 (file)
@@ -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)
index 3d6e6ab5b511cee028862dce0c8868844c12644f..4d9a758bb471573023fbd9151c265b42dbfcc263 100644 (file)
@@ -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)
index e1c22f2f04cac673b675a9a5fe662163b48989a8..2d10e6f991aff0f78963c660b7d17074361b0b22 100644 (file)
@@ -324,7 +324,6 @@ immutable Msgtable[] msgtable =
     { "__switch_error"},
     { "__ArrayCast"},
     { "_d_HookTraceImpl" },
-    { "_d_arraysetlengthTImpl"},
     { "_d_arraysetlengthT"},
     { "_d_arraysetlengthTTrace"},
     { "_d_arrayappendT" },
index 382a0f378633622dfa4ce48c98e9a1cc667ac45e..e22bcc8b123f223fb0d1bdf8b7cda3bcebdd0322 100644 (file)
@@ -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
index 2f88a21c049f731c003b0692d0644edd0c1fd13e..059de62b1f9c9f1e3221f88b6f21c263b77aeef6 100644 (file)
@@ -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;
+}
index 1ebccf77ee32956a5539b048e70aba30ae073ce9..7247d747974610728d733cb9bf021ebd25ec1207 100644 (file)
@@ -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);
index 393ffb8a92d419fd0842ef3968cf17047da8a1da..daff06f3d2c6590eb9cffd1a3daf539adf568dba 100644 (file)
@@ -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;
index 3ad2c7d57941ab689f14e71e20690cbe092478ce..cc797614ed0b5ebbaa514930a0289d2c8370d186 100644 (file)
@@ -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)
index a3e1a8ca858b79b993e13fb2c2e175b28a50f07c..c9b57449658ae04af3965d91ee79251259127f53 100644 (file)
@@ -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;
index 4d1938f4a723a41542d0763bec48682bda800d84..4d303acf3c3c59216c5c277466216f64e9241e5e 100644 (file)
@@ -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;
index f1494a409f6ecb3400009f735655a212c3b3a9a6..5e3c164acbb41c62c4d2a0f2a6586ddd70b88b88 100644 (file)
@@ -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;
 }
 
index 0c93f0e7994a86ec2810d8ec07ad91ec66e8d27e..b8116343d6fedf8bc935be7d1516d6b73707b1e7 100644 (file)
@@ -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";
index 7b4c302303da56296ff53021687aa2300f7370f2..782688b9de1c5b0408f00797f99effdda2d7355d 100644 (file)
@@ -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); }
 };
index 66b8c6a4953c5fbccc0d8c5e07103bbd56ccee69..b13f8c64584f9d32d407bb5dc9a7ce3d1c4cd706 100644 (file)
@@ -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.
index e68017c87e5505a0481af35bf7291d7250798ee4..c57f1d3f7f74d4a1b59fa50990ebd5513dc51a14 100644 (file)
@@ -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);
         }
 
index 1c58e63936d7cf7eb71735a7ff58c95ef3823d95..26f0fa8a254ff0b168da89c292ff79c77263831d 100644 (file)
@@ -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;
index a24af7bbbfcfe4281168da400107c0c4619db7bc..bafb2e7d8719364cd8e806967fe1791e0c2def52 100644 (file)
@@ -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)
                         {
index 0c9b6becb700d3890223775a61bfa6f7a98164e9..523ed7b39781839d5acc22f3648a94b192a46323 100644 (file)
@@ -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())
index 5576965ce4b2a0b9d8290fbf15f65eb69746c539..bfc41514804394570a4f83a1f3b9055ab72665de 100644 (file)
@@ -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); }
 };
index e5efce4a8bccafe427d1e4cb0a87423d747a1cdb..a9cf867f11475c674db9b09c7e962c0845309edd 100644 (file)
@@ -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]))
index 127a89d198422e7390532f290ebec688697ad6c9..8cce1732e87ee6ced8230992007ddf1a1b7d6990 100644 (file)
@@ -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;
             }
index d4c7a5865d25d521cf52e7d1d8ca532a1f05d882..ffbdfed6eb37eb7f74a7144b7f4221bb7d6ae273 100644 (file)
@@ -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())
index 026b12fb93e14fab77083807849c9ca4205e9b82..160d37846f29511227347e465f6f48f0d39fc4c1 100644 (file)
@@ -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;
              }
          }
index 1593eb6acd342ae711d670e9929d54498c33cd29..e2f36b01c94ac44289b0d79c3476c8e2e64beda9 100644 (file)
@@ -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" }
     }
 }
 
index f6aaf3b2a4ae193bfaea86daab9358deae2f9ce1..fb78ec76bca7e027e72fbfd3f6da8e5a53ad1182 100644 (file)
@@ -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 (file)
index 0000000..cd17315
--- /dev/null
@@ -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 (file)
index 0000000..cd17315
--- /dev/null
@@ -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 (file)
index 0000000..56ac79c
--- /dev/null
@@ -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 (file)
index 0000000..7ae7490
--- /dev/null
@@ -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 (file)
index 0000000..3d6b454
--- /dev/null
@@ -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 (file)
index 0000000..26ee9a3
--- /dev/null
@@ -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 (file)
index 0000000..3263aed
--- /dev/null
@@ -0,0 +1,3 @@
+// https://github.com/dlang/dmd/issues/20499
+// EXTRA_FILES: imports/imp20499.c
+import imports.imp20499;
index 23ec46f2905596b12f1104bfee15517341e439cc..664452ef4e686f9770255115c06a32164c54e045 100644 (file)
@@ -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)
index 89228a9bc4ab96082872f87db15e3dd059e0a182..08aa3b03d11d3535fcf6bcab3565901847f1f623 100644 (file)
@@ -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 (file)
index 0000000..df33174
--- /dev/null
@@ -0,0 +1,3 @@
+enum UDA;
+int fun() @UDA => 7;
+static assert(fun() == 7);
index 9197441affea872f75b1560d4270115e5d8b3813..bcb7256723c6921f7409a48fa8b255505861eaa5 100644 (file)
@@ -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;
+}));
index 4c2a5bd026d2e5fe32d310abaafab569b8a43efc..5838f5c8e10c2175c1682eac2d2e8209b02bcc12 100644 (file)
@@ -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"`
 ---
index 44c237f144f8cfd21a4038c2900f00c9e4d6bf1c..56e28e1ce7bb45b0d75d065f04cfc4adcd02a3fa 100644 (file)
@@ -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 (file)
index 28da8af..0000000
+++ /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;
-}
index 84af42533fcc58459de1a254a7381ac7c058640a..d030a98ec2c228f79ed01447d93c6506c7311652 100644 (file)
@@ -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()
 {
index 1fa4da5ffb9e30c08987eb6fab0ae2c971af164a..9cb17c00d74f2d3931c146702a64989ddf74e065 100644 (file)
@@ -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
 ---
 */
 
index 22e94e57596910eafa8bcc7d989d482ee4ddd791..50b8717adf316b5ef0d8c97a1860a08cb637327c 100644 (file)
@@ -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 (file)
index 0000000..ea144b2
--- /dev/null
@@ -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 (file)
index 0000000..9c04e9a
--- /dev/null
@@ -0,0 +1,18 @@
+/*\r
+TEST_OUTPUT:\r
+---\r
+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\r
+---\r
+*/\r
+\r
+enum A1 : int\r
+{\r
+    a,\r
+    b,\r
+}\r
+\r
+enum A2 : A1\r
+{\r
+    c,\r
+    d,\r
+}\r
index 003e65f9b807d5edb900dcd2144f578307d85a48..94f951f9f95371699b8c4a8a4b1923438e598463 100644 (file)
@@ -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`
 ---
 */
 
index abc47087ffaaf95232f8212fd6b10af552f89a46..f36f3e5831e96d0b99821291216ddf6805ac729d 100644 (file)
@@ -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
 ---
 */
 
index 8e5f9800a816e7e3050fce80b35fdea12f00a62b..aec716556a4fd1e6d72414746a53d82c94256c3b 100644 (file)
@@ -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
 ---
 */
 
index 4b209685ca4435811a3d75665c620867fffb17c8..4cbd591cbf828e56e67e2ab92531da5469cd8aaa 100644 (file)
@@ -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)`
index 4602d3de3bd61d3b0b6613dea0454db4a740eacb..ce021a95b8599641c20588011374896423ecc70d 100644 (file)
@@ -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 `;`
 ---
 */
 
index 7f8f028fa52dd61f1d6b3e3e62b5924a94deeba4..590bf23931c93317789ed14a31b18f732511c3f1 100644 (file)
@@ -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()
index bf4b189f6ebcf2914f0e0d5cf7c602dc28695213..f5fc27f1a89dae9287fc1ef0df5b360a681d0e89 100644 (file)
@@ -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;
index c1abd0df90af88d015d5ee24c00a055aac43055a..e617249ed71362851f5dd3547bd5269498b784aa 100644 (file)
@@ -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)?
index 78c596390b56e3d8f9afb65870fd315b50124d15..a5d4499f3fffbfd8c0e80e2499cc8637afdcbc46 100644 (file)
@@ -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
index 7a6a44a4a133ccfbb83767b4af5194523ea9a7e3..440a301de51451f137a969f4e8433e5fb4626f48 100644 (file)
@@ -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 }`
 ---
 */
 
index b070e581a4a72c6c0bf6ef8befc1327bedccf6dc..6f16bc1343669a9dce48ec3c0852d0c62ad481b8 100644 (file)
@@ -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 (file)
index aef1624..0000000
+++ /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";
-}
index 9df207120b364c78b7e820e3b91aa6768dca62d7..8fb9857d4dc4552ca7407bedfc56ec8da6847d25 100644 (file)
@@ -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 }`
 ---
 */
 
index c56acf5642cdef69da5d37fe218cbc7e0b641cf9..996990bd4001c1771851c4170defc03ffa8a978e 100644 (file)
@@ -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 (file)
index 6d89395..0000000
+++ /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;
-}
index 7541d3718c7b7f1af15b32344d781cdc88d47d41..20b18d19db5b1df7dddec13f2752d1a42394d586 100644 (file)
@@ -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
 ---
 */
 
index 79242b163eeab0768d26da1c217a7cdc6ebd7c68..ebd36a7cc1d2f6a711a33cac5af979d64aa5c685 100644 (file)
@@ -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;
index b6c3bc906a1533f7b5c5a7ba00fcb3808471553f..749d98f9bd0cac9895dedee4127404e4ccc1ae06 100644 (file)
@@ -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 (file)
index 0000000..beca56f
--- /dev/null
@@ -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 (file)
index 0000000..00f229d
--- /dev/null
@@ -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 (file)
index 0000000..f320300
--- /dev/null
@@ -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 (file)
index 0000000..0ccad09
--- /dev/null
@@ -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 (file)
index 0000000..b2b224e
--- /dev/null
@@ -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 (file)
index 0000000..1d38013
--- /dev/null
@@ -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 (file)
index 0000000..24dbf8b
--- /dev/null
@@ -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 (file)
index 0000000..8d6e695
--- /dev/null
@@ -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!");
+}
index 826bd8cd7ec16093fd5e418bbf67c4933f10cc27..936d987c152822e3a3bb8147a3ec0aa26a8a1f74 100644 (file)
@@ -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 `{`
 ---
 */
 
index 6d60fc43c1b2724d13c706201c2da13c0435bca5..2770676294c29d03a88cab5f53163731ee8d6643 100644 (file)
@@ -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 (file)
index 0000000..2ef629e
--- /dev/null
@@ -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 (file)
index 0000000..3cbbf7a
--- /dev/null
@@ -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;
+};
index fe752f2f4d74b22eb3feb8346a65b4d3bd5b6dfb..db7eedab30ac03b8a29aabd07a73f9dbeabf224f 100644 (file)
@@ -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)`
 ---
 */
 
index db8bf5968ddc70c57ff2b859e29d9f54d12d2e88..103c6b2a04737c92c81a7bf0d91c7120aeecb4cd 100644 (file)
@@ -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()
index 125ebcc926e54dfd77331de08d2e18ec7e136b8b..761e1d4c78c1209230cbeb170d182343294583be 100644 (file)
@@ -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)`
 ---
 */
 
index 6d8a70a2c46969630475da40ddf1ac638ee028ed..a73fd3cb2e6f80f132460a144d0fed7606bd3781 100644 (file)
@@ -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)`
 ---
 */
 
index 17daa96358b17a70d311db13285a8bf4ef6e1d48..f1a469b5445f234d1fe95f831ba720d0b2cfe92a 100644 (file)
@@ -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 (file)
index 0000000..bcced1b
--- /dev/null
@@ -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;
index ec6bd3ebce99645594b8462b487e95b78453e1a5..b49417436a534f5386106d79b747f9dfa8da11e5 100644 (file)
@@ -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 (file)
index 0000000..11ebacd
--- /dev/null
@@ -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;
+}
index 438fdd76e1b03a4caead2093f48ec85d180f8219..8802469de2c4bcce552c550a1362adae57129f43 100644 (file)
@@ -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 (file)
index 0000000..560bc34
--- /dev/null
@@ -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
+}
index 38ca33126724644efa7ddd18d656bb875490fb50..85b74bfad58331978834f6a36e84f900d862e75f 100644 (file)
@@ -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 (file)
index 0000000..ec0487c
--- /dev/null
@@ -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;
index 369c0a8624954e1e3719f0f1611ac0731324409b..712721487caa81f9f6b7d3dd21ebfac7e16a78bb 100644 (file)
@@ -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 (file)
index 0000000..1cd5350
--- /dev/null
@@ -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 (file)
index 0000000..5efa315
--- /dev/null
@@ -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 (file)
index 0000000..9789e2b
--- /dev/null
@@ -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 (file)
index 0000000..39b3963
--- /dev/null
@@ -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;
index 1173d14480d0d1765391dbe9bba85e81aa363952..a0ade760fe523861e1e6f07234e2cf6e0487eb06 100644 (file)
@@ -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 (file)
index 0000000..bd3ff49
--- /dev/null
@@ -0,0 +1,7 @@
+/+
+TEST_OUTPUT:
+---
+fail_compilation/uda_lambda.d(7): Error: declaration expected, not `=>`
+---
++/
+@a => 7 int b;
index f08809c4850052540972a8ef9af6f0252fff3c8e..134da36ecdbf389900368eed80024019a7036eb6 100644 (file)
@@ -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
 ---
 */
 
index d90d10a5e7445252831958b25fcdce4e21efe1f5..834a1f76bcbf3b9edf00369ea464a82f59d0f30b 100644 (file)
@@ -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 (file)
index 0000000..92d1c04
--- /dev/null
@@ -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");
+}
index e1abcb4418c5a4a6768f31099825a2a0ebd645f4..3d199d9841251fa0b19ea36a6521c0725435e1bc 100644 (file)
@@ -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;
index 0ce85571911704b530cbd5c6235756724ec6a9b8..11b8829b9fceb26d4eb71f20bdb1eea5d6de1a2c 100644 (file)
@@ -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();
 }
index 840f8dd4f9d9c0a9fe54a5c1ba093e5be9450cd2..62d90e5770b5d58c127b0a718df0f874f6231a15 100644 (file)
@@ -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.
index 4c8d65b76f5f44edd363fe6640df34b5d0f3b395..0e9b71bfa5d2ba5b0c50d99e6bb9832049553906 100644 (file)
@@ -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
 
index a6bbb76c216b482dba23e3a60d3e8d7a9decd37c..8543c6e53edcb2d751dd1ec7d007cef462860bbf 100644 (file)
@@ -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)
index 27c8b99d2cbf897db401a5ab121c180f3b40534c..b1247891e69cc69f1a7da15ecabb1fecc70af4fa 100644 (file)
@@ -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);
 }
index 10ce2c65c958f370eb4f7212f38b5bb5002097b5..11bd357d7c27dbc71cf29fb36d9d3d1442d8cd94 100644 (file)
 */
 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);
index 13ec5fad40fde63125e69c9064fc533d000a890f..fab2a5a9b7c1f0001009eee52f2c81772e43fe8a 100644 (file)
@@ -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;
                 }
             }
index 40e5a61bbded04564309ae6fe171ac9701c47710..76811ef3ffd0cb6364e6ea0a66573416ee6efc94 100644 (file)
@@ -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)
         {
index deaae3f95da63d7611c872acdcd2dadb4a6debbd..1d105e6ebf19a349d166e6578319d8a677c01bfb 100644 (file)
@@ -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;
+}
index a7446debae656495e63369bd5240832750a6da95..fd78de221d11a8a84f00a02c84204c9f04a8ad1d 100644 (file)
@@ -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();
+    }
+}
index ce77d5c1e6b2e6539a01b0c44af744ebd1b25b6c..7d42d5c8c023307aec1f796456cf61e40a9a4472 100644 (file)
@@ -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.");
index 1f384f9cbd46b7fd5c79c151d377f3fbf4bdfc78..5b78d6f61f363cc6dfa04d2265a31099caec73b2 100644 (file)
@@ -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.
index 0ba1ebe34e3899e3bd1f4405a2af68f336dc4657..c694dfb3ac3f1f10de56f3cc26c57e5218aa9a40 100644 (file)
@@ -316,7 +316,7 @@ else version (LDC)
 }
 else version (DigitalMars)
 {
-    void va_end(va_list ap) {}
+    void va_end()(va_list ap) {}
 }
 
 
index e2756e10c91ba3c2d93d1467ce6acc2e2bab5cd0..a14f21bb1ec1ed8ba0a6a7cdd7ada39e37745477 100644 (file)
@@ -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;
index 10a5610ac449ba467b70d846073eb43a6d8841c0..9430a7bab4e3f35e65ea088a814464bfaf0f3244 100644 (file)
@@ -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;
 
index d96c790f3b66e1db206a8ef57c26028cdcecb1c9..19b51626a16736f4046e670f9f9c6e4d4326729f 100644 (file)
@@ -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;
index ac988b58f0d40e860194fc22a89ae066a2b289de..14bae215cde78bf415217a5e410abe1a1bf4bafa 100644 (file)
@@ -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;
 
index c3693f85f5eab3a705ff024dfe326ae0e0a9e81b..7f7cf9467fa0b2b7a3ffad8234842bd6cf8226d8 100644 (file)
@@ -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;
index 1a85ba606a19b859ee5e5eda7f49cbacbfc60385..c15bb9268e581c5191cf9d4295e7402ebadd1531 100644 (file)
@@ -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;
 
index 8937e0ec70575b3954118bd56b7678050ca3a753..5cb443a6f8a20309f8e85962c53f06ccdc412d29 100644 (file)
@@ -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;
index 459e9115878e2983d883f23ed9c58b6fa30f2a07..ba7b3c019d909f52ecf94ff3342b89cdcebbe40b 100644 (file)
@@ -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;
 
index c3752de520706a73de43079ef7ffe8990a5b8d42..d346a0805ff4f8e83f0bd71666d5426e41dfaae4 100644 (file)
@@ -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;
index b50b6a33914051ecca37431f079dc5e8e39097b8..6dd95808d61c37c06dbfb4549182eb8843171764 100644 (file)
@@ -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
index 1b428f5aecccf37baae8888fb938318748ed85c4..f3c23572fb2ccc1d0db4c87d1eb41ab112081e76 100644 (file)
@@ -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;
 
index 0ad072974d5c527a6f7b09feb1318eb57ddc9e69..f8bedfb81bd90bc5a5acde6591c41ecce6a0a238 100644 (file)
@@ -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:
  */
index 5cd512e826301a4d36551e935608983c7062c197..0a940db65ed4d64e0bf834883e59b469bd57fffe 100644 (file)
@@ -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);
 }
index a8da398246120ebc3be432b2be4c165f3c33de99..7288231730d11d76719cbb55a1c725b62e1404b7 100644 (file)
@@ -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 (file)
index 0000000..9e313e1
--- /dev/null
@@ -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;
index 4b56229687c74bbbd45e2c7def464691b4d647c2..9eb48f1c5ef70a633288df9a8e235e4557f26912 100644 (file)
@@ -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 (file)
index 0000000..84d03e7
--- /dev/null
@@ -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;
index 548870268dbf43c0cf27114c82894ede6205206c..3194ec2962c6313e2777e777176b7076f5e1987b 100644 (file)
@@ -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, ...);
index 44eb66adc2fc0aff04d4760fe76e839eb64acb15..399ddea989a8668012327cbaec56a30fb77c2af5 100644 (file)
@@ -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;
index f1281da275b7ea00678e88594931bebc0f7b90ff..d83d22d56dd8c1c7fc5955864cf7fc746c163428 100644 (file)
@@ -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;
 
index 3901ea9703ba123f45f5107b222a36c9886077e4..ded053a36e49c057c6bc69fccb27a71c62d1087c 100644 (file)
@@ -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;
 
index b4676140e382251d7b22da72c1ac4f6a2739ab5b..271f2c4bfc63f608fbbf9559048361647b455d12 100644 (file)
@@ -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;
index 4480c94ac37b66d4b057a9059a82c10531dced7a..e0c33be9d678ed7617d5aa25b1348e8d0b04d070 100644 (file)
@@ -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;
 
index 70a5fe1901f342d2be7dddd8cc7056e413d599f0..4713f4b4955911a96160eb058d1376e38d7c9519 100644 (file)
@@ -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
index 5818ee6e22b6ae10a61ba6208aeab6bcb6756046..09a4a5e07d10d119db674ceb0d230322c68586ea 100644 (file)
@@ -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;
index e3d80fb0218026e09c5a7e42b965868e1ca876f6..bdc68687d0f62aee7a5fe3590c4384d3365190cf 100644 (file)
@@ -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");
 
index caf3ebafb5a59993899111563214dcb5433b95fd..27584d357c4d956ad346cad27fd03e9f0128e564 100644 (file)
@@ -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;
     }
index bd342503252163155021fa41bc8bea78d29dfb59..c8a88bddc0ca98f78f6e4d14b35a8fbe9699609f 100644 (file)
@@ -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;
     }
index 12824373d586484e279452ef9a819c96ee2d1385..5bdc22294c1db7ba5ec5e107160c00234e9ed4b2 100644 (file)
@@ -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 );
         }
index 328f620a42a2234e9652d49c71360f1148730522..ab79a4067509d209781ef997154b81872e95d6e4 100644 (file)
@@ -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)
 
     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);
@@ -1776,19 +1776,19 @@ else version (CRuntime_UClibc)
 
     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);
index f6b0674a3b161dc5a5769cb8d56911647c5609fb..131a9400dcf0a37da8414c8892cb4ad4b273d2b5 100644 (file)
@@ -127,7 +127,7 @@ version (CRuntime_Glibc)
 
     private
     {
-        extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
+        extern (D) int __WTERMSIG()(int status) { return status & 0x7F; }
     }
 
     //
@@ -135,128 +135,128 @@ version (CRuntime_Glibc)
     //       C headers as the parameter definition there is different and
     //       much more complicated.
     //
-    extern (D) int  WEXITSTATUS( int status )  { return ( status & 0xFF00 ) >> 8;   }
-    extern (D) int  WIFCONTINUED( int status ) { return status == __W_CONTINUED;    }
-    extern (D) bool WIFEXITED( int status )    { return __WTERMSIG( status ) == 0;  }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int  WEXITSTATUS()( int status )  { return ( status & 0xFF00 ) >> 8;   }
+    extern (D) int  WIFCONTINUED()( int status ) { return status == __W_CONTINUED;    }
+    extern (D) bool WIFEXITED()( int status )    { return __WTERMSIG( status ) == 0;  }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return ( cast(byte) ( ( status & 0x7F ) + 1 ) >> 1 ) > 0;
     }
-    extern (D) bool WIFSTOPPED( int status )   { return ( status & 0xFF ) == 0x7F;  }
-    extern (D) int  WSTOPSIG( int status )     { return WEXITSTATUS( status );      }
-    extern (D) int  WTERMSIG( int status )     { return status & 0x7F;              }
+    extern (D) bool WIFSTOPPED()( int status )   { return ( status & 0xFF ) == 0x7F;  }
+    extern (D) int  WSTOPSIG()( int status )     { return WEXITSTATUS( status );      }
+    extern (D) int  WTERMSIG()( int status )     { return status & 0x7F;              }
 }
 else version (Darwin)
 {
     @safe pure:
 
-    extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
-    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
-    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
-    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int _WSTATUS()(int status)         { return (status & 0x7F);           }
+    extern (D) int  WEXITSTATUS()( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED()( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED()( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
     }
-    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
-    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
-    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+    extern (D) bool WIFSTOPPED()( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG()( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG()( int status )     { return _WSTATUS( status );              }
 }
 else version (FreeBSD)
 {
     @safe pure:
 
-    extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
-    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
-    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
-    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int _WSTATUS()(int status)         { return (status & 0x7F);           }
+    extern (D) int  WEXITSTATUS()( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED()( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED()( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
     }
-    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
-    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
-    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+    extern (D) bool WIFSTOPPED()( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG()( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG()( int status )     { return _WSTATUS( status );              }
 }
 else version (NetBSD)
 {
     @safe pure:
 
-    extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
-    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
-    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
-    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int _WSTATUS()(int status)         { return (status & 0x7F);           }
+    extern (D) int  WEXITSTATUS()( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED()( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED()( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
     }
-    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
-    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
-    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+    extern (D) bool WIFSTOPPED()( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG()( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG()( int status )     { return _WSTATUS( status );              }
 }
 else version (OpenBSD)
 {
     @safe pure:
 
-    extern (D) int _WSTATUS(int status)         { return (status & 0x7F);                     }
-    extern (D) int  WEXITSTATUS(int status)   { return (status >> 8) & 0xFF;                  }
-    extern (D) int  WIFCONTINUED(int status)  { return (status & _WCONTINUED) == _WCONTINUED; }
-    extern (D) bool WIFEXITED(int status)     { return _WSTATUS(status) == 0;                 }
-    extern (D) bool WIFSIGNALED(int status)
+    extern (D) int _WSTATUS()(int status)         { return (status & 0x7F);                     }
+    extern (D) int  WEXITSTATUS()(int status)   { return (status >> 8) & 0xFF;                  }
+    extern (D) int  WIFCONTINUED()(int status)  { return (status & _WCONTINUED) == _WCONTINUED; }
+    extern (D) bool WIFEXITED()(int status)     { return _WSTATUS(status) == 0;                 }
+    extern (D) bool WIFSIGNALED()(int status)
     {
         return _WSTATUS(status) != _WSTOPPED && _WSTATUS(status) != 0;
     }
-    extern (D) bool WIFSTOPPED(int status)   { return (status & 0xFF) == _WSTOPPED; }
-    extern (D) int  WSTOPSIG(int status)     { return (status >> 8) & 0xFF;         }
-    extern (D) int  WTERMSIG(int status)     { return _WSTATUS(status);             }
+    extern (D) bool WIFSTOPPED()(int status)   { return (status & 0xFF) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG()(int status)     { return (status >> 8) & 0xFF;         }
+    extern (D) int  WTERMSIG()(int status)     { return _WSTATUS(status);             }
 }
 else version (DragonFlyBSD)
 {
     @safe pure:
 
-    extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
-    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
-    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
-    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int _WSTATUS()(int status)         { return (status & 0x7F);           }
+    extern (D) int  WEXITSTATUS()( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED()( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED()( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
     }
-    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
-    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
-    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+    extern (D) bool WIFSTOPPED()( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG()( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG()( int status )     { return _WSTATUS( status );              }
 }
 else version (Solaris)
 {
     @safe pure:
 
-    extern (D) int WEXITSTATUS(int status) { return (status >> 8) & 0xff; }
-    extern (D) int WIFCONTINUED(int status) { return (status & 0xffff) == 0xffff; }
-    extern (D) bool WIFEXITED(int status) { return (status & 0xff) == 0;     }
-    extern (D) bool WIFSIGNALED(int status) { return (status & 0xff) > 0 && (status & 0xff00) == 0; }
-    extern (D) bool WIFSTOPPED(int status) { return (status & 0xff) == 0x7f && (status & 0xff00) != 0; }
-    extern (D) int WSTOPSIG(int status) { return (status >> 8) & 0x7f; }
-    extern (D) int WTERMSIG(int status) { return (status & 0x7f); }
+    extern (D) int WEXITSTATUS()(int status) { return (status >> 8) & 0xff; }
+    extern (D) int WIFCONTINUED()(int status) { return (status & 0xffff) == 0xffff; }
+    extern (D) bool WIFEXITED()(int status) { return (status & 0xff) == 0;     }
+    extern (D) bool WIFSIGNALED()(int status) { return (status & 0xff) > 0 && (status & 0xff00) == 0; }
+    extern (D) bool WIFSTOPPED()(int status) { return (status & 0xff) == 0x7f && (status & 0xff00) != 0; }
+    extern (D) int WSTOPSIG()(int status) { return (status >> 8) & 0x7f; }
+    extern (D) int WTERMSIG()(int status) { return (status & 0x7f); }
 }
 else version (CRuntime_Bionic)
 {
     @safe pure:
-    extern (D) int  WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; }
-    extern (D) bool WIFEXITED( int status ) { return WTERMSIG(status) == 0; }
-    extern (D) bool WIFSIGNALED( int status ) { return WTERMSIG(status + 1) >= 2; }
-    extern (D) bool WIFSTOPPED( int status ) { return WTERMSIG(status) == 0x7F; }
-    extern (D) int  WSTOPSIG( int status ) { return WEXITSTATUS(status); }
-    extern (D) int  WTERMSIG( int status ) { return status & 0x7F; }
+    extern (D) int  WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; }
+    extern (D) bool WIFEXITED()( int status ) { return WTERMSIG(status) == 0; }
+    extern (D) bool WIFSIGNALED()( int status ) { return WTERMSIG(status + 1) >= 2; }
+    extern (D) bool WIFSTOPPED()( int status ) { return WTERMSIG(status) == 0x7F; }
+    extern (D) int  WSTOPSIG()( int status ) { return WEXITSTATUS(status); }
+    extern (D) int  WTERMSIG()( int status ) { return status & 0x7F; }
 }
 else version (CRuntime_Musl)
 {
     @safe pure:
-    extern (D) int  WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; }
-    extern (D) int  WIFCONTINUED( int status ) { return status == 0xffff; }
-    extern (D) bool WIFEXITED( int status ) { return WTERMSIG( status ) == 0; }
-    extern (D) bool WIFSIGNALED( int status ) { return (status&0xffff)-1U < 0xffU; }
-    extern (D) bool WIFSTOPPED( int status ) { return cast(short)(((status&0xffff)*0x10001)>>8) > 0x7f00; }
-    extern (D) int  WTERMSIG( int status ) { return status & 0x7F; }
+    extern (D) int  WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; }
+    extern (D) int  WIFCONTINUED()( int status ) { return status == 0xffff; }
+    extern (D) bool WIFEXITED()( int status ) { return WTERMSIG( status ) == 0; }
+    extern (D) bool WIFSIGNALED()( int status ) { return (status&0xffff)-1U < 0xffU; }
+    extern (D) bool WIFSTOPPED()( int status ) { return cast(short)(((status&0xffff)*0x10001)>>8) > 0x7f00; }
+    extern (D) int  WTERMSIG()( int status ) { return status & 0x7F; }
     alias WEXITSTATUS WSTOPSIG;
 }
 else version (CRuntime_UClibc)
@@ -265,7 +265,7 @@ else version (CRuntime_UClibc)
 
     private
     {
-        extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
+        extern (D) int __WTERMSIG()( int status ) { return status & 0x7F; }
     }
 
     //
@@ -273,23 +273,23 @@ else version (CRuntime_UClibc)
     //       C headers as the parameter definition there is different and
     //       much more complicated.
     //
-    extern (D) int  WEXITSTATUS( int status )  { return ( status & 0xFF00 ) >> 8;   }
-    extern (D) int  WIFCONTINUED( int status ) { return status == __W_CONTINUED;    }
-    extern (D) bool WIFEXITED( int status )    { return __WTERMSIG( status ) == 0;  }
-    extern (D) bool WIFSIGNALED( int status )
+    extern (D) int  WEXITSTATUS()( int status )  { return ( status & 0xFF00 ) >> 8;   }
+    extern (D) int  WIFCONTINUED()( int status ) { return status == __W_CONTINUED;    }
+    extern (D) bool WIFEXITED()( int status )    { return __WTERMSIG( status ) == 0;  }
+    extern (D) bool WIFSIGNALED()( int status )
     {
         return ( cast(ulong) ( ( status & 0xffff ) - 1U ) >> 1 ) < 0xffU;
     }
     version (MIPS32)
     {
-        extern (D) bool WIFSTOPPED( int status )   { return ( status & 0xFF ) == 0x7F;  }
+        extern (D) bool WIFSTOPPED()( int status )   { return ( status & 0xFF ) == 0x7F;  }
     }
     else
     {
-        extern (D) bool WIFSTOPPED( int status )   { return ( status & 0xFF ) == 0x7F && ( status & 0xFF00 );  }
+        extern (D) bool WIFSTOPPED()( int status )   { return ( status & 0xFF ) == 0x7F && ( status & 0xFF00 );  }
     }
-    extern (D) int  WSTOPSIG( int status )     { return WEXITSTATUS( status );      }
-    extern (D) int  WTERMSIG( int status )     { return status & 0x7F;              }
+    extern (D) int  WSTOPSIG()( int status )     { return WEXITSTATUS( status );      }
+    extern (D) int  WTERMSIG()( int status )     { return status & 0x7F;              }
 }
 else
 {
index f7876430150e1e4398a0c3399487cc7f7c00ff6c..03bdd7ecb98b2d3a9c56802029cc5bcc2b840ff1 100644 (file)
@@ -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.solaris.err;
 import core.stdc.stdarg : va_list;
index 1e5a45427c7f1e0f77cbe34eae8cf93d8448d141..d06bc5744ece58f99da39fda12e533935142536f 100644 (file)
@@ -44,20 +44,20 @@ enum ulong ADDRESS_TAG_BIT = 0x40000000000;
     alias uint UHALF_PTR;
     alias uint* PUHALF_PTR;
 
-    uint HandleToULong(void* h) { return(cast(uint) cast(ULONG_PTR) h); }
-    int HandleToLong(void* h)   { return(cast(int) cast(LONG_PTR) h); }
-    void* ULongToHandle(uint h) { return(cast(void*) cast(UINT_PTR) h); }
-    void* LongToHandle(int h)   { return(cast(void*) cast(INT_PTR) h); }
-    uint PtrToUlong(void* p)    { return(cast(uint) cast(ULONG_PTR) p); }
-    uint PtrToUint(void* p)     { return(cast(uint) cast(UINT_PTR) p); }
-    ushort PtrToUshort(void* p) { return(cast(ushort) cast(uint) cast(ULONG_PTR) p); }
-    int PtrToLong(void* p)      { return(cast(int) cast(LONG_PTR) p); }
-    int PtrToInt(void* p)       { return(cast(int) cast(INT_PTR) p); }
-    short PtrToShort(void* p)   { return(cast(short) cast(int) cast(LONG_PTR) p); }
-    void* IntToPtr(int i)       { return(cast(void*) cast(INT_PTR) i); }
-    void* UIntToPtr(uint ui)    { return(cast(void*) cast(UINT_PTR) ui); }
-    void* LongToPtr(int l)      { return(cast(void*) cast(LONG_PTR) l); }
-    void* ULongToPtr(uint ul)   { return(cast(void*) cast(ULONG_PTR) ul); }
+    uint HandleToULong()(void* h) { return(cast(uint) cast(ULONG_PTR) h); }
+    int HandleToLong()(void* h)   { return(cast(int) cast(LONG_PTR) h); }
+    void* ULongToHandle()(uint h) { return(cast(void*) cast(UINT_PTR) h); }
+    void* LongToHandle()(int h)   { return(cast(void*) cast(INT_PTR) h); }
+    uint PtrToUlong()(void* p)    { return(cast(uint) cast(ULONG_PTR) p); }
+    uint PtrToUint()(void* p)     { return(cast(uint) cast(UINT_PTR) p); }
+    ushort PtrToUshort()(void* p) { return(cast(ushort) cast(uint) cast(ULONG_PTR) p); }
+    int PtrToLong()(void* p)      { return(cast(int) cast(LONG_PTR) p); }
+    int PtrToInt()(void* p)       { return(cast(int) cast(INT_PTR) p); }
+    short PtrToShort()(void* p)   { return(cast(short) cast(int) cast(LONG_PTR) p); }
+    void* IntToPtr()(int i)       { return(cast(void*) cast(INT_PTR) i); }
+    void* UIntToPtr()(uint ui)    { return(cast(void*) cast(UINT_PTR) ui); }
+    void* LongToPtr()(int l)      { return(cast(void*) cast(LONG_PTR) l); }
+    void* ULongToPtr()(uint ul)   { return(cast(void*) cast(ULONG_PTR) ul); }
 
 } else {
     alias int __int3264;
@@ -72,16 +72,16 @@ enum uint ADDRESS_TAG_BIT = 0x80000000;
     alias ushort UHALF_PTR;
     alias ushort* PUHALF_PTR;
 
-    uint HandleToUlong(HANDLE h)      { return cast(uint) h; }
-    int HandleToLong(HANDLE h)        { return cast(int) h; }
-    HANDLE LongToHandle(LONG_PTR h)   { return cast(HANDLE)h; }
+    uint HandleToUlong()(HANDLE h)      { return cast(uint) h; }
+    int HandleToLong()(HANDLE h)        { return cast(int) h; }
+    HANDLE LongToHandle()(LONG_PTR h)   { return cast(HANDLE)h; }
     uint PtrToUlong(const(void)* p)    { return cast(uint) p; }
     uint PtrToUint(const(void)* p)     { return cast(uint) p; }
     int PtrToInt(const(void)* p)       { return cast(int) p; }
     ushort PtrToUshort(const(void)* p) { return cast(ushort) p; }
     short PtrToShort(const(void)* p)   { return cast(short) p; }
-    void* IntToPtr(int i)             { return cast(void*) i; }
-    void* UIntToPtr(uint ui)          { return cast(void*) ui; }
+    void* IntToPtr()(int i)             { return cast(void*) i; }
+    void* UIntToPtr()(uint ui)          { return cast(void*) ui; }
     alias IntToPtr LongToPtr;
     alias UIntToPtr ULongToPtr;
 }
index 073587f01c152efe43610546c3832c7b70457859..fcece45be46b614790957958cadee21057fc2585 100644 (file)
@@ -4937,8 +4937,8 @@ static if (_WIN32_WINNT >= 0x501) {
     alias NMLINK* PNMLINK;
 }
 
-uint INDEXTOOVERLAYMASK(uint i) { return i << 8; }
-uint INDEXTOSTATEIMAGEMASK(uint i) { return i << 12; }
+uint INDEXTOOVERLAYMASK()(uint i) { return i << 8; }
+uint INDEXTOSTATEIMAGEMASK()(uint i) { return i << 12; }
 
 template HANDLE_WM_NOTIFY(R) {
     private alias _prm_HANDLE_WM_NOTIFY = extern (Windows)
index 975c62e42f31a642c9472c187702899328b5b610..e4a75c5711abbbb939af1c9d55a22da8565cc07f 100644 (file)
@@ -31,7 +31,7 @@ struct DDEACK {
     ubyte bAppReturnCode;
     ubyte _bf;
 
-    @property ubyte reserved() { return cast(ubyte) (_bf & 0x3F); }
+    @property ubyte reserved()() { return cast(ubyte) (_bf & 0x3F); }
     @property bool  fBusy()    { return cast(bool)  (_bf & 0x40); }
     @property bool  fAck()     { return cast(bool)  (_bf & 0x80); }
 
@@ -49,7 +49,7 @@ struct DDEADVISE {
     short  cfFormat;
 
     @property ushort reserved()  { return cast(ushort) (_bf & 0x3FFF); }
-    @property bool   fDeferUpd() { return cast(bool)   (_bf & 0x4000); }
+    @property bool   fDeferUpd()() { return cast(bool)   (_bf & 0x4000); }
     @property bool   fAckReq()   { return cast(bool)   (_bf & 0x8000); }
 
     @property ushort reserved(ushort r) {
@@ -67,12 +67,12 @@ struct DDEDATA {
     byte   _Value;
 
     @property ushort unused()    { return cast(ushort) (_bf & 0x0FFF); }
-    @property bool   fResponse() { return cast(bool)   (_bf & 0x1000); }
+    @property bool   fResponse()() { return cast(bool)   (_bf & 0x1000); }
     @property bool   fRelease()  { return cast(bool)   (_bf & 0x2000); }
     @property bool   reserved()  { return cast(bool)   (_bf & 0x4000); }
     @property bool   fAckReq()   { return cast(bool)   (_bf & 0x8000); }
 
-    @property byte*  Value() return { return &_Value; }
+    @property byte*  Value() { return &_Value; }
 
     @property ushort unused(ushort r) {
         _bf = cast(ushort) ((_bf & ~0x0FFF) | (r & 0x0FFF));
@@ -90,38 +90,38 @@ struct DDEPOKE {
     short  cfFormat;
     byte   _Value;
 
-    @property ushort unused()    { return cast(ushort) (_bf & 0x1FFF); }
-    @property bool   fRelease()  { return cast(bool)   (_bf & 0x2000); }
-    @property ubyte  fReserved() { return cast(ubyte)  ((_bf & 0xC000) >>> 14); }
+    @property ushort unused()()    { return cast(ushort) (_bf & 0x1FFF); }
+    @property bool   fRelease()()  { return cast(bool)   (_bf & 0x2000); }
+    @property ubyte  fReserved()() { return cast(ubyte)  ((_bf & 0xC000) >>> 14); }
 
-    @property byte*  Value() return { return &_Value; }
+    @property byte*  Value() { return &_Value; }
 
-    @property ushort unused(ushort u) {
+    @property ushort unused()(ushort u) {
         _bf = cast(ushort) ((_bf & ~0x1FFF) | (u & 0x1FFF));
         return cast(ushort)(u & 0x1FFF);
     }
 
-    @property bool   fRelease(bool f)   { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
-    @property ubyte  fReserved(ubyte r) { _bf = cast(ushort) ((_bf & ~0xC000) | (r << 14)); return r; }
+    @property bool   fRelease()(bool f)   { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
+    @property ubyte  fReserved()(ubyte r) { _bf = cast(ushort) ((_bf & ~0xC000) | (r << 14)); return r; }
 }
 
 deprecated struct DDELN {
     ushort _bf;
     short  cfFormat;
 
-    @property ushort unused()    { return cast(ushort) (_bf & 0x1FFF); }
-    @property bool   fRelease()  { return cast(bool)   (_bf & 0x2000); }
-    @property bool   fDeferUpd() { return cast(bool)   (_bf & 0x4000); }
-    @property bool   fAckReq()   { return cast(bool)   (_bf & 0x8000); }
+    @property ushort unused()()    { return cast(ushort) (_bf & 0x1FFF); }
+    @property bool   fRelease()()  { return cast(bool)   (_bf & 0x2000); }
+    @property bool   fDeferUpd()() { return cast(bool)   (_bf & 0x4000); }
+    @property bool   fAckReq()()   { return cast(bool)   (_bf & 0x8000); }
 
-    @property ushort unused(ushort u) {
+    @property ushort unused()(ushort u) {
         _bf = cast(ushort)((_bf & ~0x1FFF) | (u & 0x1FFF));
         return cast(ushort)(u & 0x1FFF);
     }
 
-    @property bool   fRelease(bool f)  { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
-    @property bool   fDeferUpd(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; }
-    @property bool   fAckReq(bool f)   { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; }
+    @property bool   fRelease()(bool f)  { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
+    @property bool   fDeferUpd()(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; }
+    @property bool   fAckReq()(bool f)   { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; }
 }
 
 deprecated struct DDEUP {
@@ -129,23 +129,23 @@ deprecated struct DDEUP {
     short  cfFormat;
     byte   _rgb;
 
-    @property ushort unused()    { return cast(ushort) (_bf & 0x0FFF); }
-    @property bool   fAck()      { return cast(bool)   (_bf & 0x1000); }
-    @property bool   fRelease()  { return cast(bool)   (_bf & 0x2000); }
-    @property bool   fReserved() { return cast(bool)   (_bf & 0x4000); }
-    @property bool   fAckReq()   { return cast(bool)   (_bf & 0x8000); }
+    @property ushort unused()()    { return cast(ushort) (_bf & 0x0FFF); }
+    @property bool   fAck()()      { return cast(bool)   (_bf & 0x1000); }
+    @property bool   fRelease()()  { return cast(bool)   (_bf & 0x2000); }
+    @property bool   fReserved()() { return cast(bool)   (_bf & 0x4000); }
+    @property bool   fAckReq()()   { return cast(bool)   (_bf & 0x8000); }
 
-    @property byte*  rgb() return { return &_rgb; }
+    @property byte*  rgb()()       { return &_rgb; }
 
-    @property ushort unused(ushort r) {
+    @property ushort unused()(ushort r) {
         _bf = cast(ushort) ((_bf & ~0x0FFF) | (r & 0x0FFF));
         return cast(ushort)(r & 0x0FFF);
     }
 
-    @property bool   fAck(bool f)      { _bf = cast(ushort) ((_bf & ~0x1000) | (f << 12)); return f; }
-    @property bool   fRelease(bool f)  { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
-    @property bool   fReserved(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; }
-    @property bool   fAckReq(bool f)   { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; }
+    @property bool   fAck()(bool f)      { _bf = cast(ushort) ((_bf & ~0x1000) | (f << 12)); return f; }
+    @property bool   fRelease()(bool f)  { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; }
+    @property bool   fReserved()(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; }
+    @property bool   fAckReq()(bool f)   { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; }
 }
 
 extern (Windows) nothrow @nogc {
index 29c066e7c97a96809785b479ba2cd59f1711a906..2ce75aa7888fceb6cb4485d8052fd468e81a8f68 100644 (file)
@@ -283,8 +283,8 @@ enum MEVT_F_SHORT=0;
 enum MEVT_F_LONG=0x80000000;
 enum MEVT_F_CALLBACK=0x40000000;
 
-BYTE MEVT_EVENTTYPE(DWORD x) { return cast(BYTE)((x>>24) &0xFF); }
-DWORD MEVT_EVENTPARM(DWORD x) { return x & 0xFFFFFF; }
+BYTE MEVT_EVENTTYPE()(DWORD x) { return cast(BYTE)((x>>24) &0xFF); }
+DWORD MEVT_EVENTPARM()(DWORD x) { return x & 0xFFFFFF; }
 
 enum MEVT_SHORTMSG=0;
 enum MEVT_TEMPO=1;
@@ -766,22 +766,22 @@ enum MCI_FORMAT_TMSF=10;
 
 
 // Macros
-BYTE MCI_HMS_HOUR(DWORD t) { return cast(BYTE)(t); }
-BYTE MCI_HMS_MINUTE(DWORD t) { return cast(BYTE)(t>>>8); }
-BYTE MCI_HMS_SECOND(DWORD t) { return cast(BYTE)( t>>>16); }
-DWORD MCI_MAKE_HMS(BYTE h, BYTE m, BYTE s) { return h |(m<<8)|(cast(DWORD)(s)<<16); }
-DWORD MCI_MAKE_MSF(BYTE m, BYTE s, BYTE f) { return m |(s<<8)|(cast(DWORD)(f)<<16); }
+BYTE MCI_HMS_HOUR()(DWORD t) { return cast(BYTE)(t); }
+BYTE MCI_HMS_MINUTE()(DWORD t) { return cast(BYTE)(t>>>8); }
+BYTE MCI_HMS_SECOND()(DWORD t) { return cast(BYTE)( t>>>16); }
+DWORD MCI_MAKE_HMS()(BYTE h, BYTE m, BYTE s) { return h |(m<<8)|(cast(DWORD)(s)<<16); }
+DWORD MCI_MAKE_MSF()(BYTE m, BYTE s, BYTE f) { return m |(s<<8)|(cast(DWORD)(f)<<16); }
 DWORD MCI_MAKE_TMSF(BYTE t, BYTE m, BYTE s, BYTE f) {
  return t |(m<<8)|(s<<16)|(cast(DWORD)(f)<< 24); }
 
-BYTE MCI_MSF_MINUTE(DWORD t) { return cast(BYTE)(t); }
-BYTE MCI_MSF_SECOND(DWORD t) { return cast(BYTE)(t >>> 8); }
+BYTE MCI_MSF_MINUTE()(DWORD t) { return cast(BYTE)(t); }
+BYTE MCI_MSF_SECOND()(DWORD t) { return cast(BYTE)(t >>> 8); }
 BYTE MCI_MSF_FRAME(DWORD t)  {  return cast(BYTE)(t >>> 16); }
 
-BYTE MCI_TMSF_TRACK(DWORD t)  { return cast(BYTE)(t); }
-BYTE MCI_TMSF_MINUTE(DWORD t) { return cast(BYTE)(t>>8); }
-BYTE MCI_TMSF_SECOND(DWORD t) { return cast(BYTE)(t>>16); }
-BYTE MCI_TMSF_FRAME(DWORD t)  { return cast(BYTE)(t>>24); }
+BYTE MCI_TMSF_TRACK()(DWORD t)  { return cast(BYTE)(t); }
+BYTE MCI_TMSF_MINUTE()(DWORD t) { return cast(BYTE)(t>>8); }
+BYTE MCI_TMSF_SECOND()(DWORD t) { return cast(BYTE)(t>>16); }
+BYTE MCI_TMSF_FRAME()(DWORD t)  { return cast(BYTE)(t>>24); }
 
 
 enum MCI_NOTIFY_SUCCESSFUL=1;
index 160443312b4b4d8151269a347f693b840e3bb604..e45d0effcd9b4c69a326f73644d1031883e48d6c 100644 (file)
@@ -34,10 +34,10 @@ void InitializeObjectAttributes(OBJECT_ATTRIBUTES* p, UNICODE_STRING* n,
 }
 
 pragma(inline, true) @safe pure nothrow @nogc {
-    bool NT_SUCCESS(NTSTATUS Status)     { return Status >= 0; }
-    bool NT_INFORMATION(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; }
-    bool NT_WARNING(NTSTATUS Status)     { return ((cast(ULONG) Status) >> 30) == 2; }
-    bool NT_ERROR(NTSTATUS Status)       { return ((cast(ULONG) Status) >> 30) == 3; }
+    bool NT_SUCCESS()(NTSTATUS Status)     { return Status >= 0; }
+    bool NT_INFORMATION()(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; }
+    bool NT_WARNING()(NTSTATUS Status)     { return ((cast(ULONG) Status) >> 30) == 2; }
+    bool NT_ERROR()(NTSTATUS Status)       { return ((cast(ULONG) Status) >> 30) == 3; }
 }
 
 /*  In MinGW, NTSTATUS, UNICODE_STRING, STRING and their associated pointer
index 77101f669b4a6b3b9f1ade758522fdb2e642a334..7088cb10202ab4f3a32d41855843eac66eb5012f 100644 (file)
@@ -40,7 +40,7 @@ enum {
     LSA_MODE_LOG_FULL
 }
 
-bool LSA_SUCCESS(int x) { return x >= 0; }
+bool LSA_SUCCESS()(int x) { return x >= 0; }
 
 /*  TOTHINKABOUT: These constants don't have ANSI/Unicode versioned
  *  aliases.  Should we merge them anyway?
index f4bb40259ab8630949a9cce6dee645b9c22435d2..cc7b937a03a6b7539bfc2f315f082d1ddbaef244 100644 (file)
@@ -41,7 +41,7 @@ enum DISPATCH_PROPERTYGET = 2;
 enum DISPATCH_PROPERTYPUT = 4;
 enum DISPATCH_PROPERTYPUTREF = 8;
 
-//ULONG LHashValOfName(LCID l, OLECHAR* n) { return LHashValOfNameSys(SYSKIND.SYS_WIN32, l, n); }
+//ULONG LHashValOfName()(LCID l, OLECHAR* n) { return LHashValOfNameSys(SYSKIND.SYS_WIN32, l, n); }
 
 // DAC: These aren't in the 2003 SDK.
 //MACRO #define WHashValOfLHashVal(h) ((unsigned short)(0x0000ffff&(h)))
index bcd254b18edac847008c3c00ab7183f468271678..0e292d4c71de1a719a4f2665adcf3db9ea1e6cc6 100644 (file)
@@ -1034,35 +1034,35 @@ struct SHELLFLAGSTATE {
     BOOL fHideIcons : 1;
     UINT fRestFlags : 3;
 */
-    @property bool fShowAllObjects()       { return cast(bool) (_bf & 0x0001); }
-    @property bool fShowExtensions()       { return cast(bool) (_bf & 0x0002); }
-    @property bool fNoConfirmRecycle()     { return cast(bool) (_bf & 0x0004); }
-    @property bool fShowSysFiles()         { return cast(bool) (_bf & 0x0008); }
-    @property bool fShowCompColor()        { return cast(bool) (_bf & 0x0010); }
-    @property bool fDoubleClickInWebView() { return cast(bool) (_bf & 0x0020); }
-    @property bool fDesktopHTML()          { return cast(bool) (_bf & 0x0040); }
-    @property bool fWin95Classic()         { return cast(bool) (_bf & 0x0080); }
-    @property bool fDontPrettyPath()       { return cast(bool) (_bf & 0x0100); }
-    @property bool fShowAttribCol()        { return cast(bool) (_bf & 0x0200); }
-    @property bool fMapNetDrvBtn()         { return cast(bool) (_bf & 0x0400); }
-    @property bool fShowInfoTip()          { return cast(bool) (_bf & 0x0800); }
-    @property bool fHideIcons()            { return cast(bool) (_bf & 0x1000); }
-    @property ubyte fRestFlags()           { return cast(ubyte) (_bf >> 13); }
-
-    @property bool fShowAllObjects(bool f)       { _bf = cast(ushort) ((_bf & ~0xFFFE) | f);        return f; }
-    @property bool fShowExtensions(bool f)       { _bf = cast(ushort) ((_bf & ~0xFFFD) | (f <<  1)); return f; }
-    @property bool fNoConfirmRecycle(bool f)     { _bf = cast(ushort) ((_bf & ~0xFFFB) | (f <<  2)); return f; }
-    @property bool fShowSysFiles(bool f)         { _bf = cast(ushort) ((_bf & ~0xFFF8) | (f <<  3)); return f; }
-    @property bool fShowCompColor(bool f)        { _bf = cast(ushort) ((_bf & ~0xFFEF) | (f <<  4)); return f; }
-    @property bool fDoubleClickInWebView(bool f) { _bf = cast(ushort) ((_bf & ~0xFFDF) | (f <<  5)); return f; }
-    @property bool fDesktopHTML(bool f)          { _bf = cast(ushort) ((_bf & ~0xFFBF) | (f <<  6)); return f; }
-    @property bool fWin95Classic(bool f)         { _bf = cast(ushort) ((_bf & ~0xFF8F) | (f <<  7)); return f; }
-    @property bool fDontPrettyPath(bool f)       { _bf = cast(ushort) ((_bf & ~0xFEFF) | (f <<  8)); return f; }
-    @property bool fShowAttribCol(bool f)        { _bf = cast(ushort) ((_bf & ~0xFDFF) | (f <<  9)); return f; }
-    @property bool fMapNetDrvBtn(bool f)         { _bf = cast(ushort) ((_bf & ~0xFBFF) | (f << 10)); return f; }
-    @property bool fShowInfoTip(bool f)          { _bf = cast(ushort) ((_bf & ~0xF8FF) | (f << 11)); return f; }
-    @property bool fHideIcons(bool f)            { _bf = cast(ushort) ((_bf & ~0xEFFF) | (f << 12)); return f; }
-    @property ubyte fRestFlags(ubyte f)          { _bf = cast(ushort) ((_bf & ~0x1FFF) | (f << 13)); return cast(ubyte) (f & 7); }
+    @property bool fShowAllObjects()()       { return cast(bool) (_bf & 0x0001); }
+    @property bool fShowExtensions()()       { return cast(bool) (_bf & 0x0002); }
+    @property bool fNoConfirmRecycle()()     { return cast(bool) (_bf & 0x0004); }
+    @property bool fShowSysFiles()()         { return cast(bool) (_bf & 0x0008); }
+    @property bool fShowCompColor()()        { return cast(bool) (_bf & 0x0010); }
+    @property bool fDoubleClickInWebView()() { return cast(bool) (_bf & 0x0020); }
+    @property bool fDesktopHTML()()          { return cast(bool) (_bf & 0x0040); }
+    @property bool fWin95Classic()()         { return cast(bool) (_bf & 0x0080); }
+    @property bool fDontPrettyPath()()       { return cast(bool) (_bf & 0x0100); }
+    @property bool fShowAttribCol()()        { return cast(bool) (_bf & 0x0200); }
+    @property bool fMapNetDrvBtn()()         { return cast(bool) (_bf & 0x0400); }
+    @property bool fShowInfoTip()()          { return cast(bool) (_bf & 0x0800); }
+    @property bool fHideIcons()()            { return cast(bool) (_bf & 0x1000); }
+    @property ubyte fRestFlags()()           { return cast(ubyte) (_bf >> 13); }
+
+    @property bool fShowAllObjects()(bool f)       { _bf = cast(ushort) ((_bf & ~0xFFFE) | f);        return f; }
+    @property bool fShowExtensions()(bool f)       { _bf = cast(ushort) ((_bf & ~0xFFFD) | (f <<  1)); return f; }
+    @property bool fNoConfirmRecycle()(bool f)     { _bf = cast(ushort) ((_bf & ~0xFFFB) | (f <<  2)); return f; }
+    @property bool fShowSysFiles()(bool f)         { _bf = cast(ushort) ((_bf & ~0xFFF8) | (f <<  3)); return f; }
+    @property bool fShowCompColor()(bool f)        { _bf = cast(ushort) ((_bf & ~0xFFEF) | (f <<  4)); return f; }
+    @property bool fDoubleClickInWebView()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFDF) | (f <<  5)); return f; }
+    @property bool fDesktopHTML()(bool f)          { _bf = cast(ushort) ((_bf & ~0xFFBF) | (f <<  6)); return f; }
+    @property bool fWin95Classic()(bool f)         { _bf = cast(ushort) ((_bf & ~0xFF8F) | (f <<  7)); return f; }
+    @property bool fDontPrettyPath()(bool f)       { _bf = cast(ushort) ((_bf & ~0xFEFF) | (f <<  8)); return f; }
+    @property bool fShowAttribCol()(bool f)        { _bf = cast(ushort) ((_bf & ~0xFDFF) | (f <<  9)); return f; }
+    @property bool fMapNetDrvBtn()(bool f)         { _bf = cast(ushort) ((_bf & ~0xFBFF) | (f << 10)); return f; }
+    @property bool fShowInfoTip()(bool f)          { _bf = cast(ushort) ((_bf & ~0xF8FF) | (f << 11)); return f; }
+    @property bool fHideIcons()(bool f)            { _bf = cast(ushort) ((_bf & ~0xEFFF) | (f << 12)); return f; }
+    @property ubyte fRestFlags()(ubyte f)          { _bf = cast(ushort) ((_bf & ~0x1FFF) | (f << 13)); return cast(ubyte) (f & 7); }
 }
 alias SHELLFLAGSTATE* LPSHELLFLAGSTATE;
 
@@ -1118,56 +1118,56 @@ static if (_WIN32_WINNT >= 0x500) {
         BOOL fShowSuperHidden : 1;
         BOOL fNoNetCrawling : 1;
     */
-        @property bool fShowAllObjects()       { return cast(bool) (_bf1 & 0x00000001); }
-        @property bool fShowExtensions()       { return cast(bool) (_bf1 & 0x00000002); }
-        @property bool fNoConfirmRecycle()     { return cast(bool) (_bf1 & 0x00000004); }
-        @property bool fShowSysFiles()         { return cast(bool) (_bf1 & 0x00000008); }
-        @property bool fShowCompColor()        { return cast(bool) (_bf1 & 0x00000010); }
-        @property bool fDoubleClickInWebView() { return cast(bool) (_bf1 & 0x00000020); }
-        @property bool fDesktopHTML()          { return cast(bool) (_bf1 & 0x00000040); }
-        @property bool fWin95Classic()         { return cast(bool) (_bf1 & 0x00000080); }
-        @property bool fDontPrettyPath()       { return cast(bool) (_bf1 & 0x00000100); }
-        @property bool fShowAttribCol()        { return cast(bool) (_bf1 & 0x00000200); }
-        @property bool fMapNetDrvBtn()         { return cast(bool) (_bf1 & 0x00000400); }
-        @property bool fShowInfoTip()          { return cast(bool) (_bf1 & 0x00000800); }
-        @property bool fHideIcons()            { return cast(bool) (_bf1 & 0x00001000); }
-        @property bool fWebView()              { return cast(bool) (_bf1 & 0x00002000); }
-        @property bool fFilter()               { return cast(bool) (_bf1 & 0x00004000); }
-        @property bool fShowSuperHidden()      { return cast(bool) (_bf1 & 0x00008000); }
-        @property bool fNoNetCrawling()        { return cast(bool) (_bf1 & 0x00010000); }
-
-        @property bool fShowAllObjects(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFE) | f);         return f; }
-        @property bool fShowExtensions(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFD) | (f <<  1)); return f; }
-        @property bool fNoConfirmRecycle(bool f)     { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFB) | (f <<  2)); return f; }
-        @property bool fShowSysFiles(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFF8) | (f <<  3)); return f; }
-        @property bool fShowCompColor(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFEF) | (f <<  4)); return f; }
-        @property bool fDoubleClickInWebView(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFDF) | (f <<  5)); return f; }
-        @property bool fDesktopHTML(bool f)          { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFBF) | (f <<  6)); return f; }
-        @property bool fWin95Classic(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFF8F) | (f <<  7)); return f; }
-        @property bool fDontPrettyPath(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFEFF) | (f <<  8)); return f; }
-        @property bool fShowAttribCol(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFDFF) | (f <<  9)); return f; }
-        @property bool fMapNetDrvBtn(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFBFF) | (f << 10)); return f; }
-        @property bool fShowInfoTip(bool f)          { _bf1 = cast(uint) ((_bf1 & ~0xFFFFF8FF) | (f << 11)); return f; }
-        @property bool fHideIcons(bool f)            { _bf1 = cast(uint) ((_bf1 & ~0xFFFFEFFF) | (f << 12)); return f; }
-        @property bool fWebView(bool f)              { _bf1 = cast(uint) ((_bf1 & ~0xFFFFDFFF) | (f << 13)); return f; }
-        @property bool fFilter(bool f)               { _bf1 = cast(uint) ((_bf1 & ~0xFFFFBFFF) | (f << 14)); return f; }
-        @property bool fShowSuperHidden(bool f)      { _bf1 = cast(uint) ((_bf1 & ~0xFFFF8FFF) | (f << 15)); return f; }
-        @property bool fNoNetCrawling(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFEFFFF) | (f << 16)); return f; }
+        @property bool fShowAllObjects()()       { return cast(bool) (_bf1 & 0x00000001); }
+        @property bool fShowExtensions()()       { return cast(bool) (_bf1 & 0x00000002); }
+        @property bool fNoConfirmRecycle()()     { return cast(bool) (_bf1 & 0x00000004); }
+        @property bool fShowSysFiles()()         { return cast(bool) (_bf1 & 0x00000008); }
+        @property bool fShowCompColor()()        { return cast(bool) (_bf1 & 0x00000010); }
+        @property bool fDoubleClickInWebView()() { return cast(bool) (_bf1 & 0x00000020); }
+        @property bool fDesktopHTML()()          { return cast(bool) (_bf1 & 0x00000040); }
+        @property bool fWin95Classic()()         { return cast(bool) (_bf1 & 0x00000080); }
+        @property bool fDontPrettyPath()()       { return cast(bool) (_bf1 & 0x00000100); }
+        @property bool fShowAttribCol()()        { return cast(bool) (_bf1 & 0x00000200); }
+        @property bool fMapNetDrvBtn()()         { return cast(bool) (_bf1 & 0x00000400); }
+        @property bool fShowInfoTip()()          { return cast(bool) (_bf1 & 0x00000800); }
+        @property bool fHideIcons()()            { return cast(bool) (_bf1 & 0x00001000); }
+        @property bool fWebView()()              { return cast(bool) (_bf1 & 0x00002000); }
+        @property bool fFilter()()               { return cast(bool) (_bf1 & 0x00004000); }
+        @property bool fShowSuperHidden()()      { return cast(bool) (_bf1 & 0x00008000); }
+        @property bool fNoNetCrawling()()        { return cast(bool) (_bf1 & 0x00010000); }
+
+        @property bool fShowAllObjects()(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFE) | f);         return f; }
+        @property bool fShowExtensions()(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFD) | (f <<  1)); return f; }
+        @property bool fNoConfirmRecycle()(bool f)     { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFB) | (f <<  2)); return f; }
+        @property bool fShowSysFiles()(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFF8) | (f <<  3)); return f; }
+        @property bool fShowCompColor()(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFEF) | (f <<  4)); return f; }
+        @property bool fDoubleClickInWebView()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFDF) | (f <<  5)); return f; }
+        @property bool fDesktopHTML()(bool f)          { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFBF) | (f <<  6)); return f; }
+        @property bool fWin95Classic()(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFF8F) | (f <<  7)); return f; }
+        @property bool fDontPrettyPath()(bool f)       { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFEFF) | (f <<  8)); return f; }
+        @property bool fShowAttribCol()(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFDFF) | (f <<  9)); return f; }
+        @property bool fMapNetDrvBtn()(bool f)         { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFBFF) | (f << 10)); return f; }
+        @property bool fShowInfoTip()(bool f)          { _bf1 = cast(uint) ((_bf1 & ~0xFFFFF8FF) | (f << 11)); return f; }
+        @property bool fHideIcons()(bool f)            { _bf1 = cast(uint) ((_bf1 & ~0xFFFFEFFF) | (f << 12)); return f; }
+        @property bool fWebView()(bool f)              { _bf1 = cast(uint) ((_bf1 & ~0xFFFFDFFF) | (f << 13)); return f; }
+        @property bool fFilter()(bool f)               { _bf1 = cast(uint) ((_bf1 & ~0xFFFFBFFF) | (f << 14)); return f; }
+        @property bool fShowSuperHidden()(bool f)      { _bf1 = cast(uint) ((_bf1 & ~0xFFFF8FFF) | (f << 15)); return f; }
+        @property bool fNoNetCrawling()(bool f)        { _bf1 = cast(uint) ((_bf1 & ~0xFFFEFFFF) | (f << 16)); return f; }
     /*
         BOOL fSepProcess : 1;
         BOOL fStartPanelOn : 1;
         BOOL fShowStartPage : 1;
         UINT fSpareFlags : 13;
     */
-        @property bool fSepProcess()           { return cast(bool) (_bf2 & 0x00000001); }
-        @property bool fStartPanelOn()         { return cast(bool) (_bf2 & 0x00000002); }
-        @property bool fShowStartPage()        { return cast(bool) (_bf2 & 0x00000004); }
-        @property ushort fSpareFlags()         { return cast(ushort) ((_bf2 & 0x0000FFF8) >> 3); }
-
-        @property bool fSepProcess(bool f)     { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFE) | f);        return f; }
-        @property bool fStartPanelOn(bool f)   { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFD) | (f << 1)); return f; }
-        @property bool fShowStartPage(bool f)  { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFB) | (f << 2)); return f; }
-        @property ushort fSpareFlags(ushort f) {
+        @property bool fSepProcess()()           { return cast(bool) (_bf2 & 0x00000001); }
+        @property bool fStartPanelOn()()         { return cast(bool) (_bf2 & 0x00000002); }
+        @property bool fShowStartPage()()        { return cast(bool) (_bf2 & 0x00000004); }
+        @property ushort fSpareFlags()()         { return cast(ushort) ((_bf2 & 0x0000FFF8) >> 3); }
+
+        @property bool fSepProcess()(bool f)     { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFE) | f);        return f; }
+        @property bool fStartPanelOn()(bool f)   { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFD) | (f << 1)); return f; }
+        @property bool fShowStartPage()(bool f)  { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFB) | (f << 2)); return f; }
+        @property ushort fSpareFlags()(ushort f) {
             _bf2 = cast(ushort) ((_bf2 & ~0xFFFF0007) | ((f & 0x1FFF) << 3));
             return cast(ushort) (f & 0x1FFF);
         }
index 85ed24f93d8cf40d4a2645c7cdddd2285d697899..dfc7d490c42f8754cdce65b218ed5f81ee0dfc0f 100644 (file)
@@ -24,11 +24,11 @@ enum S_IFNAM  = 0x5000;
 
 @safe pure
 {
-int S_ISREG(int m)  { return (m & S_IFMT) == S_IFREG; }
-int S_ISBLK(int m)  { return (m & S_IFMT) == S_IFBLK; }
-int S_ISNAM(int m)  { return (m & S_IFMT) == S_IFNAM; }
-int S_ISDIR(int m)  { return (m & S_IFMT) == S_IFDIR; }
-int S_ISCHR(int m)  { return (m & S_IFMT) == S_IFCHR; }
+int S_ISREG()(int m)  { return (m & S_IFMT) == S_IFREG; }
+int S_ISBLK()(int m)  { return (m & S_IFMT) == S_IFBLK; }
+int S_ISNAM()(int m)  { return (m & S_IFMT) == S_IFNAM; }
+int S_ISDIR()(int m)  { return (m & S_IFMT) == S_IFDIR; }
+int S_ISCHR()(int m)  { return (m & S_IFMT) == S_IFCHR; }
 }
 
 version (CRuntime_Microsoft)
index dae8896d4b08795fa4edbc03790827a28bb299f8..40b833c1aaf8350bbc16f26a5fa31b4c85419670 100644 (file)
@@ -311,8 +311,8 @@ struct thread_aux
             enum TEB_offset_TlsSlots = 0xE10;
             enum TEB_offset_TlsExpansionSlots = 0xF94;
         }
-        void* tlsSlotsAdr(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; }
-        ref void* tlsExpansionSlots(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); }
+        void* tlsSlotsAdr()(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; }
+        ref void* tlsExpansionSlots()(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); }
 
         import core.stdc.string;
         void*[64] slots = void;
index c0f22a9fb5b886a253b250b6db4423da2947551c..313895f4acb4c3c0dd34ecf032a9c15c968094f3 100644 (file)
@@ -2115,75 +2115,75 @@ enum {
  * message wrapper
  */
 
-BOOL capSetCallbackOnError(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_ERROR, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnStatus(HWND hWnd, LPVOID fpProc)               { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_STATUS, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnYield(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_YIELD, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnFrame(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_FRAME, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnVideoStream(HWND hWnd, LPVOID fpProc)          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnWaveStream(HWND hWnd, LPVOID fpProc)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0, cast(LPARAM)fpProc); }
-BOOL capSetCallbackOnCapControl(HWND hWnd, LPVOID fpProc)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, cast(LPARAM)fpProc); }
-
-BOOL capSetUserData(HWND hWnd, LPARAM lUser)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_USER_DATA, 0, lUser); }
-BOOL capGetUserData(HWND hWnd)                                      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_USER_DATA, 0, 0); }
-
-BOOL capDriverConnect(HWND hWnd, WPARAM i)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_CONNECT, i, 0); }
-BOOL capDriverDisconnect(HWND hWnd)                                 { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0); }
-BOOL capDriverGetName(HWND hWnd, LPTSTR szName, WPARAM wSize)       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_NAME, wSize, cast(LPARAM)szName); }
-BOOL capDriverGetVersion(HWND hWnd, LPTSTR szVer, WPARAM wSize)     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_VERSION, wSize, cast(LPARAM)szVer); }
-BOOL capDriverGetCaps(HWND hWnd, LPCAPDRIVERCAPS s, WPARAM wSize)   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_CAPS, wSize, cast(LPARAM)s); }
-
-BOOL capFileSetCaptureFile(HWND hWnd, LPTSTR szName)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0, cast(LPARAM)szName); }
-BOOL capFileGetCaptureFile(HWND hWnd, LPTSTR szName, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_GET_CAPTURE_FILE, wSize, cast(LPARAM)szName); }
-BOOL capFileAlloc(HWND hWnd, WPARAM wSize)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_ALLOCATE, wSize, 0); }
-BOOL capFileSaveAs(HWND hWnd, LPTSTR szName)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEAS, 0, cast(LPARAM)szName); }
-BOOL capFileSetInfoChunk(HWND hWnd, LPCAPINFOCHUNK lpInfoChunk)     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_INFOCHUNK, 0, cast(LPARAM)lpInfoChunk); }
-BOOL capFileSaveDIB(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEDIB, 0, cast(LPARAM)szName); }
-
-BOOL capEditCopy(HWND hWnd)                                         { return cast(BOOL)AVICapSM(hWnd, WM_CAP_EDIT_COPY, 0, 0); }
-
-BOOL capSetAudioFormat(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize)   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_AUDIOFORMAT, wSize, cast(LPARAM)s); }
-DWORD capGetAudioFormat(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize)  { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, wSize, cast(LPARAM)s); }
-DWORD capGetAudioFormatSize(HWND hWnd)                              { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, 0, 0); }
-
-BOOL capDlgVideoFormat(HWND hWnd)                                   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0); }
-BOOL capDlgVideoSource(HWND hWnd)                                   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0); }
-BOOL capDlgVideoDisplay(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0); }
-BOOL capDlgVideoCompression(HWND hWnd)                              { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0); }
-
-DWORD capGetVideoFormat(HWND hWnd, void* s, WPARAM wSize)           { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, wSize, cast(LPARAM)s); }
-DWORD capGetVideoFormatSize(HWND hWnd)                              { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); }
-BOOL capSetVideoFormat(HWND hWnd, void* s, WPARAM wSize)            { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_VIDEOFORMAT, wSize, cast(LPARAM)s); }
-
-BOOL capPreview(HWND hWnd, BOOL f)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEW, cast(WPARAM)f, 0); }
-BOOL capPreviewRate(HWND hWnd, WPARAM wMS)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEWRATE, wMS, 0); }
-BOOL capOverlay(HWND hWnd, BOOL f)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_OVERLAY, cast(WPARAM)f, 0); }
-BOOL capPreviewScale(HWND hWnd, BOOL f)                             { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCALE, cast(WPARAM)f, 0); }
-BOOL capGetStatus(HWND hWnd, LPCAPSTATUS s, WPARAM wSize)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_STATUS, wSize, cast(LPARAM)s); }
-BOOL capSetScrollPos(HWND hWnd, LPPOINT lpP)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCROLL, 0, cast(LPARAM)lpP); }
-
-BOOL capGrabFrame(HWND hWnd)                                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME, 0, 0); }
-BOOL capGrabFrameNoStop(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0); }
-
-BOOL capCaptureSequence(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE, 0, 0); }
-BOOL capCaptureSequenceNoFile(HWND hWnd)                            { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); }
-BOOL capCaptureStop(HWND hWnd)                                      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_STOP, 0, 0); }
-BOOL capCaptureAbort(HWND hWnd)                                     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_ABORT, 0, 0); }
-
-BOOL capCaptureSingleFrameOpen(HWND hWnd)                           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_OPEN, 0, 0); }
-BOOL capCaptureSingleFrameClose(HWND hWnd)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0); }
-BOOL capCaptureSingleFrame(HWND hWnd)                               { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME, 0, 0); }
-
-BOOL capCaptureGetSetup(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); }
-BOOL capCaptureSetSetup(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); }
-
-BOOL capSetMCIDeviceName(HWND hWnd, LPTSTR szName)                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_MCI_DEVICE, 0, cast(LPARAM)szName); }
-BOOL capGetMCIDeviceName(HWND hWnd, LPTSTR szName, WPARAM wSize)    { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_MCI_DEVICE, wSize, cast(LPARAM)szName); }
-
-BOOL capPaletteOpen(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_OPEN, 0, cast(LPARAM)szName); }
-BOOL capPaletteSave(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_SAVE, 0, cast(LPARAM)szName); }
-BOOL capPalettePaste(HWND hWnd)                                     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_PASTE, 0, 0); }
-BOOL capPaletteAuto(HWND hWnd, WPARAM iFrames, LPARAM iColors)      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_AUTOCREATE, iFrames, iColors); }
-BOOL capPaletteManual(HWND hWnd, WPARAM fGrab, LPARAM iColors)      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_MANUALCREATE, fGrab, iColors); }
+BOOL capSetCallbackOnError()(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_ERROR, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnStatus()(HWND hWnd, LPVOID fpProc)               { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_STATUS, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnYield()(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_YIELD, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnFrame()(HWND hWnd, LPVOID fpProc)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_FRAME, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnVideoStream()(HWND hWnd, LPVOID fpProc)          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnWaveStream()(HWND hWnd, LPVOID fpProc)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0, cast(LPARAM)fpProc); }
+BOOL capSetCallbackOnCapControl()(HWND hWnd, LPVOID fpProc)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, cast(LPARAM)fpProc); }
+
+BOOL capSetUserData()(HWND hWnd, LPARAM lUser)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_USER_DATA, 0, lUser); }
+BOOL capGetUserData()(HWND hWnd)                                      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_USER_DATA, 0, 0); }
+
+BOOL capDriverConnect()(HWND hWnd, WPARAM i)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_CONNECT, i, 0); }
+BOOL capDriverDisconnect()(HWND hWnd)                                 { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0); }
+BOOL capDriverGetName()(HWND hWnd, LPTSTR szName, WPARAM wSize)       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_NAME, wSize, cast(LPARAM)szName); }
+BOOL capDriverGetVersion()(HWND hWnd, LPTSTR szVer, WPARAM wSize)     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_VERSION, wSize, cast(LPARAM)szVer); }
+BOOL capDriverGetCaps()(HWND hWnd, LPCAPDRIVERCAPS s, WPARAM wSize)   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_CAPS, wSize, cast(LPARAM)s); }
+
+BOOL capFileSetCaptureFile()(HWND hWnd, LPTSTR szName)                { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0, cast(LPARAM)szName); }
+BOOL capFileGetCaptureFile()(HWND hWnd, LPTSTR szName, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_GET_CAPTURE_FILE, wSize, cast(LPARAM)szName); }
+BOOL capFileAlloc()(HWND hWnd, WPARAM wSize)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_ALLOCATE, wSize, 0); }
+BOOL capFileSaveAs()(HWND hWnd, LPTSTR szName)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEAS, 0, cast(LPARAM)szName); }
+BOOL capFileSetInfoChunk()(HWND hWnd, LPCAPINFOCHUNK lpInfoChunk)     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_INFOCHUNK, 0, cast(LPARAM)lpInfoChunk); }
+BOOL capFileSaveDIB()(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEDIB, 0, cast(LPARAM)szName); }
+
+BOOL capEditCopy()(HWND hWnd)                                         { return cast(BOOL)AVICapSM(hWnd, WM_CAP_EDIT_COPY, 0, 0); }
+
+BOOL capSetAudioFormat()(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize)   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_AUDIOFORMAT, wSize, cast(LPARAM)s); }
+DWORD capGetAudioFormat()(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize)  { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, wSize, cast(LPARAM)s); }
+DWORD capGetAudioFormatSize()(HWND hWnd)                              { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, 0, 0); }
+
+BOOL capDlgVideoFormat()(HWND hWnd)                                   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0); }
+BOOL capDlgVideoSource()(HWND hWnd)                                   { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0); }
+BOOL capDlgVideoDisplay()(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0); }
+BOOL capDlgVideoCompression()(HWND hWnd)                              { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0); }
+
+DWORD capGetVideoFormat()(HWND hWnd, void* s, WPARAM wSize)           { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, wSize, cast(LPARAM)s); }
+DWORD capGetVideoFormatSize()(HWND hWnd)                              { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); }
+BOOL capSetVideoFormat()(HWND hWnd, void* s, WPARAM wSize)            { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_VIDEOFORMAT, wSize, cast(LPARAM)s); }
+
+BOOL capPreview()(HWND hWnd, BOOL f)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEW, cast(WPARAM)f, 0); }
+BOOL capPreviewRate()(HWND hWnd, WPARAM wMS)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEWRATE, wMS, 0); }
+BOOL capOverlay()(HWND hWnd, BOOL f)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_OVERLAY, cast(WPARAM)f, 0); }
+BOOL capPreviewScale()(HWND hWnd, BOOL f)                             { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCALE, cast(WPARAM)f, 0); }
+BOOL capGetStatus()(HWND hWnd, LPCAPSTATUS s, WPARAM wSize)           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_STATUS, wSize, cast(LPARAM)s); }
+BOOL capSetScrollPos()(HWND hWnd, LPPOINT lpP)                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCROLL, 0, cast(LPARAM)lpP); }
+
+BOOL capGrabFrame()(HWND hWnd)                                        { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME, 0, 0); }
+BOOL capGrabFrameNoStop()(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0); }
+
+BOOL capCaptureSequence()(HWND hWnd)                                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE, 0, 0); }
+BOOL capCaptureSequenceNoFile()(HWND hWnd)                            { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); }
+BOOL capCaptureStop()(HWND hWnd)                                      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_STOP, 0, 0); }
+BOOL capCaptureAbort()(HWND hWnd)                                     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_ABORT, 0, 0); }
+
+BOOL capCaptureSingleFrameOpen()(HWND hWnd)                           { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_OPEN, 0, 0); }
+BOOL capCaptureSingleFrameClose()(HWND hWnd)                          { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0); }
+BOOL capCaptureSingleFrame()(HWND hWnd)                               { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME, 0, 0); }
+
+BOOL capCaptureGetSetup()(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); }
+BOOL capCaptureSetSetup()(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize)  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); }
+
+BOOL capSetMCIDeviceName()(HWND hWnd, LPTSTR szName)                  { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_MCI_DEVICE, 0, cast(LPARAM)szName); }
+BOOL capGetMCIDeviceName()(HWND hWnd, LPTSTR szName, WPARAM wSize)    { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_MCI_DEVICE, wSize, cast(LPARAM)szName); }
+
+BOOL capPaletteOpen()(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_OPEN, 0, cast(LPARAM)szName); }
+BOOL capPaletteSave()(HWND hWnd, LPTSTR szName)                       { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_SAVE, 0, cast(LPARAM)szName); }
+BOOL capPalettePaste()(HWND hWnd)                                     { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_PASTE, 0, 0); }
+BOOL capPaletteAuto()(HWND hWnd, WPARAM iFrames, LPARAM iColors)      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_AUTOCREATE, iFrames, iColors); }
+BOOL capPaletteManual()(HWND hWnd, WPARAM fGrab, LPARAM iColors)      { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_MANUALCREATE, fGrab, iColors); }
 
 /**
  * structs
index 935c7c432cfdf87737f962687214f3becd783423..2c2905b6352c46eb40d7f9981e46106d9856e102 100644 (file)
@@ -963,7 +963,7 @@ struct DCB {
     bool fOutxDsrFlow()      { return cast(bool) (_bf & 8); }
     byte fDtrControl()       { return cast(byte) ((_bf & (32+16))>>4); }
     bool fDsrSensitivity()   { return cast(bool) (_bf & 64); }
-    bool fTXContinueOnXoff() { return cast(bool) (_bf & 128); }
+    bool fTXContinueOnXoff()() { return cast(bool) (_bf & 128); }
     bool fOutX()             { return cast(bool) (_bf & 256); }
     bool fInX()              { return cast(bool) (_bf & 512); }
     bool fErrorChar()        { return cast(bool) (_bf & 1024); }
@@ -1031,9 +1031,9 @@ struct COMSTAT {
 
     bool fCtsHold()  { return cast(bool) (_bf & 1); }
     bool fDsrHold()  { return cast(bool) (_bf & 2); }
-    bool fRlsdHold() { return cast(bool) (_bf & 4); }
-    bool fXoffHold() { return cast(bool) (_bf & 8); }
-    bool fXoffSent() { return cast(bool) (_bf & 16); }
+    bool fRlsdHold()() { return cast(bool) (_bf & 4); }
+    bool fXoffHold()() { return cast(bool) (_bf & 8); }
+    bool fXoffSent()() { return cast(bool) (_bf & 16); }
     bool fEof()      { return cast(bool) (_bf & 32); }
     bool fTxim()     { return cast(bool) (_bf & 64); }
 
@@ -1494,8 +1494,8 @@ struct LDT_ENTRY {
 
         byte LimitHi()     { return cast(byte) (Flags2 & 0x0F); }
         bool Sys()         { return cast(bool) (Flags2 & 0x10); }
-        bool Default_Big() { return cast(bool) (Flags2 & 0x40); }
-        bool Granularity() { return cast(bool) (Flags2 & 0x80); }
+        bool Default_Big()() { return cast(bool) (Flags2 & 0x40); }
+        bool Granularity()() { return cast(bool) (Flags2 & 0x80); }
     }
 /+
     union  HighWord {
@@ -2567,8 +2567,8 @@ WINBASEAPI BOOL WINAPI SetEvent(HANDLE);
 // For compatibility with old core.sys.windows.windows:
 version (LittleEndian) nothrow @nogc
 {
-    BOOL QueryPerformanceCounter(long* lpPerformanceCount) { return QueryPerformanceCounter(cast(PLARGE_INTEGER)lpPerformanceCount); }
-    BOOL QueryPerformanceFrequency(long* lpFrequency) { return QueryPerformanceFrequency(cast(PLARGE_INTEGER)lpFrequency); }
+    BOOL QueryPerformanceCounter()(long* lpPerformanceCount) { return QueryPerformanceCounter(cast(PLARGE_INTEGER)lpPerformanceCount); }
+    BOOL QueryPerformanceFrequency()(long* lpFrequency) { return QueryPerformanceFrequency(cast(PLARGE_INTEGER)lpFrequency); }
 }
 
 mixin DECLARE_AW!("STARTUPINFO");
index cb52d9e717dcd13c7ec71d4f7337648a81173f77..f068a3a7958bbf3f5063b804d55d20746c252cbf 100644 (file)
@@ -44,9 +44,9 @@ const TCHAR[] MS_ENH_RSA_AES_PROV
       = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)";
 }
 
-ALG_ID GET_ALG_CLASS(ALG_ID x) { return x & 0xE000; }
-ALG_ID GET_ALG_TYPE (ALG_ID x) { return x & 0x1E00; }
-ALG_ID GET_ALG_SID  (ALG_ID x) { return x & 0x01FF; }
+ALG_ID GET_ALG_CLASS()(ALG_ID x) { return x & 0xE000; }
+ALG_ID GET_ALG_TYPE ()(ALG_ID x) { return x & 0x1E00; }
+ALG_ID GET_ALG_SID  ()(ALG_ID x) { return x & 0x01FF; }
 
 enum : ALG_ID {
     ALG_CLASS_ANY           = 0,
@@ -214,8 +214,8 @@ enum {
     CRYPT_SUCCEED = TRUE,
 }
 
-bool RCRYPT_SUCCEEDED(BOOL r) { return r==CRYPT_SUCCEED; }
-bool RCRYPT_FAILED(BOOL r) { return r==CRYPT_FAILED; }
+bool RCRYPT_SUCCEEDED()(BOOL r) { return r==CRYPT_SUCCEED; }
+bool RCRYPT_FAILED()(BOOL r) { return r==CRYPT_FAILED; }
 
 enum {
     PP_ENUMALGS = 1,
index ca4a903fb6ae88f8196aaeb1e52f7b59db70073e..097a2b6fd43506bf5d42e88341ea4bd0e7faf70b 100644 (file)
@@ -858,16 +858,16 @@ enum : WORD {
 }
 
 pure nothrow @nogc {
-    WORD MAKELANGID(/*USHORT*/uint p, /*USHORT*/ uint s) { return cast(WORD)((s << 10) | p); }
-    WORD PRIMARYLANGID(/*WORD*/uint lgid) { return cast(WORD)(lgid & 0x3FF); }
-    WORD SUBLANGID(/*WORD*/uint lgid) { return cast(WORD)(lgid >>> 10); }
+    WORD MAKELANGID()(/*USHORT*/uint p, /*USHORT*/ uint s) { return cast(WORD)((s << 10) | p); }
+    WORD PRIMARYLANGID()(/*WORD*/uint lgid) { return cast(WORD)(lgid & 0x3FF); }
+    WORD SUBLANGID()(/*WORD*/uint lgid) { return cast(WORD)(lgid >>> 10); }
 
-    DWORD MAKELCID(/*WORD*/uint lgid, /*WORD*/uint srtid) { return (cast(DWORD) srtid << 16) | cast(DWORD) lgid; }
+    DWORD MAKELCID()(/*WORD*/uint lgid, /*WORD*/uint srtid) { return (cast(DWORD) srtid << 16) | cast(DWORD) lgid; }
     // ???
-    //DWORD MAKESORTLCID(WORD lgid, WORD srtid, WORD ver) { return (MAKELCID(lgid, srtid)) | ((cast(DWORD)ver) << 20); }
-    WORD LANGIDFROMLCID(LCID lcid) { return cast(WORD) lcid; }
-    WORD SORTIDFROMLCID(LCID lcid) { return cast(WORD) ((lcid >>> 16) & 0x0F); }
-    WORD SORTVERSIONFROMLCID(LCID lcid) { return cast(WORD) ((lcid >>> 20) & 0x0F); }
+    //DWORD MAKESORTLCID()(WORD lgid, WORD srtid, WORD ver) { return (MAKELCID(lgid, srtid)) | ((cast(DWORD)ver) << 20); }
+    WORD LANGIDFROMLCID()(LCID lcid) { return cast(WORD) lcid; }
+    WORD SORTIDFROMLCID()(LCID lcid) { return cast(WORD) ((lcid >>> 16) & 0x0F); }
+    WORD SORTVERSIONFROMLCID()(LCID lcid) { return cast(WORD) ((lcid >>> 20) & 0x0F); }
 }
 
 enum WORD LANG_SYSTEM_DEFAULT = (SUBLANG_SYS_DEFAULT << 10) | LANG_NEUTRAL;
@@ -1555,8 +1555,8 @@ const TCHAR[]
 
 enum IMAGE_ORDINAL_FLAG32 = 0x80000000;
 
-ulong IMAGE_ORDINAL64(ulong Ordinal) { return Ordinal & 0xFFFF; }
-uint IMAGE_ORDINAL32(uint Ordinal)   { return Ordinal & 0xFFFF; }
+ulong IMAGE_ORDINAL64()(ulong Ordinal) { return Ordinal & 0xFFFF; }
+uint IMAGE_ORDINAL32()(uint Ordinal)   { return Ordinal & 0xFFFF; }
 
 bool IMAGE_SNAP_BY_ORDINAL32(uint Ordinal) {
     return (Ordinal & IMAGE_ORDINAL_FLAG32) != 0;
@@ -1919,10 +1919,10 @@ static if (_WIN32_WINNT >= 0x501) {
 }
 
 // Macros
-BYTE BTYPE(BYTE x) { return cast(BYTE) (x & N_BTMASK); }
-bool ISPTR(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); }
-bool ISFCN(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); }
-bool ISARY(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); }
+BYTE BTYPE()(BYTE x) { return cast(BYTE) (x & N_BTMASK); }
+bool ISPTR()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); }
+bool ISFCN()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); }
+bool ISARY()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); }
 bool ISTAG(uint x) {
     return x == IMAGE_SYM_CLASS_STRUCT_TAG
         || x == IMAGE_SYM_CLASS_UNION_TAG
@@ -1932,7 +1932,7 @@ uint INCREF(uint x) {
     return ((x & ~N_BTMASK) << N_TSHIFT) | (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT)
       | (x & N_BTMASK);
 }
-uint DECREF(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); }
+uint DECREF()(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); }
 
 enum DWORD TLS_MINIMUM_AVAILABLE = 64;
 
@@ -1948,9 +1948,9 @@ enum ULONG
 /*  Although these are semantically boolean, they are documented and
  *  implemented to return ULONG; this behaviour is preserved for compatibility
  */
-ULONG IsReparseTagMicrosoft(ULONG x)     { return x & 0x80000000; }
-ULONG IsReparseTagHighLatency(ULONG x)   { return x & 0x40000000; }
-ULONG IsReparseTagNameSurrogate(ULONG x) { return x & 0x20000000; }
+ULONG IsReparseTagMicrosoft()(ULONG x)     { return x & 0x80000000; }
+ULONG IsReparseTagHighLatency()(ULONG x)   { return x & 0x40000000; }
+ULONG IsReparseTagNameSurrogate()(ULONG x) { return x & 0x20000000; }
 
 bool IsReparseTagValid(ULONG x) {
     return !(x & ~IO_REPARSE_TAG_VALID_VALUES) && (x > IO_REPARSE_TAG_RESERVED_RANGE);
@@ -3380,7 +3380,7 @@ struct IMAGE_RESOURCE_DIRECTORY_ENTRY {
 
     uint NameOffset()        { return Name & 0x7FFFFFFF; }
     bool NameIsString()      { return cast(bool)(Name & 0x80000000); }
-    uint OffsetToDirectory() { return OffsetToData & 0x7FFFFFFF; }
+    uint OffsetToDirectory()() { return OffsetToData & 0x7FFFFFFF; }
     bool DataIsDirectory()   { return cast(bool)(OffsetToData & 0x80000000); }
 
     uint NameOffset(uint n) {
@@ -3498,7 +3498,7 @@ struct IMAGE_CE_RUNTIME_FUNCTION_ENTRY {
 +/
     uint FuncLen()       { return (_bf >> 8) & 0x3FFFFF; }
     bool ThirtyTwoBit()  { return cast(bool)(_bf & 0x40000000); }
-    bool ExceptionFlag() { return cast(bool)(_bf & 0x80000000); }
+    bool ExceptionFlag()() { return cast(bool)(_bf & 0x80000000); }
 
     uint FuncLen(uint f) {
         _bf = (_bf & ~0x3FFFFF00) | ((f & 0x3FFFFF) << 8); return f & 0x3FFFFF;
@@ -3543,8 +3543,8 @@ struct FPO_DATA {
     ubyte cbRegs()  { return cast(ubyte)(_bf & 0x07); }
     bool fHasSEH()  { return cast(bool)(_bf & 0x08); }
     bool fUseBP()   { return cast(bool)(_bf & 0x10); }
-    bool reserved() { return cast(bool)(_bf & 0x20); }
-    ubyte cbFrame() { return cast(ubyte)(_bf >> 6); }
+    bool reserved()() { return cast(bool)(_bf & 0x20); }
+    ubyte cbFrame()() { return cast(ubyte)(_bf >> 6); }
 
     ubyte cbRegs(ubyte c) {
         _bf = cast(ubyte) ((_bf & ~0x07) | (c & 0x07));
@@ -4108,7 +4108,7 @@ struct PROCESSOR_POWER_POLICY_INFO {
     uint     _bf;
 
     bool AllowDemotion()  { return cast(bool)(_bf & 1); }
-    bool AllowPromotion() { return cast(bool)(_bf & 2); }
+    bool AllowPromotion()() { return cast(bool)(_bf & 2); }
 
     bool AllowDemotion(bool a)  { _bf = (_bf & ~1) | a; return a; }
     bool AllowPromotion(bool a) { _bf = (_bf & ~2) | (a << 1); return a; }
index f6414440783a57a93cf1de3cbc1515bffd48b845..a7917b774f4cbbb5f3ccadf00a8727014e037f10 100644 (file)
@@ -3275,10 +3275,10 @@ struct MENUBARINFO {
     byte bf_; // Simulated bitfield
 //  BOOL  fBarFocused:1;
 //  BOOL  fFocused:1;
-    bool fBarFocused()       { return (bf_ & 1) == 1; }
-    bool fFocused()          { return (bf_ & 2) == 2; }
-    bool fBarFocused(bool b) { bf_ = cast(byte) ((bf_ & 0xFE) | b);           return b; }
-    bool fFocused(bool b)    { bf_ = cast(byte) (b ? (bf_ | 2) : bf_ & 0xFD); return b; }
+    bool fBarFocused()()       { return (bf_ & 1) == 1; }
+    bool fFocused()()          { return (bf_ & 2) == 2; }
+    bool fBarFocused()(bool b) { bf_ = cast(byte) ((bf_ & 0xFE) | b);           return b; }
+    bool fFocused()(bool b)    { bf_ = cast(byte) (b ? (bf_ | 2) : bf_ & 0xFD); return b; }
 }
 alias MENUBARINFO* PMENUBARINFO;
 
@@ -4424,9 +4424,9 @@ int BroadcastSystemMessageW(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
 UINT SendInput(UINT, LPINPUT, int);
 BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
 BOOL GetMonitorInfoA(HMONITOR, LPMONITORINFO);
-extern(D) BOOL GetMonitorInfoA(HMONITOR m, LPMONITORINFOEXA mi) { return GetMonitorInfoA(m, cast(LPMONITORINFO)mi); }
+extern(D) BOOL GetMonitorInfoA()(HMONITOR m, LPMONITORINFOEXA mi) { return GetMonitorInfoA(m, cast(LPMONITORINFO)mi); }
 BOOL GetMonitorInfoW(HMONITOR, LPMONITORINFO);
-extern(D) BOOL GetMonitorInfoW(HMONITOR m, LPMONITORINFOEXW mi) { return GetMonitorInfoW(m, cast(LPMONITORINFO)mi); }
+extern(D) BOOL GetMonitorInfoW()(HMONITOR m, LPMONITORINFOEXW mi) { return GetMonitorInfoW(m, cast(LPMONITORINFO)mi); }
 HMONITOR MonitorFromPoint(POINT, DWORD);
 HMONITOR MonitorFromRect(LPCRECT, DWORD);
 HMONITOR MonitorFromWindow(HWND, DWORD);
index 1703450c65fb4d2e3354a17fcb48b9ac8de6a1da..76ce3879e0d140a53c0febd5cb4710b537613d14 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright: Copyright © 2019, The D Language Foundation
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Authors:   Walter Bright, Ernesto Castellotti
+ * Authors:   Walter Bright, Emily Castellotti
  * Source:    $(DRUNTIMESRC core/volatile.d)
  */
 
index e274fd30e8c4c0244aec5c2787f4a800fb5862be..e9838db4f383bc7395aa15416202efccec01d598 100644 (file)
@@ -3901,9 +3901,11 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
     assert(s == "abc");
 }
 
+
 // HACK:  This is a lie.  `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
 // necessary for now to prevent breaking code.
-private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
+import core.internal.array.capacity : _d_arraysetcapacityPureNothrow;
+import core.internal.traits: Unqual;
 
 /**
 (Property) Gets the current _capacity of a slice. The _capacity is the size
@@ -3918,7 +3920,10 @@ Note: The _capacity of a slice may be impacted by operations on other slices.
 */
 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
 {
-    return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr);
+    const isshared = is(T == shared);
+    alias Unqual_T = Unqual!T;
+    // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper
+    return _d_arraysetcapacityPureNothrow!Unqual_T(0, cast(void[]*)&arr, isshared);
 }
 
 ///
@@ -3957,7 +3962,12 @@ size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
     if (__ctfe)
         return newcapacity;
     else
-        return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr);
+    {
+        const isshared = is(T == shared);
+        alias Unqual_T = Unqual!T;
+        // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper
+        return _d_arraysetcapacityPureNothrow!Unqual_T(newcapacity, cast(void[]*)&arr, isshared);
+    }
 }
 
 ///
@@ -4692,6 +4702,7 @@ version (D_ProfileGC)
     public import core.lifetime : _d_newitemTTrace;
     public import core.internal.array.construction : _d_newarrayTTrace;
     public import core.internal.array.construction : _d_newarraymTXTrace;
+    public import core.internal.array.capacity: _d_arraysetlengthTTrace;
 }
 public import core.internal.array.appending : _d_arrayappendcTX;
 public import core.internal.array.comparison : __cmp;
@@ -4705,7 +4716,7 @@ public import core.internal.array.construction : _d_newarraymTX;
 public import core.internal.array.arrayassign : _d_arrayassign_l;
 public import core.internal.array.arrayassign : _d_arrayassign_r;
 public import core.internal.array.arrayassign : _d_arraysetassign;
-public import core.internal.array.capacity: _d_arraysetlengthTImpl;
+public import core.internal.array.capacity : _d_arraysetlengthT;
 
 public import core.internal.dassert: _d_assert_fail;
 
index f77d8b9c4e82dd6ec1900326dbd480baace30946..3558976bd0846a2cd6f77b8830f91ca06aa9fcb2 100644 (file)
@@ -313,119 +313,6 @@ void __doPostblit(void *ptr, size_t len, const TypeInfo ti)
     }
 }
 
-
-/**
-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:
-    ti = type info of element type
-    newcapacity = requested new capacity
-    p = pointer to array to set. Its `length` is left unchanged.
-
-Returns: the number of elements that can actually be stored once the resizing is done
-*/
-extern(C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* p) @weak
-in
-{
-    assert(ti);
-    assert(!(*p).length || (*p).ptr);
-}
-do
-{
-    auto isshared = typeid(ti) is typeid(TypeInfo_Shared);
-    auto tinext = unqualify(ti.next);
-    auto size = tinext.tsize;
-    version (D_InlineAsm_X86)
-    {
-        size_t reqsize = void;
-
-        asm
-        {
-            mov EAX, newcapacity;
-            mul EAX, size;
-            mov reqsize, EAX;
-            jnc  Lcontinue;
-        }
-    }
-    else version (D_InlineAsm_X86_64)
-    {
-        size_t reqsize = void;
-
-        asm
-        {
-            mov RAX, newcapacity;
-            mul RAX, size;
-            mov reqsize, RAX;
-            jnc  Lcontinue;
-        }
-    }
-    else
-    {
-        bool overflow = false;
-        size_t reqsize = mulu(size, newcapacity, overflow);
-        if (!overflow)
-            goto Lcontinue;
-    }
-Loverflow:
-    onOutOfMemoryError();
-    assert(0);
-Lcontinue:
-
-    // 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(tinext, (*p).ptr) | BlkAttr.APPENDABLE;
-    auto ptr = GC.malloc(reqsize, attrs, tinext);
-    if (ptr is null)
-        goto Loverflow;
-
-    // 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(ptr, datasize, tinext);
-
-    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;
-}
-
 /**
 Allocate an array with the garbage collector.
 
@@ -741,259 +628,6 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr, TypeInfo type
 }
 
 
-/**
-Resize a dynamic array by setting the `.length` property
-
-Newly created elements are initialized to their default value.
-
-Has two variants:
-- `_d_arraysetlengthT` for arrays with elements that initialize to 0
-- `_d_arraysetlengthiT` for non-zero initializers retrieved from `TypeInfo`
-
----
-void main()
-{
-    int[] a = [1, 2];
-    a.length = 3; // gets lowered to `_d_arraysetlengthT(typeid(int[]), 3, &a)`
-}
----
-
-Params:
-    ti = `TypeInfo` of array
-    newlength = new value for the array's `.length`
-    p = pointer to array to update the `.length` of.
-        While it's cast to `void[]`, its `.length` is still treated as element length.
-Returns: `*p` after being updated
-*/
-extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) @weak
-in
-{
-    assert(ti);
-    assert(!(*p).length || (*p).ptr);
-}
-do
-{
-    debug(PRINTF)
-    {
-        //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
-        if (p)
-            printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length);
-    }
-
-    if (newlength <= (*p).length)
-    {
-        *p = (*p)[0 .. newlength];
-        return *p;
-    }
-    auto tinext = unqualify(ti.next);
-    size_t sizeelem = tinext.tsize;
-
-    /* Calculate: newsize = newlength * sizeelem
-     */
-    bool overflow = false;
-    version (D_InlineAsm_X86)
-    {
-        size_t newsize = void;
-
-        asm pure nothrow @nogc
-        {
-            mov EAX, newlength;
-            mul EAX, sizeelem;
-            mov newsize, EAX;
-            setc overflow;
-        }
-    }
-    else version (D_InlineAsm_X86_64)
-    {
-        size_t newsize = void;
-
-        asm pure nothrow @nogc
-        {
-            mov RAX, newlength;
-            mul RAX, sizeelem;
-            mov newsize, RAX;
-            setc overflow;
-        }
-    }
-    else
-    {
-        const size_t newsize = mulu(sizeelem, newlength, overflow);
-    }
-    if (overflow)
-    {
-        onOutOfMemoryError();
-        assert(0);
-    }
-
-    debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
-
-    if (!(*p).ptr)
-    {
-        assert((*p).length == 0);
-        // pointer was null, need to allocate
-        auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
-        if (ptr is null)
-        {
-            onOutOfMemoryError();
-            assert(0);
-        }
-        memset(ptr, 0, newsize);
-        *p = ptr[0 .. newlength];
-        return *p;
-    }
-
-    const size_t size = (*p).length * sizeelem;
-    const isshared = typeid(ti) is typeid(TypeInfo_Shared);
-
-    /* Attempt to extend past the end of the existing array.
-     * If not possible, allocate new space for entire array and copy.
-     */
-    void* newdata = (*p).ptr;
-    if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared))
-    {
-        newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext);
-        if (newdata is null)
-        {
-            onOutOfMemoryError();
-            assert(0);
-        }
-
-        newdata[0 .. size] = (*p).ptr[0 .. size];
-
-        // Do postblit processing, as we are making a copy.
-        __doPostblit(newdata, size, tinext);
-    }
-
-    // Zero the unused portion of the newly allocated space
-    memset(newdata + size, 0, newsize - size);
-
-    *p = newdata[0 .. newlength];
-    return *p;
-}
-
-/// ditto
-extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) @weak
-in
-{
-    assert(!(*p).length || (*p).ptr);
-}
-do
-{
-    debug(PRINTF)
-    {
-        //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
-        if (p)
-            printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length);
-    }
-
-    if (newlength <= (*p).length)
-    {
-        *p = (*p)[0 .. newlength];
-        return *p;
-    }
-    auto tinext = unqualify(ti.next);
-    size_t sizeelem = tinext.tsize;
-
-    /* Calculate: newsize = newlength * sizeelem
-     */
-    bool overflow = false;
-    version (D_InlineAsm_X86)
-    {
-        size_t newsize = void;
-
-        asm pure nothrow @nogc
-        {
-            mov EAX, newlength;
-            mul EAX, sizeelem;
-            mov newsize, EAX;
-            setc overflow;
-        }
-    }
-    else version (D_InlineAsm_X86_64)
-    {
-        size_t newsize = void;
-
-        asm pure nothrow @nogc
-        {
-            mov RAX, newlength;
-            mul RAX, sizeelem;
-            mov newsize, RAX;
-            setc overflow;
-        }
-    }
-    else
-    {
-        const size_t newsize = mulu(sizeelem, newlength, overflow);
-    }
-    if (overflow)
-    {
-        onOutOfMemoryError();
-        assert(0);
-    }
-
-    debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
-
-    static void doInitialize(void *start, void *end, const void[] initializer)
-    {
-        if (initializer.length == 1)
-        {
-            memset(start, *(cast(ubyte*)initializer.ptr), end - start);
-        }
-        else
-        {
-            auto q = initializer.ptr;
-            immutable initsize = initializer.length;
-            for (; start < end; start += initsize)
-            {
-                memcpy(start, q, initsize);
-            }
-        }
-    }
-
-    if (!(*p).ptr)
-    {
-        assert((*p).length == 0);
-        // pointer was null, need to allocate
-        auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
-        if (ptr is null)
-        {
-            onOutOfMemoryError();
-            assert(0);
-        }
-        doInitialize(ptr, ptr + newsize, tinext.initializer);
-        *p = ptr[0 .. newlength];
-        return *p;
-    }
-
-    const size_t size = (*p).length * sizeelem;
-    const isshared = typeid(ti) is typeid(TypeInfo_Shared);
-
-    /* Attempt to extend past the end of the existing array.
-     * If not possible, allocate new space for entire array and copy.
-     */
-    void* newdata = (*p).ptr;
-    if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared))
-    {
-        newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext);
-        if (newdata is null)
-        {
-            onOutOfMemoryError();
-            assert(0);
-        }
-
-        newdata[0 .. size] = (*p).ptr[0 .. size];
-
-        // Do postblit processing, as we are making a copy.
-        __doPostblit(newdata, size, tinext);
-    }
-
-    // Initialize the unused portion of the newly allocated space
-    doInitialize(newdata + size, newdata + newsize, tinext.initializer);
-    *p = newdata[0 .. newlength];
-    return *p;
-}
-
-
 /**
 Given an array of length `size` that needs to be expanded to `newlength`,
 compute a new capacity.
index 6e9cd1c8fe1487cc00b757da077d671f47c184cc..6f096744127326bcef275ca8609cec356487f12b 100644 (file)
@@ -492,7 +492,10 @@ struct ModuleGroup
                 if (!bt(ctordone, idx))
                 {
                     if (!processMod(idx))
+                    {
+                        .free(ctors);
                         return false;
+                    }
                 }
             }
 
index a28116af8f23d5cd36577ccdd956a9ffc10aaeae..b1bf0c3c930fd3f3c0a6c3d7df19d631288a34ab 100644 (file)
@@ -1,4 +1,4 @@
-40ffbb3641495b02815891ee004d4c6e173b1089
+5a142da0af7b72bfed314278d14464d8f1147391
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
index 9cbb94fc8276243dca43575e117b8719d691a965..7529b360eea813ec835d5a008eecf51f5dc2131a 100644 (file)
@@ -145,15 +145,14 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/odbc/odbc32.d etc/c/odbc/odbc64.d \
        std/internal/unicode_comp.d std/internal/unicode_decomp.d \
        std/internal/unicode_grapheme.d std/internal/unicode_norm.d \
        std/internal/unicode_tables.d std/internal/windows/advapi32.d \
-       std/internal/windows/bcrypt.d std/json.d std/logger/core.d \
-       std/logger/filelogger.d std/logger/multilogger.d \
-       std/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \
-       std/math/constants.d std/math/exponential.d std/math/hardware.d \
-       std/math/operations.d std/math/package.d std/math/remainder.d \
-       std/math/rounding.d std/math/traits.d std/math/trigonometry.d \
-       std/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \
-       std/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \
-       std/parallelism.d std/path.d std/process.d std/random.d \
+       std/json.d std/logger/core.d std/logger/filelogger.d \
+       std/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \
+       std/math/algebraic.d std/math/constants.d std/math/exponential.d \
+       std/math/hardware.d std/math/operations.d std/math/package.d \
+       std/math/remainder.d std/math/rounding.d std/math/traits.d \
+       std/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \
+       std/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \
+       std/package.d std/parallelism.d std/path.d std/process.d std/random.d \
        std/range/interfaces.d std/range/package.d std/range/primitives.d \
        std/regex/internal/backtracking.d std/regex/internal/generator.d \
        std/regex/internal/ir.d std/regex/internal/kickstart.d \
index 2bbd70f960adda162d0d531fefe779e225802677..27ed8788a47005a746fbfac0b0b0a88eb9974d93 100644 (file)
@@ -254,7 +254,6 @@ am__dirstamp = $(am__leading_dot)dirstamp
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/unicode_norm.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/unicode_tables.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/windows/advapi32.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/windows/bcrypt.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/json.lo std/logger/core.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/logger/filelogger.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/logger/multilogger.lo \
@@ -618,15 +617,14 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/unicode_comp.d std/internal/unicode_decomp.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/unicode_grapheme.d std/internal/unicode_norm.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/unicode_tables.d std/internal/windows/advapi32.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/internal/windows/bcrypt.d std/json.d std/logger/core.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/logger/filelogger.d std/logger/multilogger.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/constants.d std/math/exponential.d std/math/hardware.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/operations.d std/math/package.d std/math/remainder.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/rounding.d std/math/traits.d std/math/trigonometry.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/parallelism.d std/path.d std/process.d std/random.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/json.d std/logger/core.d std/logger/filelogger.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/algebraic.d std/math/constants.d std/math/exponential.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/hardware.d std/math/operations.d std/math/package.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/remainder.d std/math/rounding.d std/math/traits.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/package.d std/parallelism.d std/path.d std/process.d std/random.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/range/interfaces.d std/range/package.d std/range/primitives.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/regex/internal/backtracking.d std/regex/internal/generator.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@        std/regex/internal/ir.d std/regex/internal/kickstart.d \
@@ -908,7 +906,6 @@ std/internal/windows/$(am__dirstamp):
        @: > std/internal/windows/$(am__dirstamp)
 std/internal/windows/advapi32.lo:  \
        std/internal/windows/$(am__dirstamp)
-std/internal/windows/bcrypt.lo: std/internal/windows/$(am__dirstamp)
 std/json.lo: std/$(am__dirstamp)
 std/logger/$(am__dirstamp):
        @$(MKDIR_P) std/logger
index f8e1c05b658a09c04c7503685a6e9797800984a5..7923eeee944d3e35608a1e5c48636c478a1f498e 100644 (file)
@@ -8,6 +8,8 @@ $(BOOKTABLE Cheat Sheet,
 $(TR $(TH Function Name) $(TH Description))
 $(T2 cache,
         Eagerly evaluates and caches another range's `front`.)
+$(T2 lazyCache,
+        Lazily evaluates and caches another range's `front`, unlike `cache`.)
 $(T2 cacheBidirectional,
         As above, but also provides `back` and `popBack`.)
 $(T2 chunkBy,
@@ -50,7 +52,7 @@ $(T2 reduce,
 $(T2 splitWhen,
         Lazily splits a range by comparing adjacent elements.)
 $(T2 splitter,
-        Lazily splits a range by a separator.)
+        Lazily splits a range by a separator, element predicate or whitespace.)
 $(T2 substitute,
         `[1, 2].substitute(1, 0.1)` returns `[0.1, 2]`.)
 $(T2 sum,
@@ -420,6 +422,203 @@ private struct _Cache(R, bool bidir)
     }
 }
 
+/**
+ * Similar to `cache`, but lazily evaluates the elements. Unlike `cache`,
+ * this function does not eagerly evaluate the front of the range until
+ * it's explicitly requested.
+ *
+ * This can be useful when evaluation of range elements has side effects that
+ * should be delayed until actually needed.
+ *
+ * See_Also: cache
+ *
+ * Params:
+ *    range = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+ *
+ * Returns:
+ *    An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with the lazily cached values of range
+ */
+
+auto lazyCache(Range)(Range range)
+if (isInputRange!Range)
+{
+    return LazyCache!(Range, isBidirectionalRange!Range)(range);
+}
+
+///
+@safe unittest
+{
+    import std.algorithm.comparison : equal;
+    import std.range, std.stdio;
+    import std.typecons : tuple;
+
+    ulong counter = 0;
+    double fun(int x)
+    {
+        ++counter;
+        // http://en.wikipedia.org/wiki/Quartic_function
+        return ( (x + 4.0) * (x + 1.0) * (x - 1.0) * (x - 3.0) ) / 14.0 + 0.5;
+    }
+    // With lazyCache, front won't be evaluated until requested
+    counter = 0;
+    auto result = iota(-4, 5).map!(a => tuple(a, fun(a)))()
+                            .lazyCache();
+    // At this point, no elements have been evaluated yet
+    assert(counter == 0);
+    // Now access the first element
+    auto firstElement = result.front;
+    // Only now the first element is evaluated
+    assert(counter == 1);
+    // Process the result lazily
+    auto filtered = result.filter!(a => a[1] < 0)()
+                         .map!(a => a[0])();
+    // Values are calculated as we iterate
+    assert(equal(filtered, [-3, -2, 2]));
+    // Only elements we actually accessed were evaluated
+    assert(counter == iota(-4, 5).length);
+}
+
+private struct LazyCache(R, bool bidir)
+{
+    import core.exception : RangeError;
+
+    private
+    {
+        import std.algorithm.internal : algoFormat;
+        import std.meta : AliasSeq;
+
+        alias E  = ElementType!R;
+        alias UE = Unqual!E;
+
+        R source;
+
+        static if (bidir) alias CacheTypes = AliasSeq!(UE, UE);
+        else              alias CacheTypes = AliasSeq!UE;
+        CacheTypes caches;
+        // Flags to track if front/back have been cached
+        bool frontCached = false;
+        static if (bidir) bool backCached = false;
+
+        static assert(isAssignable!(UE, E) && is(UE : E),
+            algoFormat(
+                "Cannot instantiate range with %s because %s elements are not assignable to %s.",
+                R.stringof,
+                E.stringof,
+                UE.stringof
+            )
+        );
+    }
+
+    this(R range)
+    {
+        source = range;
+        // Don't eagerly evaluate anything in the constructor
+    }
+
+    static if (isInfinite!R)
+        enum empty = false;
+    else
+        bool empty() @property
+        {
+            return source.empty;
+        }
+
+    mixin ImplementLength!source;
+
+    E front() @property
+    {
+        version (assert) if (empty) throw new RangeError();
+        // Only evaluate front if it hasn't been cached yet
+        if (!frontCached && !source.empty)
+        {
+            caches[0] = source.front;
+            frontCached = true;
+        }
+        return caches[0];
+    }
+    static if (bidir) E back() @property
+    {
+        version (assert) if (empty) throw new RangeError();
+        // Only evaluate back if it hasn't been cached yet
+        if (!backCached && !source.empty)
+        {
+            caches[1] = source.back;
+            backCached = true;
+        }
+        return caches[1];
+    }
+
+    void popFront()
+    {
+        version (assert) if (empty) throw new RangeError();
+        source.popFront();
+        // Reset the cache state for front
+        frontCached = false;
+    }
+    static if (bidir) void popBack()
+    {
+        version (assert) if (empty) throw new RangeError();
+        source.popBack();
+        // Reset the cache state for back
+        backCached = false;
+    }
+
+    static if (isForwardRange!R)
+    {
+        private this(R source, ref CacheTypes caches, bool frontCached, bool backCached = false)
+        {
+            this.source = source;
+            this.caches = caches;
+            this.frontCached = frontCached;
+            static if (bidir) this.backCached = backCached;
+        }
+        typeof(this) save() @property
+        {
+            static if (bidir)
+                return typeof(this)(source.save, caches, frontCached, backCached);
+            else
+                return typeof(this)(source.save, caches, frontCached);
+        }
+    }
+
+    static if (hasSlicing!R)
+    {
+        enum hasEndSlicing = is(typeof(source[size_t.max .. $]));
+
+        static if (hasEndSlicing)
+        {
+            private static struct DollarToken{}
+            enum opDollar = DollarToken.init;
+
+            auto opSlice(size_t low, DollarToken)
+            {
+                return typeof(this)(source[low .. $]);
+            }
+        }
+
+        static if (!isInfinite!R)
+        {
+            typeof(this) opSlice(size_t low, size_t high)
+            {
+                return typeof(this)(source[low .. high]);
+            }
+        }
+        else static if (hasEndSlicing)
+        {
+            auto opSlice(size_t low, size_t high)
+            in
+            {
+                assert(low <= high, "Bounds error when slicing lazyCache.");
+            }
+            do
+            {
+                import std.range : takeExactly;
+                return this[low .. $].takeExactly(high - low);
+            }
+        }
+    }
+}
+
 /**
 Implements the homonym function (also known as `transform`) present
 in many languages of functional flavor. The call `map!(fun)(range)`
@@ -865,8 +1064,8 @@ See_Also: $(REF tee, std,range)
 template each(alias fun = "a")
 {
     import std.meta : AliasSeq;
-    import std.traits : Parameters;
-    import std.typecons : Flag, Yes, No;
+    import std.traits : Parameters, isInstanceOf;
+    import std.typecons : Flag, Yes, No, Tuple;
 
 private:
     alias BinaryArgs = AliasSeq!(fun, "i", "a");
@@ -912,7 +1111,8 @@ public:
     Flag!"each" each(Range)(Range r)
     if (!isForeachIterable!Range && (
         isRangeIterable!Range ||
-        __traits(compiles, typeof(r.front).length)))
+        // Tuples get automatically expanded if function takes right number of args
+        (isInputRange!Range && isInstanceOf!(Tuple, typeof(r.front)))))
     {
         static if (isRangeIterable!Range)
         {
@@ -953,7 +1153,11 @@ public:
         }
         else
         {
-            // range interface with >2 parameters.
+            /* Range over Tuples, fun must have correct number of args
+            * If number of args of fun is <= 2, calling fun(tuple) or fun(idx, tuple)
+            * will have precendence over fun(tuple.expand).
+            * Provide types to delegate params to control this.
+            */
             for (auto range = r; !range.empty; range.popFront())
             {
                 static if (!is(typeof(fun(r.front.expand)) == Flag!"each"))
@@ -2806,10 +3010,10 @@ if (isInputRange!Range)
 
 /**
 Splits a forward range into subranges in places determined by a binary
-predicate.
+predicate called with adjacent elements.
 
 When iterating, one element of `r` is compared with `pred` to the next
-element. If `pred` return true, a new subrange is started for the next element.
+element. If `pred` returns true, a new subrange is started for the next element.
 Otherwise, they are part of the same subrange.
 
 If the elements are compared with an inequality (!=) operator, consider
@@ -2819,7 +3023,8 @@ Params:
 pred = Predicate for determining where to split. The earlier element in the
 source range is always given as the first argument.
 r = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to be split.
-Returns: a range of subranges of `r`, split such that within a given subrange,
+
+Returns: A range of subranges of `r`, split such that within a given subrange,
 calling `pred` with any pair of adjacent elements as arguments returns `false`.
 Copying the range currently has reference semantics, but this may change in the future.
 
@@ -2829,7 +3034,7 @@ relations.
 */
 
 auto splitWhen(alias pred, Range)(Range r)
-if (isForwardRange!Range)
+if (is(typeof(binaryFun!pred(r.front, r.front)) : bool) && isForwardRange!Range)
 {   import std.functional : not;
     return ChunkByImpl!(not!pred, not!pred, GroupingOpType.binaryAny, Range)(r);
 }
@@ -4309,19 +4514,23 @@ Implements the homonym function (also known as `accumulate`, $(D
 compress), `inject`, or `foldl`) present in various programming
 languages of functional flavor. There is also $(LREF fold) which does
 the same thing but with the opposite parameter order.
-The call `reduce!(fun)(seed, range)` first assigns `seed` to
-an internal variable `result`, also called the accumulator.
-Then, for each element `x` in `range`, `result = fun(result, x)`
-gets evaluated. Finally, `result` is returned.
+
+* Use `seed` to initialize an internal `accumulator`.
+* For each element `e` in $(D range), evaluate `accumulator = fun(result, e)`.
+* Return $(D accumulator).
+
 The one-argument version `reduce!(fun)(range)`
 works similarly, but it uses the first element of the range as the
-seed (the range must be non-empty).
+seed (the range must be non-empty, else this throws).
+
+If range has only one element, the functions are never invoked and
+`result` and the seed is returned unchanged.
 
 Returns:
-    the accumulated `result`
+    the accumulated result
 
 Params:
-    fun = one or more functions
+    fun = one or more functions of the form `Acc function(Acc, ElemT)`
 
 See_Also:
     $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function))
@@ -4803,26 +5012,28 @@ languages of functional flavor, iteratively calling one or more predicates.
 $(P Each predicate in `fun` must take two arguments:)
 * An accumulator value
 * An element of the range `r`
-$(P Each predicate must return a value which implicitly converts to the
+$(P Each function must return a value which implicitly converts to the
 type of the accumulator.)
 
-$(P For a single predicate,
+$(P For a single function,
 the call `fold!(fun)(range, seed)` will:)
 
-* Use `seed` to initialize an internal variable `result` (also called
-  the accumulator).
-* For each element `e` in $(D range), evaluate `result = fun(result, e)`.
-* Return $(D result).
+* Use `seed` to initialize an internal `accumulator`.
+* For each element `e` in $(D range), evaluate `accumulator = fun(result, e)`.
+* Return $(D accumulator).
 
 $(P The one-argument version `fold!(fun)(range)`
 works similarly, but it uses the first element of the range as the
 seed (the range must be non-empty) and iterates over the remaining
 elements.)
 
-Multiple results are produced when using multiple predicates.
+Multiple results are produced when using multiple functions.
+
+If range has only one element, the functions are never invoked and
+`result` and the seed is returned unchanged.
 
 Params:
-    fun = the predicate function(s) to apply to the elements
+    fun = one or more functions of the form `Acc function(Acc, ElemT)`
 
 See_Also:
     * $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function))
@@ -4913,7 +5124,7 @@ This function is also known as
     $(HTTP mathworld.wolfram.com/CumulativeSum.html, Cumulative Sum).
 
 Params:
-    fun = one or more functions to use as fold operation
+    fun = one or more functions of the form `Acc function(Acc, ElemT)`
 
 Returns:
     The function returns a range containing the consecutive reduced values. If
@@ -5296,12 +5507,9 @@ empty elements.
 The predicate is passed to $(REF binaryFun, std,functional) and accepts
 any callable function that can be executed via `pred(element, s)`.
 
-Notes:
+Note:
     If splitting a string on whitespace and token compression is desired,
-    consider using `splitter` without specifying a separator.
-
-    If no separator is passed, the $(REF_ALTTEXT, unary, unaryFun, std,functional)
-    predicate `isTerminator` decides whether to accept an element of `r`.
+    consider using the `splitter(r)` overload.
 
 Params:
     pred = The predicate for comparing each element with the separator,
@@ -5310,7 +5518,6 @@ Params:
         split. Must support slicing and `.length` or be a narrow string type.
     s = The element (or range) to be treated as the separator
         between range segments to be split.
-    isTerminator = The predicate for deciding where to split the range when no separator is passed
     keepSeparators = The flag for deciding if the separators are kept
 
 Constraints:
@@ -5324,16 +5531,16 @@ Returns:
     the returned range will be likewise.
     When a range is used a separator, bidirectionality isn't possible.
 
-    If keepSeparators is equal to Yes.keepSeparators the output will also contain the
+    If `keepSeparators` is equal to `Yes.keepSeparators` the output will also contain the
     separators.
 
     If an empty range is given, the result is an empty range. If a range with
     one separator is given, the result is a range with two empty elements.
 
 See_Also:
- $(REF _splitter, std,regex) for a version that splits using a regular expression defined separator,
- $(REF _split, std,array) for a version that splits eagerly and
- $(LREF splitWhen), which compares adjacent elements instead of element against separator.
+ - $(REF _splitter, std,regex) for a version that splits using a regular expression defined separator.
+ - $(REF _split, std,array) for a version that splits eagerly.
$(LREF splitWhen), which compares adjacent elements instead of element against separator.
 */
 auto splitter(alias pred = "a == b",
               Flag!"keepSeparators" keepSeparators = No.keepSeparators,
@@ -5736,29 +5943,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
         .equal([ [[0]], [[1]], [[2]] ]));
 }
 
-/// Use splitter without a separator
-@safe unittest
-{
-    import std.algorithm.comparison : equal;
-    import std.range.primitives : front;
-
-    assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ]));
-    assert(equal(splitter!(a => a == ' ')("hello  world"), [ "hello", "", "world" ]));
-
-    int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
-    int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
-    assert(equal(splitter!(a => a == 0)(a), w));
-
-    a = [ 0 ];
-    assert(equal(splitter!(a => a == 0)(a), [ (int[]).init, (int[]).init ]));
-
-    a = [ 0, 1 ];
-    assert(equal(splitter!(a => a == 0)(a), [ [], [1] ]));
-
-    w = [ [0], [1], [2] ];
-    assert(equal(splitter!(a => a.front == 1)(w), [ [[0]], [[2]] ]));
-}
-
 /// Leading separators, trailing separators, or no separators.
 @safe unittest
 {
@@ -5798,17 +5982,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
         .retro.equal([ "def", "|", "bc", "|", "a" ]));
 }
 
-/// Splitting by word lazily
-@safe unittest
-{
-    import std.ascii : isWhite;
-    import std.algorithm.comparison : equal;
-    import std.algorithm.iteration : splitter;
-
-    string str = "Hello World!";
-    assert(str.splitter!(isWhite).equal(["Hello", "World!"]));
-}
-
 @safe unittest
 {
     import std.algorithm;
@@ -6133,13 +6306,61 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
     assert(words.equal([ "i", "am", "pointing" ]));
 }
 
-/// ditto
+/++
+Lazily splits a range `r` whenever a predicate `isTerminator` returns true for an element.
+
+As above, two adjacent separators are considered to surround an empty element in
+the split range.
+
+Params:
+    r = The $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to be
+        split.
+    isTerminator = A $(REF_ALTTEXT unary, unaryFun, std,functional) predicate for
+        deciding where to split the range.
+
+Returns:
+    A forward range of slices of the original range split by whitespace.
+ +/
 auto splitter(alias isTerminator, Range)(Range r)
 if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r.front))))
 {
     return SplitterResult!(unaryFun!isTerminator, Range)(r);
 }
 
+///
+@safe unittest
+{
+    import std.ascii : isWhite;
+    import std.algorithm.comparison : equal;
+    import std.algorithm.iteration : splitter;
+
+    string str = "Hello World\t!";
+    assert(str.splitter!(isWhite).equal(["Hello", "World", "!"]));
+}
+
+///
+@safe unittest
+{
+    import std.algorithm.comparison : equal;
+    import std.range.primitives : front;
+
+    assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ]));
+    assert(equal(splitter!(a => a == ' ')("hello  world"), [ "hello", "", "world" ]));
+
+    int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
+    int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
+    assert(equal(splitter!(a => a == 0)(a), w));
+
+    a = [ 0 ];
+    assert(equal(splitter!(a => a == 0)(a), [ (int[]).init, (int[]).init ]));
+
+    a = [ 0, 1 ];
+    assert(equal(splitter!(a => a == 0)(a), [ [], [1] ]));
+
+    w = [ [0], [1], [2] ];
+    assert(equal(splitter!(a => a.front == 1)(w), [ [[0]], [[2]] ]));
+}
+
 private struct SplitterResult(alias isTerminator, Range)
 {
     import std.algorithm.searching : find;
index 924ea1c6b64d5da0eb71d522351018d58f80d8de..e43aeb533172c5fada49e0b698cf1e69162ad079 100644 (file)
@@ -776,26 +776,36 @@ if (isInputRange!R && !isInfinite!R)
 
 /++
     Counts elements in the given
-    $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
-    until the given predicate is true for one of the given `needles`.
+    $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+    until the given predicate is true for one of the given `needles` or `needle`.
 
     Params:
-        pred = The predicate for determining when to stop counting.
+        pred = Binary predicate for determining when to stop counting,
+            which will be passed each element of `haystack` and a needle.
         haystack = The
             $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to be
-            counted.
-        needles = Either a single element, or a
-            $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
-            of elements, to be evaluated in turn against each
-            element in `haystack` under the given predicate.
+            counted. Must be a
+            $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to
+            use multiple needles.
+        needles = A sequence of values or
+            $(REF_ALTTEXT forward ranges, isForwardRange, std,range,primitives)
+            of values, to be evaluated in turn by calling `pred(element, needle)`
+            with each element of `haystack`.
+        needle = A value passed as the 2nd argument to `pred`.
 
-    Returns: The number of elements which must be popped from the front of
+    Returns:
+  - The number of elements which must be popped from the front of
     `haystack` before reaching an element for which
-    `startsWith!pred(haystack, needles)` is `true`. If
+    $(LREF startsWith)`!pred(haystack, needles)` is `true`.
+  - If
     `startsWith!pred(haystack, needles)` is not `true` for any element in
-    `haystack`, then `-1` is returned. If more than one needle is provided,
-    `countUntil` will wrap the result     in a tuple similar to
-    `Tuple!(ptrdiff_t, "steps", ptrdiff_t needle)`
+    `haystack`, then `-1` is returned.
+  - If more than one needle is provided,
+    `countUntil` will wrap the result in a pseudo-tuple similar to
+    `Tuple!(ptrdiff_t, "steps", ptrdiff_t, "needle")`.
+    - `steps` is the count value, which can be implicitly tested for equality.
+    - `needle` is the index into `needles` which matched.
+    - Both are `-1` if there was no match.
 
     See_Also: $(REF indexOf, std,string)
   +/
@@ -923,19 +933,29 @@ if (isInputRange!R &&
     assert(countUntil("日本語", '語')   == 2);
     assert(countUntil("日本語", "五") == -1);
     assert(countUntil("日本語", '五') == -1);
-    assert(countUntil([0, 7, 12, 22, 9], [12, 22]) == 2);
-    assert(countUntil([0, 7, 12, 22, 9], 9) == 4);
-    assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3);
 
-    // supports multiple needles
+    const arr = [0, 7, 12, 22, 9];
+    assert(countUntil(arr, [12, 22]) == 2);
+    assert(countUntil(arr, 9) == 4);
+    assert(countUntil!"a > b"(arr, 20) == 3);
+}
+
+/// Multiple needles
+@safe unittest
+{
     auto res = "...hello".countUntil("ha", "he");
     assert(res.steps == 3);
-    assert(res.needle == 1);
+    assert(res.needle == 1); // the 2nd needle matched
 
     // returns -1 if no needle was found
     res = "hello".countUntil("ha", "hu");
     assert(res.steps == -1);
     assert(res.needle == -1);
+
+    // `steps` can also be implicitly compared
+    const arr = [0, 7, 12, 22, 9];
+    assert(countUntil(arr, 22, 12) == 2); // `12` found after 2 elements
+    assert(countUntil(arr, 5, 6) == -1);
 }
 
 @safe unittest
@@ -1009,7 +1029,24 @@ if (isInputRange!R &&
     assert(10.iota.repeat.joiner.countUntil!(a => a >= 9) == 9);
 }
 
-/// ditto
+/++
+    Counts elements in the given
+    $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+    until the given predicate is true for one of the elements of `haystack`.
+
+    Params:
+        pred = Unary predicate for determining when to stop counting.
+        haystack = The
+            $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to be
+            counted.
+
+    Returns:
+  - The number of elements which must be popped from the front of
+    `haystack` before reaching an element for which
+    $(LREF startsWith)`!pred(haystack)` is `true`.
+  - If `startsWith!pred(haystack)` is not `true` for any element in
+    `haystack`, then `-1` is returned.
+  +/
 ptrdiff_t countUntil(alias pred, R)(R haystack)
 if (isInputRange!R &&
     is(typeof(unaryFun!pred(haystack.front)) : bool))
index 01e8dd2c1dac946d7f88012e3f7874a4f6a92847..256d0dc2b48933619cdcd09e27d1b11c793e2b2e 100644 (file)
@@ -749,9 +749,22 @@ if (is(T R == Complex!R))
 
 
 /**
-   Params: z = A complex number.
-   Returns: The absolute value (or modulus) of `z`.
-*/
+ * Calculates the absolute value (or modulus) of a complex number.
+ *
+ *      $(TABLE_SV
+ *      $(TR $(TH $(I z))                          $(TH abs(z))             $(TH Notes))
+ *      $(TR $(TD (0, 0))                          $(TD 0)                  $(TD ))
+ *      $(TR $(TD (NaN, any) or (any, NaN))        $(TD NaN)                $(TD ))
+ *      $(TR $(TD (Inf, any) or (any, Inf))        $(TD Inf)                $(TD ))
+ *      $(TR $(TD (a, b)) normal case              $(TD hypot(a, b))      $(TD Uses algorithm to prevent overflow/underflow ))
+ *      )
+ *
+ * Params:
+ *      z = A complex number of type Complex!T
+ *
+ * Returns:
+ *      The absolute value (modulus) of `z`
+ */
 T abs(T)(Complex!T z) @safe pure nothrow @nogc
 {
     import std.math.algebraic : hypot;
@@ -767,6 +780,26 @@ T abs(T)(Complex!T z) @safe pure nothrow @nogc
     assert(abs(complex(1.0L, -2.0L)) == core.math.sqrt(5.0L));
 }
 
+@safe pure nothrow unittest
+{
+    {
+        auto x = Complex!float(-5.016556e-20, 0);
+        assert(x.abs == 5.016556e-20f);
+        auto x1 = Complex!float(-5.016556e-20f, 0);
+        assert(x1.abs == 5.016556e-20f);
+        auto x2 = Complex!float(5.016556e-20f, 0);
+        assert(x2.abs == 5.016556e-20f);
+    }
+    {
+        import std.math.traits : isNaN, isInfinity;
+        assert(Complex!double(double.nan, 0).abs.isNaN);
+        assert(Complex!double(double.nan, double.nan).abs.isNaN);
+        assert(Complex!double(double.infinity, 0).abs.isInfinity);
+        assert(Complex!double(0, double.infinity).abs.isInfinity);
+        assert(Complex!double(0, 0).abs == 0);
+    }
+}
+
 @safe pure nothrow @nogc unittest
 {
     static import core.math;
@@ -788,6 +821,7 @@ T abs(T)(Complex!T z) @safe pure nothrow @nogc
     }}
 }
 
+
 /++
    Params:
     z = A complex number.
@@ -812,6 +846,7 @@ T sqAbs(T)(Complex!T z) @safe pure nothrow @nogc
     assert(isClose(sqAbs(complex(1.0f,-1.0f)), 2.0f));
 }
 
+
 /// ditto
 T sqAbs(T)(const T x) @safe pure nothrow @nogc
 if (isFloatingPoint!T)
index 53697029c970f203109eb3327ce988a8b5ed7377..fe139a56be384f7fa1ceec93d33d858336c49fd4 100644 (file)
@@ -1737,6 +1737,26 @@ assert(equal(rbt[], [5]));
         }
     }
 
+    /**
+     * Returns a static array of 3 ranges `r` such that `r[0]` is the
+     * same as the result of `lowerBound(value)`, `r[1]` is the same
+     * as the result of $(D equalRange(value)), and `r[2]` is the same
+     * as the result of $(D upperBound(value)).
+     *
+     * Complexity: $(BIGOH log(n))
+     */
+    auto trisect(this This)(Elem e)
+    {
+        auto equalRange = this.equalRange(e);
+        alias RangeType = typeof(equalRange);
+        RangeType[3] result = [
+            RangeType(_begin, equalRange._begin),
+            equalRange,
+            RangeType(equalRange._end, _end)
+        ];
+        return result;
+    }
+
     static if (doUnittest) @safe pure unittest
     {
         import std.algorithm.comparison : equal;
@@ -2186,6 +2206,11 @@ if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init
     assert(rt1.lowerBound(3).equal([1, 2]));
     assert(rt1.equalRange(3).equal([3]));
     assert(rt1[].equal([1, 2, 3, 4, 5]));
+
+    auto t = rt1.trisect(3);
+    assert(t[0].equal(rt1.lowerBound(3)));
+    assert(t[1].equal(rt1.equalRange(3)));
+    assert(t[2].equal(rt1.upperBound(3)));
 }
 
 //immutable checks
index 65042b81095fd00c2927be6636e0e5eae812b2b3..0d44e5c3565d876d0539b60d7e99c0e6b836d10e 100644 (file)
@@ -19,6 +19,9 @@ $(TR $(TD Strings) $(TD
         $(LREF text)
         $(LREF wtext)
         $(LREF dtext)
+        $(LREF writeText)
+        $(LREF writeWText)
+        $(LREF writeDText)
         $(LREF hexString)
 ))
 $(TR $(TD Numeric) $(TD
@@ -540,6 +543,23 @@ template to(T)
     }
 }
 
+private T toImpl(T, S)(S)
+if (isInputRange!S && isInfinite!S && isExactSomeString!T)
+{
+    static assert(0, "Cannot convert infinite range to string. " ~
+                "Use `std.range.take` or `std.range.takeExactly` to make it finite.");
+}
+
+// Test for issue : https://github.com/dlang/phobos/issues/10559
+@safe pure nothrow unittest
+{
+    import std.range : repeat;
+    import std.conv : to;
+
+    // Test that converting an infinite range doesn't compile
+    static assert(!__traits(compiles, repeat(1).to!string));
+}
+
 /**
 If the source type is implicitly convertible to the target type, $(D
 to) simply performs the implicit conversion.
@@ -2470,7 +2490,8 @@ if (isIntegral!Target && !is(Target == enum) &&
             alias source = s;
         }
 
-        size_t count = 0;
+        static if (doCount)
+            size_t count = 0;
 
         if (source.empty)
             goto Lerr;
@@ -2485,7 +2506,8 @@ if (isIntegral!Target && !is(Target == enum) &&
                     sign = true;
                     goto case '+';
                 case '+':
-                    ++count;
+                    static if (doCount)
+                        ++count;
                     source.popFront();
 
                     if (source.empty)
@@ -2504,7 +2526,8 @@ if (isIntegral!Target && !is(Target == enum) &&
         {
             Target v = cast(Target) c;
 
-            ++count;
+            static if (doCount)
+                ++count;
             source.popFront();
 
             while (!source.empty)
@@ -2520,7 +2543,8 @@ if (isIntegral!Target && !is(Target == enum) &&
                     // Note: `v` can become negative here in case of parsing
                     // the most negative value:
                     v = cast(Target) (v * 10 + c);
-                    ++count;
+                    static if (doCount)
+                        ++count;
                     source.popFront();
                 }
                 else
@@ -2877,7 +2901,8 @@ do
         alias s = source;
     }
 
-    size_t count = 0;
+    static if (doCount)
+        size_t count = 0;
     auto found = false;
     do
     {
@@ -2904,7 +2929,8 @@ do
         auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow);
         enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion");
         v = cast(Target) nextv;
-        ++count;
+        static if (doCount)
+            ++count;
         s.popFront();
         found = true;
     } while (!s.empty);
@@ -3163,36 +3189,35 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
 
     enforce(!p.empty, bailOut());
 
-
     size_t count = 0;
     bool sign = false;
     switch (p.front)
     {
     case '-':
         sign = true;
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty, bailOut());
         if (toLower(p.front) == 'i')
             goto case 'i';
         break;
     case '+':
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty, bailOut());
         break;
     case 'i': case 'I':
         // inf
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty && toUpper(p.front) == 'N',
                bailOut("error converting input to floating point"));
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty && toUpper(p.front) == 'F',
                bailOut("error converting input to floating point"));
         // skip past the last 'f'
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         advanceSource();
         static if (doCount)
@@ -3210,7 +3235,7 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
     bool startsWithZero = p.front == '0';
     if (startsWithZero)
     {
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         if (p.empty)
         {
@@ -3228,23 +3253,23 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
         isHex = p.front == 'x' || p.front == 'X';
         if (isHex)
         {
-            ++count;
+            static if (doCount) ++count;
             p.popFront();
         }
     }
     else if (toLower(p.front) == 'n')
     {
         // nan
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty && toUpper(p.front) == 'A',
                bailOut("error converting input to floating point"));
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty && toUpper(p.front) == 'N',
                bailOut("error converting input to floating point"));
         // skip past the last 'n'
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         advanceSource();
         static if (doCount)
@@ -3332,14 +3357,14 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
                     exp += expIter;
                 }
                 exp -= dot;
-                ++count;
+                static if (doCount) ++count;
                 p.popFront();
                 if (p.empty)
                     break;
                 i = p.front;
                 if (i == '_')
                 {
-                    ++count;
+                    static if (doCount) ++count;
                     p.popFront();
                     if (p.empty)
                         break;
@@ -3348,7 +3373,7 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
             }
             if (i == '.' && !dot)
             {
-                ++count;
+                static if (doCount) ++count;
                 p.popFront();
                 dot += expIter;
             }
@@ -3373,14 +3398,14 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
         char sexp = 0;
         int e = 0;
 
-        ++count;
+        static if (doCount) ++count;
         p.popFront();
         enforce(!p.empty, new ConvException("Unexpected end of input"));
         switch (p.front)
         {
             case '-':    sexp++;
                          goto case;
-            case '+':    ++count;
+            case '+':    static if (doCount) ++count;
                          p.popFront();
                          break;
             default: {}
@@ -3392,7 +3417,7 @@ if (isFloatingPoint!Target && !is(Target == enum) &&
             {
                 e = e * 10 + p.front - '0';
             }
-            ++count;
+            static if (doCount) ++count;
             p.popFront();
             sawDigits = true;
         }
@@ -4098,7 +4123,12 @@ if (isDynamicArray!Target && !is(Target == enum) &&
     auto result = appender!Target();
 
     parseCheck!s(lbracket);
-    size_t count = 1 + skipWS!(Source, Yes.doCount)(s);
+    static if (doCount)
+        size_t count = 1;
+    static if (doCount)
+        count += skipWS!(Source, Yes.doCount)(s);
+    else
+        skipWS!(Source, No.doCount)(s);
     if (s.empty)
         throw convError!(Source, Target)(s);
     if (s.front == rbracket)
@@ -4106,36 +4136,54 @@ if (isDynamicArray!Target && !is(Target == enum) &&
         s.popFront();
         static if (doCount)
         {
-            return tuple!("data", "count")(result.data, ++count);
+            ++count;
+            return tuple!("data", "count")(result.data, count);
         }
         else
         {
             return result.data;
         }
     }
-    for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s))
+    for (;;)
     {
         if (!s.empty && s.front == rbracket)
             break;
-        auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s);
-        result ~= r.data;
-        count += r.count + skipWS!(Source, Yes.doCount)(s);
+        static if (doCount)
+        {
+            auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s);
+            result ~= r.data;
+            count += r.count;
+            count += skipWS!(Source, Yes.doCount)(s);
+        }
+        else
+        {
+            auto r = parseElement!(WideElementType!Target, Source, No.doCount)(s);
+            result ~= r;
+            skipWS!(Source, No.doCount)(s);
+        }
         if (s.empty)
             throw convError!(Source, Target)(s);
         if (s.front != comma)
             break;
+        s.popFront();
+        static if (doCount)
+            ++count;
+        static if (doCount)
+            count += skipWS!(Source, Yes.doCount)(s);
+        else
+            skipWS!(Source, No.doCount)(s);
     }
     parseCheck!s(rbracket);
     static if (doCount)
     {
-        return tuple!("data", "count")(result.data, ++count);
+        ++count;
+        return tuple!("data", "count")(result.data, count);
     }
     else
     {
         return result.data;
     }
 }
-
 ///
 @safe pure unittest
 {
@@ -4286,7 +4334,12 @@ if (isStaticArray!Target && !is(Target == enum) &&
         Target result = void;
 
     parseCheck!s(lbracket);
-    size_t count = 1 + skipWS!(Source, Yes.doCount)(s);
+    static if (doCount)
+        size_t count = 1;
+    static if (doCount)
+        count += skipWS!(Source, Yes.doCount)(s);
+    else
+        skipWS!(Source, No.doCount)(s);
     if (s.empty)
         throw convError!(Source, Target)(s);
     if (s.front == rbracket)
@@ -4298,7 +4351,8 @@ if (isStaticArray!Target && !is(Target == enum) &&
             s.popFront();
             static if (doCount)
             {
-                return tuple!("data", "count")(result, ++count);
+                ++count;
+                return tuple!("data", "count")(result, count);
             }
             else
             {
@@ -4306,13 +4360,23 @@ if (isStaticArray!Target && !is(Target == enum) &&
             }
         }
     }
-    for (size_t i = 0; ; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s))
+    for (size_t i = 0; ; )
     {
         if (i == result.length)
             goto Lmanyerr;
-        auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s);
-        result[i++] = r.data;
-        count += r.count + skipWS!(Source, Yes.doCount)(s);
+        static if (doCount)
+        {
+            auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s);
+            result[i++] = r.data;
+            count += r.count;
+            count += skipWS!(Source, Yes.doCount)(s);
+        }
+        else
+        {
+            auto r = parseElement!(ElementType!Target, Source, No.doCount)(s);
+            result[i++] = r;
+            skipWS!(Source, No.doCount)(s);
+        }
         if (s.empty)
             throw convError!(Source, Target)(s);
         if (s.front != comma)
@@ -4321,21 +4385,27 @@ if (isStaticArray!Target && !is(Target == enum) &&
                 goto Lfewerr;
             break;
         }
+        s.popFront();
+        static if (doCount)
+            ++count;
+        static if (doCount)
+            count += skipWS!(Source, Yes.doCount)(s);
+        else
+            skipWS!(Source, No.doCount)(s);
     }
     parseCheck!s(rbracket);
     static if (doCount)
     {
-        return tuple!("data", "count")(result, ++count);
+        ++count;
+        return tuple!("data", "count")(result, count);
     }
     else
     {
         return result;
     }
 
-
 Lmanyerr:
     throw parseError(text("Too many elements in input, ", result.length, " elements expected."));
-
 Lfewerr:
     throw parseError(text("Too few elements in input, ", result.length, " elements expected."));
 }
@@ -4393,46 +4463,60 @@ if (isAssociativeArray!Target && !is(Target == enum) &&
     alias ValType = typeof(Target.init.values[0]);
 
     Target result;
+    static if (doCount) size_t count;
 
     parseCheck!s(lbracket);
-    size_t count = 1 + skipWS!(Source, Yes.doCount)(s);
+    static if (doCount)
+        count = 1 + skipWS!(Source, Yes.doCount)(s);
+    else
+        skipWS!(Source, No.doCount)(s);
     if (s.empty)
         throw convError!(Source, Target)(s);
     if (s.front == rbracket)
     {
         s.popFront();
+        static if (doCount)
+            return tuple!("data", "count")(result, count + 1);
+        else
+            return result;
+    }
+    for (;;)
+    {
         static if (doCount)
         {
-            return tuple!("data", "count")(result, ++count);
+            auto key = parseElement!(KeyType, Source, Yes.doCount)(s);
+            count += key.count + skipWS!(Source, Yes.doCount)(s);
+            parseCheck!s(keyval);
+            count += 1 + skipWS!(Source, Yes.doCount)(s);
+            auto val = parseElement!(ValType, Source, Yes.doCount)(s);
+            count += val.count + skipWS!(Source, Yes.doCount)(s);
+            result[key.data] = val.data;
         }
         else
         {
-            return result;
+            auto key = parseElement!(KeyType, Source, No.doCount)(s);
+            skipWS!(Source, No.doCount)(s);
+            parseCheck!s(keyval);
+            skipWS!(Source, No.doCount)(s);
+            auto val = parseElement!(ValType, Source, No.doCount)(s);
+            skipWS!(Source, No.doCount)(s);
+            result[key] = val;
         }
-    }
-    for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s))
-    {
-        auto key = parseElement!(KeyType, Source, Yes.doCount)(s);
-        count += key.count + skipWS!(Source, Yes.doCount)(s);
-        parseCheck!s(keyval);
-        count += 1 + skipWS!(Source, Yes.doCount)(s);
-        auto val = parseElement!(ValType, Source, Yes.doCount)(s);
-        count += val.count + skipWS!(Source, Yes.doCount)(s);
-        result[key.data] = val.data;
         if (s.empty)
             throw convError!(Source, Target)(s);
         if (s.front != comma)
             break;
+        s.popFront();
+        static if (doCount)
+            count += 1 + skipWS!(Source, Yes.doCount)(s);
+        else
+            skipWS!(Source, No.doCount)(s);
     }
     parseCheck!s(rbracket);
     static if (doCount)
-    {
-        return tuple!("data", "count")(result, ++count);
-    }
+        return tuple!("data", "count")(result, count + 1);
     else
-    {
         return result;
-    }
 }
 
 ///
@@ -4489,7 +4573,9 @@ private auto parseEscape(Source, Flag!"doCount" doCount = No.doCount)(ref Source
 if (isInputRange!Source && isSomeChar!(ElementType!Source))
 {
     parseCheck!s('\\');
-    size_t count = 1;
+    size_t count;
+    static if (doCount)
+        count = 1;
     if (s.empty)
         throw parseError("Unterminated escape sequence");
 
@@ -4507,15 +4593,15 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
             throw parseError("Hex digit is missing");
         return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
     }
-
     // We need to do octals separate, because they need a lookahead to find out,
     // where the escape sequence ends.
     auto first = s.front;
     if (first >= '0' && first <= '7')
     {
         dchar c1 = s.front;
-        ++count;
         s.popFront();
+        static if (doCount)
+            ++count;
         if (s.empty)
         {
             static if (doCount)
@@ -4539,8 +4625,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
                 return cast (dchar)(c1 - '0');
             }
         }
-        ++count;
         s.popFront();
+        static if (doCount)
+            ++count;
         dchar c3 = s.front;
         if (c3 < '0' || c3 > '7')
         {
@@ -4553,8 +4640,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
                 return cast (dchar) (8 * (c1 - '0') + (c2 - '0'));
             }
         }
-        ++count;
         s.popFront();
+        static if (doCount)
+            ++count;
         if (c1 > '3')
             throw parseError("Octal sequence is larger than \\377");
         static if (doCount)
@@ -4585,14 +4673,16 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
         case 'x':
             result  = getHexDigit() << 4;
             result |= getHexDigit();
-            count += 2;
+            static if (doCount)
+                count += 2;
             break;
         case 'u':
             result  = getHexDigit() << 12;
             result |= getHexDigit() << 8;
             result |= getHexDigit() << 4;
             result |= getHexDigit();
-            count += 4;
+            static if (doCount)
+                count += 4;
             break;
         case 'U':
             result  = getHexDigit() << 28;
@@ -4603,7 +4693,8 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
             result |= getHexDigit() << 8;
             result |= getHexDigit() << 4;
             result |= getHexDigit();
-            count += 8;
+            static if (doCount)
+                count += 8;
             break;
         default:
             throw parseError("Unknown escape character " ~ to!string(s.front));
@@ -4643,7 +4734,6 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source))
         // https://issues.dlang.org/show_bug.cgi?id=9621 (Named Character Entities)
         //'\&amp;', '\&quot;',
     ];
-
     foreach (i ; 0 .. s1.length)
     {
         assert(s2[i] == parseEscape(s1[i]));
@@ -4696,7 +4786,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
     }
 
     parseCheck!s('\"');
-    size_t count = 1;
+    size_t count;
+    static if (doCount)
+        count = 1;
     if (s.empty)
         throw convError!(Source, Target)(s);
     if (s.front == '\"')
@@ -4704,13 +4796,13 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         s.popFront();
         static if (doCount)
         {
-            return tuple!("data", "count")(result.data, ++count);
+            count++;
+            return tuple!("data", "count")(result.data, count);
         }
         else
         {
             return result.data;
         }
-
     }
     while (true)
     {
@@ -4722,20 +4814,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
                 s.popFront();
                 static if (doCount)
                 {
-                    return tuple!("data", "count")(result.data, ++count);
+                    count++;
+                    return tuple!("data", "count")(result.data, count);
                 }
                 else
                 {
                     return result.data;
                 }
             case '\\':
-                auto r = parseEscape!(typeof(s), Yes.doCount)(s);
-                result.put(r[0]);
-                count += r[1];
+                static if (doCount)
+                {
+                    auto r = parseEscape!(typeof(s), Yes.doCount)(s);
+                    result.put(r[0]);
+                    count += r[1];
+                }
+                else
+                {
+                    auto r = parseEscape!(typeof(s), No.doCount)(s);
+                    result.put(r);
+                }
                 break;
             default:
                 result.put(s.front);
-                ++count;
+                static if (doCount)
+                    count++;
                 s.popFront();
                 break;
         }
@@ -4751,21 +4853,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
     Unqual!Target c;
 
     parseCheck!s('\'');
-    size_t count = 1;
+    size_t count;
+    static if (doCount)
+        count = 1;
     if (s.empty)
         throw convError!(Source, Target)(s);
-    ++count; // for the following if-else sequence
+    static if (doCount)
+        count++;
     if (s.front != '\\')
     {
         c = s.front;
         s.popFront();
     }
     else
-        c = parseEscape(s);
+    {
+        static if (doCount)
+            c = parseEscape!(typeof(s), Yes.doCount)(s).data;
+        else
+            c = parseEscape!(typeof(s), No.doCount)(s);
+    }
     parseCheck!s('\'');
     static if (doCount)
     {
-        return tuple!("data", "count")(c, ++count);
+        count++;
+        return tuple!("data", "count")(c, count);
     }
     else
     {
@@ -4835,6 +4946,225 @@ if (T.length > 0) { return textImpl!dstring(args); }
     assert(dtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"d);
 }
 
+// Ensure that ranges are being printed as expected.
+@safe unittest
+{
+    static struct Range
+    {
+        int counter = 0;
+
+    @safe pure nothrow @nogc:
+        bool empty() const => (counter <= 0);
+        int front() const => counter;
+        void popFront() { --counter; }
+    }
+
+    auto m = Range(2);
+    assert(text(m) == "[2, 1]");
+
+    const c = Range(3);
+    assert(text(c) == "const(Range)(3)");
+}
+
+// Ensure that a usage pattern seen in libraries like "unit-threaded" works.
+@safe unittest
+{
+    static final class Foo
+    {
+        override string toString() const @safe
+        {
+            return ":-)";
+        }
+    }
+
+    const c = new Foo();
+    assert(text(c) == ":-)");
+    assert(text(c, " ") == ":-) ");
+}
+
+// Ensure that classes are printed as expected.
+@system unittest
+{
+    import std.string : endsWith, startsWith;
+
+    static final class Bar {}
+
+    // CTFE:                                                         `Bar`
+    // Runtime:                         `std.conv.__unittest_L4875_C9.Bar`
+    static assert(text(     new       Bar ()     )  ==               "Bar"   );
+           assert(text(     new       Bar ()     ).endsWith  (      ".Bar"  ));
+    static assert(text("=", new       Bar (), ".")  ==              "=Bar."  );
+           assert(text("=", new       Bar (), ".").endsWith  (      ".Bar." ));
+    static assert(text(     new const(Bar)()     )  ==         "const(Bar)"  );
+           assert(text(     new const(Bar)()     ).startsWith( "const("     ));
+           assert(text(     new const(Bar)()     ).endsWith  (      ".Bar)" ));
+    static assert(text("=", new const(Bar)(), ".")  ==        "=const(Bar)." );
+           assert(text("=", new const(Bar)(), ".").startsWith("=const("     ));
+           assert(text("=", new const(Bar)(), ".").endsWith  (      ".Bar)."));
+}
+
+// Ensure that various types are printed as expected.
+@safe unittest
+{
+    import std.string : endsWith;
+
+    int dummy;
+
+    static struct Foo {}
+    struct Bar { int i() @safe => dummy; }
+
+    static struct Point
+    {
+        int x;
+        int y;
+    }
+
+    struct Range
+    {
+        bool empty()    =>              dummy > 9;
+        int  front()    =>              dummy;
+        void popFront() => cast(void) ++dummy;
+    }
+
+    assert(text(null         ) == "null"     );
+    assert(text(null, null   ) == "nullnull" );
+    assert(text(0, null, '\0') == "0null\x00");
+
+    assert(text('\r','\n','\t','\x00') == "\r\n\t\0");
+    assert(text("\r\n\t\0"           ) == "\r\n\t\0");
+
+    assert(text(       3141,     ) ==    "3141"  );
+    assert(text(": ",  3141, '\0') ==  ": 3141\0");
+    assert(text(      -3141,     ) ==   "-3141"  );
+    assert(text(": ", -3141, '\0') == ": -3141\0");
+
+    () @trusted
+    {
+        int* pointer = cast(int*) 3141;
+        assert(text(       pointer,     ) ==    "C45"  );
+        assert(text(": ",  pointer, '\0') ==  ": C45\0");
+    }();
+
+    assert(text(      3.1415923,      ) ==   "3.14159"  );
+    assert(text(": ", 3.1415923,  '\0') == ": 3.14159\0");
+    assert(text(      3.1415923f,     ) ==   "3.14159"  );
+    assert(text(": ", 3.1415923f, '\0') == ": 3.14159\0");
+
+    assert(text(       !3141,     ) ==   "false"  );
+    assert(text(": ",  !3141, '\0') == ": false\0");
+    assert(text(      !!3141,     ) ==   "true"   );
+    assert(text(": ", !!3141, '\0') == ": true\0" );
+
+    assert(text(             Foo(),      ) ==         "Foo()"  );
+    assert(text(": ",        Foo(),  '\0') ==       ": Foo()\0");
+    assert(text(      const(Foo)(),     ) ==   "const(Foo)()"  );
+    assert(text(": ", const(Foo)(), '\0') == ": const(Foo)()\0");
+
+    assert(text(             Bar(),      ) ==         "Bar()"  );
+    assert(text(": ",        Bar(),  '\0') ==       ": Bar()\0");
+    assert(text(      const(Bar)(),     ) ==   "const(Bar)()"  );
+    assert(text(": ", const(Bar)(), '\0') == ": const(Bar)()\0");
+
+    assert(text(                 Point(3, 141),     ) ==              "Point(3, 141)"  );
+    assert(text(": ",            Point(3, 141), '\0') ==            ": Point(3, 141)\0");
+    assert(text(          const(Point)(3, 141),     ) ==       "const(Point)(3, 141)"  );
+    assert(text(": ",     const(Point)(3, 141), '\0') ==     ": const(Point)(3, 141)\0");
+    assert(text(         shared(Point)(3, 141),     ) ==      "shared(Point)(3, 141)"  );
+    assert(text(": ",    shared(Point)(3, 141), '\0') ==    ": shared(Point)(3, 141)\0");
+    assert(text(      immutable(Point)(3, 141),     ) ==   "immutable(Point)(3, 141)"  );
+    assert(text(": ", immutable(Point)(3, 141), '\0') == ": immutable(Point)(3, 141)\0");
+
+    dummy = 0;
+    assert(text(            Range(),      ) ==   "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"  );
+    dummy = 0;
+    assert(text(": ",       Range(),  '\0') == ": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\0");
+    assert(text(      const(Range)(),     ) ==   "const(Range)()"                  );
+    assert(text(": ", const(Range)(), '\0') == ": const(Range)()\0"                );
+
+    void function() @safe fn1;
+    void delegate() @safe dg1;
+    assert(text(fn1) == "null");
+    assert(text(dg1) == "void delegate() @safe");
+
+    bool function(bool, int) @safe    fn2;
+    bool delegate(bool, int) @safe    dg2;
+    bool delegate(bool, int) @system  dg3;
+    bool delegate(bool, int) @trusted dg4;
+    assert(text(fn2) == "null");
+    assert(text(dg2) == "bool delegate(bool, int) @safe");
+    assert(text(dg3) == "bool delegate(bool, int) @system");
+    assert(text(dg4) == "bool delegate(bool, int) @trusted");
+}
+
+/// Convenience functions for writing arguments to an output range as text.
+void writeText(Sink, T...)(ref Sink sink, T args)
+if (isOutputRange!(Sink, char) && T.length > 0)
+{
+    sink.writeTextImpl!string(args);
+}
+
+/// ditto
+void writeWText(Sink, T...)(ref Sink sink, T args)
+if (isOutputRange!(Sink, wchar) && T.length > 0)
+{
+    sink.writeTextImpl!wstring(args);
+}
+
+/// ditto
+void writeDText(Sink, T...)(ref Sink sink, T args)
+if (isOutputRange!(Sink, dchar) && T.length > 0)
+{
+    sink.writeTextImpl!dstring(args);
+}
+
+///
+@safe unittest
+{
+    import std.array : appender;
+
+    auto output = appender!string();
+    output.writeText("The answer is ", 42);
+
+    assert(output.data == "The answer is 42");
+}
+
+///
+@safe unittest
+{
+    import std.array : appender;
+
+    const color = "red";
+    auto output = appender!string();
+    output.writeText(i"My favorite color is $(color)");
+
+    assert(output.data == "My favorite color is red");
+}
+
+@safe unittest
+{
+    auto capp = appender!string();
+    auto wapp = appender!wstring();
+    auto dapp = appender!dstring();
+
+    capp.writeText(42, ' ', 1.5, ": xyz");
+    wapp.writeWText(42, ' ', 1.5, ": xyz");
+    dapp.writeDText(42, ' ', 1.5, ": xyz");
+
+    assert(capp.data == "42 1.5: xyz"c);
+    assert(wapp.data == "42 1.5: xyz"w);
+    assert(dapp.data == "42 1.5: xyz"d);
+}
+
+// Check range API compliance using OutputRange interface
+@system unittest
+{
+    import std.range.interfaces : OutputRange, outputRangeObject;
+    import std.range : nullSink;
+
+    OutputRange!char testOutput = outputRangeObject!char(nullSink);
+    testOutput.writeText(42, ' ', 1.5, ": xyz");
+}
+
 private S textImpl(S, U...)(U args)
 {
     static if (U.length == 0)
@@ -4855,30 +5185,35 @@ private S textImpl(S, U...)(U args)
         // assume that on average, parameters will have less
         // than 20 elements
         app.reserve(U.length * 20);
-        // Must be static foreach because of https://issues.dlang.org/show_bug.cgi?id=21209
-        static foreach (arg; args)
-        {
-            static if (
-                isSomeChar!(typeof(arg))
-                || isSomeString!(typeof(arg))
-                || ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) )
-            )
-                app.put(arg);
-            else static if (
-
-                is(immutable typeof(arg) == immutable uint) || is(immutable typeof(arg) == immutable ulong) ||
-                is(immutable typeof(arg) == immutable int) || is(immutable typeof(arg) == immutable long)
-            )
-                // https://issues.dlang.org/show_bug.cgi?id=17712#c15
-                app.put(textImpl!(S)(arg));
-            else
-                app.put(to!S(arg));
-        }
-
+        app.writeTextImpl!S(args);
         return app.data;
     }
 }
 
+private void writeTextImpl(S, Sink, U...)(ref Sink sink, U args)
+if (isSomeString!S && isOutputRange!(Sink, ElementEncodingType!S))
+{
+    // Must be static foreach because of https://issues.dlang.org/show_bug.cgi?id=21209
+    static foreach (arg; args)
+    {
+        static if (
+            isSomeChar!(typeof(arg))
+            || isSomeString!(typeof(arg))
+            || ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) )
+        )
+            put(sink, arg);
+        else static if (
+
+            is(immutable typeof(arg) == immutable uint) || is(immutable typeof(arg) == immutable ulong) ||
+            is(immutable typeof(arg) == immutable int) || is(immutable typeof(arg) == immutable long)
+        )
+            // https://issues.dlang.org/show_bug.cgi?id=17712#c15
+            put(sink, textImpl!(S)(arg));
+        else
+            put(sink, to!S(arg));
+    }
+}
+
 
 /***************************************************************
 The `octal` facility provides a means to declare a number in base 8.
index 9334f3183f6aa5fe8c51f5a9461abed7de9db48f..c7c161e7d4d5d3efc4c510c9f0f6152357897b2b 100644 (file)
@@ -1879,7 +1879,7 @@ immutable(E)[] sanitize(E)(immutable(E)[] s)
         offset += n;
         t = t[n..$];
     }
-    return cast(immutable(E)[])array[0 .. offset];
+    return array[0 .. offset];
 }
 
 ///
index 0b8da501d3f5e11115a2fd731c1c59e4fb610599..a5b53270f952b2ba801961308b1826bd7ab5114f 100644 (file)
@@ -983,10 +983,10 @@ private void renameImpl(scope const(char)[] f, scope const(char)[] t,
             import std.conv : to, text;
 
             if (!f)
-                f = fromz ? to!(typeof(f))(fromz[0 .. wcslen(fromz)]) : "(null)";
+                f = to!(typeof(f))(fromz[0 .. wcslen(fromz)]);
 
             if (!t)
-                t = toz ? to!(typeof(t))(toz[0 .. wcslen(toz)]) : "(null)";
+                t = to!(typeof(t))(toz[0 .. wcslen(toz)]);
 
             enforce(false,
                 new FileException(
@@ -2369,7 +2369,6 @@ if (isConvertibleToString!R)
 }
 
 ///
-
 @safe unittest
 {
     import std.exception : assertThrown;
@@ -4638,6 +4637,7 @@ private struct DirIteratorImpl
     DirEntry _cur;
     DirHandle[] _stack;
     DirEntry[] _stashed; //used in depth first mode
+    string _pathPrefix = null;
 
     //stack helpers
     void pushExtra(DirEntry de)
@@ -4793,20 +4793,12 @@ private struct DirIteratorImpl
         }
     }
 
-    this(R)(R pathname, SpanMode mode, bool followSymlink)
-    if (isSomeFiniteCharInputRange!R)
+    this(string pathname, SpanMode mode, bool followSymlink)
     {
         _mode = mode;
         _followSymlink = followSymlink;
 
-        static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
-            alias pathnameStr = pathname;
-        else
-        {
-            import std.array : array;
-            string pathnameStr = pathname.array;
-        }
-        if (stepIn(pathnameStr))
+        if (stepIn(pathname))
         {
             if (_mode == SpanMode.depth)
                 while (mayStepIn())
@@ -5105,6 +5097,15 @@ auto dirEntries(bool useDIP1000 = dip1000Enabled)
 
     // https://issues.dlang.org/show_bug.cgi?id=15146
     dirEntries("", SpanMode.shallow).walkLength();
+
+    // https://github.com/dlang/phobos/issues/9584
+    string cwd = getcwd();
+    foreach (string entry; dirEntries(testdir, SpanMode.shallow))
+    {
+        if (entry.isDir)
+            chdir(entry);
+    }
+    chdir(cwd); // needed for the directories to be removed
 }
 
 /// Ditto
index bb6d878c8395800b0cb34fd141f6e346665ccd90..8d3288579303c606e2cf0bc0c80fe3fe70e53416 100644 (file)
@@ -1412,6 +1412,12 @@ if (isInputRange!T)
     // if the format spec is valid
     enum formatTestMode = is(Writer == NoOpSink);
 
+    static if (!formatTestMode && isInfinite!T)
+    {
+        static assert(!isInfinite!T, "Cannot format an infinite range. " ~
+            "Convert it to a finite range first using `std.range.take` or `std.range.takeExactly`.");
+    }
+
     // Formatting character ranges like string
     if (f.spec == 's')
     {
@@ -1582,18 +1588,16 @@ if (isInputRange!T)
         throw new FormatException(text("Incorrect format specifier for range: %", f.spec));
 }
 
-// https://issues.dlang.org/show_bug.cgi?id=20218
 @safe pure unittest
 {
-    void notCalled()
-    {
-        import std.range : repeat;
+    import std.range : repeat;
+    import std.format : format;
 
-        auto value = 1.repeat;
+    auto value = 1.repeat;
 
-        // test that range is not evaluated to completion at compiletime
-        format!"%s"(value);
-    }
+    // This should fail to compile — so we assert that it *doesn't* compile
+    static assert(!__traits(compiles, format!"%s"(value)),
+        "Test failed: formatting an infinite range should not compile.");
 }
 
 // character formatting with ecaping
index 68a96d48625cbebc6f15649c3bfad409b13af714..d704c14f5faa14524ddae33aa1554a9e46ee1373 100644 (file)
@@ -534,8 +534,6 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
 
     // Are we already done with formats? Then just dump each parameter in turn
     uint currentArg = 0;
-    bool lastWasConsumeAll;
-
     while (spec.writeUpToNextSpec(w))
     {
         if (currentArg == Args.length && !spec.indexStart)
@@ -651,10 +649,7 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
             }
         default:
             if (spec.indexEnd == spec.indexEnd.max)
-            {
-                lastWasConsumeAll = true;
                 break;
-            }
             else if (spec.indexEnd == spec.indexStart)
                 throw new FormatException(
                     text("Positional specifier %", spec.indexStart, '$', spec.spec,
@@ -665,8 +660,7 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
                     " index exceeds ", Args.length));
         }
     }
-
-    return lastWasConsumeAll ? Args.length : currentArg;
+    return currentArg;
 }
 
 ///
@@ -1218,8 +1212,7 @@ if (isSomeString!(typeof(fmt)))
     import std.array : appender;
     auto w = appender!(char[])();
 
-    uint count = formattedWrite(w, "%1:$d", 1, 2, 3);
-    assert(count == 3);
+    formattedWrite(w, "%1:$d", 1, 2, 3);
     assert(w.data == "123");
 }
 
index 2e1c6e9ae678fe431e2bad282fb183f078a442b2..12c261bd0bd8f33e80e7bf8125d64c0077604e1a 100644 (file)
@@ -1808,7 +1808,6 @@ private struct DelegateFaker(F)
  *
  * BUGS:
  * $(UL
- *   $(LI Does not work with `@safe` functions.)
  *   $(LI Ignores C-style / D-style variadic arguments.)
  * )
  */
index 9c794b60de1220ac52ec20bad22efaa563ddb405..b2c2b890e2c198f9e1210f597907afbe28fe6e08 100644 (file)
@@ -940,7 +940,11 @@ public:
             uint [] wasteful = new BigDigit[x.data.length];
             wasteful[] = x.data[];
             immutable rem = multibyteDivAssign(wasteful, y, 0);
-            () @trusted { GC.free(wasteful.ptr); } ();
+            if (!__ctfe)
+            {
+                //use free only at runtime
+                () @trusted { GC.free(wasteful.ptr); } ();
+            }
             return rem;
         }
     }
@@ -1279,6 +1283,13 @@ pure @safe unittest
    assert(s == 5);
 }
 
+pure @safe unittest
+{ //evaluate mod at compile time
+   enum BigUint r = BigUint([5]);
+   enum BigUint t = BigUint([7]);
+   enum BigUint s = BigUint.mod(r, t);
+   static assert(s == 5);
+}
 
 @safe pure unittest
 {
@@ -1725,7 +1736,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y)
             mulKaratsuba(result[half .. $], y, x[half .. $], scratchbuff);
             BigDigit c = addAssignSimple(result[half .. half + y.length], partial);
             if (c) multibyteIncrementAssign!('+')(result[half + y.length..$], c);
-            () @trusted { GC.free(scratchbuff.ptr); } ();
+            if (!__ctfe)
+            {
+                //use free only at runtime
+                () @trusted { GC.free(scratchbuff.ptr); } ();
+            }
         }
         else
         {
@@ -1784,7 +1799,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y)
                 addAssignSimple(result[done .. done + y.length + chunksize], partial);
                 done += chunksize;
             }
-            () @trusted { GC.free(scratchbuff.ptr); } ();
+            if (!__ctfe)
+            {
+                //use free only at runtime
+                () @trusted { GC.free(scratchbuff.ptr); } ();
+            }
         }
     }
     else
@@ -1792,7 +1811,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y)
         // Balanced. Use Karatsuba directly.
         BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)];
         mulKaratsuba(result, x, y, scratchbuff);
-        () @trusted { GC.free(scratchbuff.ptr); } ();
+        if (!__ctfe)
+        {
+            //use free only at runtime
+            () @trusted { GC.free(scratchbuff.ptr); } ();
+        }
     }
 }
 
@@ -1828,24 +1851,28 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y)
  */
 void squareInternal(BigDigit[] result, const BigDigit[] x) pure nothrow @safe
 {
-  import core.memory : GC;
-  // Squaring is potentially half a multiply, plus add the squares of
-  // the diagonal elements.
-  assert(result.length == 2*x.length,
-     "result needs to have twice the capacity of x");
-  if (x.length <= KARATSUBASQUARELIMIT)
-  {
-      if (x.length == 1)
-      {
-         result[1] = multibyteMul(result[0 .. 1], x, x[0], 0);
-         return;
-      }
-      return squareSimple(result, x);
-  }
-  // The nice thing about squaring is that it always stays balanced
-  BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)];
-  squareKaratsuba(result, x, scratchbuff);
-  () @trusted { GC.free(scratchbuff.ptr); } ();
+    import core.memory : GC;
+    // Squaring is potentially half a multiply, plus add the squares of
+    // the diagonal elements.
+    assert(result.length == 2*x.length,
+        "result needs to have twice the capacity of x");
+    if (x.length <= KARATSUBASQUARELIMIT)
+    {
+        if (x.length == 1)
+        {
+            result[1] = multibyteMul(result[0 .. 1], x, x[0], 0);
+            return;
+        }
+        return squareSimple(result, x);
+    }
+    // The nice thing about squaring is that it always stays balanced
+    BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)];
+    squareKaratsuba(result, x, scratchbuff);
+    if (!__ctfe)
+    {
+        //use free only at runtime
+        () @trusted { GC.free(scratchbuff.ptr); } ();
+    }
 }
 
 
@@ -1897,7 +1924,11 @@ void divModInternal(BigDigit [] quotient, BigDigit[] remainder, const BigDigit [
         if (s == 0) remainder[] = un[0 .. vn.length];
         else multibyteShr(remainder, un[0 .. vn.length+1], s);
     }
-    () @trusted { GC.free(un.ptr); GC.free(vn.ptr); } ();
+    if (!__ctfe)
+    {
+        //use free only at runtime
+        () @trusted { GC.free(un.ptr); GC.free(vn.ptr); } ();
+    }
 }
 
 pure @safe unittest
@@ -2842,7 +2873,11 @@ pure nothrow @safe
         m -= v.length;
     }
     recursiveDivMod(quotient[0 .. m], u[0 .. m + v.length], v, scratch);
-    () @trusted { GC.free(scratch.ptr); } ();
+    if (!__ctfe)
+    {
+        //use free only at runtime
+        () @trusted { GC.free(scratch.ptr); } ();
+    }
 }
 
 @system unittest
diff --git a/libphobos/src/std/internal/windows/bcrypt.d b/libphobos/src/std/internal/windows/bcrypt.d
deleted file mode 100644 (file)
index 239dcd5..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-module std.internal.windows.bcrypt;
-
-version (Windows):
-
-import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;
-import core.sys.windows.windef : HMODULE, PUCHAR, ULONG;
-import core.sys.windows.ntdef : NT_SUCCESS;
-
-pragma(lib, "Bcrypt.lib");
-
-package(std) bool bcryptGenRandom(T)(out T result) @trusted
-{
-    loadBcrypt();
-
-    const gotRandom = ptrBCryptGenRandom(
-        null,
-        cast(PUCHAR) &result,
-        ULONG(T.sizeof),
-        BCRYPT_USE_SYSTEM_PREFERRED_RNG,
-    );
-
-    return NT_SUCCESS(gotRandom);
-}
-
-private
-{
-    HMODULE hBcrypt = null;
-    typeof(BCryptGenRandom)* ptrBCryptGenRandom;
-}
-
-private void loadBcrypt() @nogc nothrow
-{
-    import core.sys.windows.winbase : GetProcAddress, LoadLibraryA;
-
-    if (!hBcrypt)
-    {
-        hBcrypt = LoadLibraryA("Bcrypt.dll");
-        if (!hBcrypt)
-            assert(false, `LoadLibraryA("Bcrypt.dll") failed.`); // `@nogc`
-
-        ptrBCryptGenRandom = cast(typeof(ptrBCryptGenRandom)) GetProcAddress(hBcrypt , "BCryptGenRandom");
-        if (!ptrBCryptGenRandom)
-            assert(false, `GetProcAddress(hBcrypt , "BCryptGenRandom") failed.`); // `@nogc`
-    }
-}
-
-// Will free `Bcrypt.dll`.
-private void freeBcrypt() @nogc nothrow
-{
-    import core.sys.windows.winbase : FreeLibrary;
-
-    if (hBcrypt)
-    {
-        if (!FreeLibrary(hBcrypt))
-            assert(false, `FreeLibrary("Bcrypt.dll") failed.`); // `@nogc`
-
-        hBcrypt = null;
-        ptrBCryptGenRandom = null;
-    }
-}
-
-static ~this()
-{
-    freeBcrypt();
-}
index eb08de8f048d9e6523f55f8a1e57016da6b9fcfb..2875faef947b85605d56d463bf3faba98499117a 100644 (file)
@@ -1058,6 +1058,41 @@ struct JSONValue
         }
     }
 
+    /// Calculate a numerical hash value for this value,
+    /// allowing `JSONValue` to be used in associative arrays.
+    hash_t toHash() const @nogc nothrow pure @trusted
+    {
+        final switch (type_tag)
+        {
+        case JSONType.integer:
+            return hashOf(store.integer);
+        case JSONType.uinteger:
+            return hashOf(store.uinteger);
+        case JSONType.float_:
+            return hashOf(store.floating);
+        case JSONType.string:
+            return hashOf(store.str);
+        case JSONType.object:
+            hash_t result = hashOf(type_tag);
+            if (!store.object.isOrdered)
+                foreach (ref pair; store.object.unordered.byKeyValue)
+                    result ^= hashOf(pair.key, pair.value.toHash());
+            else
+                foreach (ref pair; store.object.ordered)
+                    result ^= hashOf(pair.key, pair.value.toHash());
+            return result;
+        case JSONType.array:
+            hash_t result = hashOf(type_tag);
+            foreach (ref v; store.array)
+                result = hashOf(v, result);
+            return result;
+        case JSONType.true_:
+        case JSONType.false_:
+        case JSONType.null_:
+            return hashOf(type_tag);
+        }
+    }
+
     ///
     @safe unittest
     {
@@ -2736,3 +2771,15 @@ pure nothrow @safe unittest
 
     assert(app.data == s, app.data);
 }
+
+@safe unittest
+{
+    bool[JSONValue] aa;
+    aa[JSONValue("test")] = true;
+    assert(parseJSON(`"test"`) in aa);
+    assert(parseJSON(`"boo"`) !in aa);
+
+    aa[JSONValue(int(5))] = true;
+    assert(JSONValue(int(5)) in aa);
+    assert(JSONValue(uint(5)) in aa);
+}
index cfb88c89f7560533be030e2faabedede1373c525..f96f24f153f6a447d0e91c12e83ba1cf8baa87a1 100644 (file)
@@ -256,7 +256,7 @@ real sqrt(real x) @nogc @safe pure nothrow { return core.math.sqrt(x); }
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no) )
  *      )
  */
-real cbrt(real x) @trusted nothrow @nogc
+real cbrt(real x) @trusted pure nothrow @nogc
 {
     version (CRuntime_Microsoft)
     {
@@ -273,7 +273,7 @@ real cbrt(real x) @trusted nothrow @nogc
 }
 
 ///
-@safe unittest
+@safe pure unittest
 {
     import std.math.operations : feqrel;
 
@@ -294,10 +294,11 @@ real cbrt(real x) @trusted nothrow @nogc
  * hypot(x, -y) are equivalent.
  *
  *  $(TABLE_SV
- *  $(TR $(TH x)            $(TH y)            $(TH hypot(x, y)) $(TH invalid?))
- *  $(TR $(TD x)            $(TD $(PLUSMN)0.0) $(TD |x|)         $(TD no))
- *  $(TR $(TD $(PLUSMNINF)) $(TD y)            $(TD +$(INFIN))   $(TD no))
- *  $(TR $(TD $(PLUSMNINF)) $(TD $(NAN))       $(TD +$(INFIN))   $(TD no))
+ *  $(TR $(TH x)            $(TH y)                 $(TH hypot(x, y)) $(TH invalid?))
+ *  $(TR $(TD x)            $(TD $(PLUSMN)0.0)      $(TD |x|)         $(TD no))
+ *  $(TR $(TD $(PLUSMNINF)) $(TD y)                 $(TD +$(INFIN))   $(TD no))
+ *  $(TR $(TD $(PLUSMNINF)) $(TD $(NAN))            $(TD +$(INFIN))   $(TD no))
+ *  $(TR $(TD $(NAN))       $(TD y != $(PLUSMNINF)) $(TD $(NAN))      $(TD no))
  *  )
  */
 T hypot(T)(const T x, const T y) @safe pure nothrow @nogc
@@ -308,19 +309,22 @@ if (isFloatingPoint!T)
     // If both are huge, avoid overflow by scaling by 2^^-N.
     // If both are tiny, avoid underflow by scaling by 2^^N.
     import core.math : fabs, sqrt;
-    import std.math.traits : floatTraits, RealFormat;
+    import std.math.traits : floatTraits, RealFormat, isNaN;
 
     alias F = floatTraits!T;
 
     T u = fabs(x);
     T v = fabs(y);
-    if (!(u >= v))  // check for NaN as well.
+    if (!(u >= v))
     {
         v = u;
         u = fabs(y);
         if (u == T.infinity) return u; // hypot(inf, nan) == inf
         if (v == T.infinity) return v; // hypot(nan, inf) == inf
+        if (u.isNaN || v.isNaN)
+            return T.nan;
     }
+    assert(!(u.isNaN || v.isNaN), "Comparison to NaN always fails, thus is is always handled in the branch above");
 
     static if (F.realFormat == RealFormat.ieeeSingle)
     {
@@ -349,6 +353,13 @@ if (isFloatingPoint!T)
     else
         assert(0, "hypot not implemented");
 
+    if (u * T.epsilon > v)
+    {
+        // hypot (huge, tiny) = huge
+        // also: hypot(x, 0) = x
+        return u;
+    }
+
     // Now u >= v, or else one is NaN.
     T ratio = 1.0;
     if (v >= SQRTMAX)
@@ -368,12 +379,6 @@ if (isFloatingPoint!T)
         v *= SCALE_UNDERFLOW;
     }
 
-    if (u * T.epsilon > v)
-    {
-        // hypot (huge, tiny) = huge
-        return u;
-    }
-
     // both are in the normal range
     return ratio * sqrt(u*u + v*v);
 }
@@ -382,11 +387,16 @@ if (isFloatingPoint!T)
 @safe unittest
 {
     import std.math.operations : feqrel;
+    import std.math.traits : isNaN;
 
     assert(hypot(1.0, 1.0).feqrel(1.4142) > 16);
     assert(hypot(3.0, 4.0).feqrel(5.0) > 16);
     assert(hypot(real.infinity, 1.0L) == real.infinity);
+    assert(hypot(1.0L, real.infinity) == real.infinity);
     assert(hypot(real.infinity, real.nan) == real.infinity);
+    assert(hypot(real.nan, real.infinity) == real.infinity);
+    assert(hypot(real.nan, 1.0L).isNaN);
+    assert(hypot(1.0L, real.nan).isNaN);
 }
 
 @safe unittest
@@ -404,6 +414,16 @@ if (isFloatingPoint!T)
     assert(hypot(double.infinity, double.nan) == double.infinity);
 }
 
+// https://github.com/dlang/phobos/issues/10491
+@safe pure nothrow unittest
+{
+    import std.math : isClose;
+
+    enum small = 5.016556e-20f;
+    assert(hypot(small, 0).isClose(small));
+    assert(hypot(small, float.min_normal).isClose(small));
+}
+
 @safe unittest
 {
     import std.math.operations : feqrel;
index 7a72f428cd72a61285f1daec3f4e0a34f1272814..7e420289bbc6006d2ba34a2aee689b0e22a70799 100644 (file)
@@ -830,28 +830,39 @@ if (isUnsigned!F && isUnsigned!G && isUnsigned!H)
     {
         static if (T.sizeof == 8)
         {
-            static T addmod(T a, T b, T c)
+            if (c <= 0x100000000)
             {
-                b = c - b;
-                if (a >= b)
-                    return a - b;
-                else
-                    return c - b + a;
+                T result = a * b;
+                return result % c;
             }
+            else
+            {
+                import core.int128 : Cent, mul, udivmod;
 
-            T result = 0, tmp;
+                auto product = mul(a, b);
 
-            b %= c;
-            while (a > 0)
-            {
-                if (a & 1)
-                    result = addmod(result, b, c);
+                if (product.hi >= c)
+                {
+                    product.hi %= c;
+                }
 
-                a >>= 1;
-                b = addmod(b, b, c);
+                T remainder = void;
+                udivmod(product, c, remainder);
+                return remainder;
+            }
+        }
+        else static if (T.sizeof == 4)
+        {
+            if (c <= 0x10000)
+            {
+                T result = a * b;
+                return result % c;
+            }
+            else
+            {
+                DoubleT result = cast(DoubleT) (cast(DoubleT) a * cast(DoubleT) b);
+                return result % c;
             }
-
-            return result;
         }
         else
         {
index 07905fc7003838eef44782b100bd4232644d9569..efbb4f8811c0de9a60b39d229c9605c34187dc1b 100644 (file)
@@ -1226,9 +1226,10 @@ private auto _decodeContent(T)(ubyte[] content, string encoding)
     {
         import std.exception : enforce;
         import std.format : format;
+        import std.uni : icmp;
 
         // Optimally just return the utf8 encoded content
-        if (encoding == "UTF-8")
+        if (icmp(encoding, "UTF-8") == 0)
             return cast(char[])(content);
 
         // The content has to be re-encoded to utf8
index 5fb31566baf3c802c2d2fbbad5f366aa76feae05..13694ee875e1d821ff41b8cefeb96b8dfb52c1d3 100644 (file)
@@ -992,7 +992,7 @@ private auto _stripDrive(R)(R path)
     Returns:
         index of extension separator (the dot), or -1 if not found
 */
-private ptrdiff_t extSeparatorPos(R)(const R path)
+private ptrdiff_t extSeparatorPos(R)(R path)
 if (isRandomAccessRange!R && hasLength!R && isSomeChar!(ElementType!R) ||
     isNarrowString!R)
 {
@@ -1280,6 +1280,11 @@ if (isSomeChar!C1 && isSomeChar!C2)
     assert(withExtension("file.ext"w.byWchar, ".").array == "file."w);
 }
 
+@safe unittest
+{
+    assert(chainPath("directory", "file").withExtension(".ext").array == buildPath("directory", "file.ext"));
+}
+
 @safe unittest
 {
     import std.algorithm.comparison : equal;
index edb8902c649392526970ac96ba2dc383ed47417f..fb4e5469088f3eff13a7eaa125091c6e4c0e7d5b 100644 (file)
@@ -1774,71 +1774,41 @@ else
 
 version (linux)
 {
-    version (linux_legacy_emulate_getrandom)
-    {
-        /+
-            Emulates `getrandom()` for backwards compatibility
-            with outdated kernels and legacy libc versions.
-
-            `getrandom()` was added to the GNU C Library in v2.25.
-         +/
-        pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled.");
-
-        /+
-            On modern kernels (5.6+), `/dev/random` would behave more similar
-            to `getrandom()`.
-            However, this emulator was specifically written for systems older
-            than that. Hence, `/dev/urandom` is the CSPRNG of choice.
-
-            <https://web.archive.org/web/20200914181930/https://www.2uo.de/myths-about-urandom/>
-         +/
-        private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom";
-
-        import core.sys.posix.sys.types : ssize_t;
-
-        /+
-            Linux `getrandom()` emulation built upon `/dev/urandom`.
-            The fourth parameter (`uint flags`) is happily ignored.
-         +/
-        private ssize_t getrandom(
-                void* buf,
-                size_t buflen,
-                uint,
-        ) @system nothrow @nogc
-        {
-            import core.stdc.stdio : fclose, fopen, fread;
+    // `getrandom()` was introduced in Linux 3.17.
 
-            auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r");
-            if (blockDev is null)
-                assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed.");
-            scope (exit) fclose(blockDev);
-
-            const bytesRead = fread(buf, 1, buflen, blockDev);
-            return bytesRead;
-        }
-    }
+    // Shim for missing bindings in druntime
+    version (none)
+        import core.sys.linux.sys.random : getrandom;
     else
     {
-        // `getrandom()` was introduced in Linux 3.17.
-
-        // Shim for missing bindings in druntime
-        version (none)
-            import core.sys.linux.sys.random : getrandom;
-        else
-        {
-            import core.sys.posix.sys.types : ssize_t;
-            private extern extern(C) ssize_t getrandom(
-                void* buf,
-                size_t buflen,
-                uint flags,
-            ) @system nothrow @nogc;
-        }
+        import core.sys.posix.sys.types : ssize_t;
+        extern extern(C) ssize_t getrandom(
+            void* buf,
+            size_t buflen,
+            uint flags,
+        ) @system nothrow @nogc;
     }
 }
 
 version (Windows)
 {
-    import std.internal.windows.bcrypt : bcryptGenRandom;
+    pragma(lib, "Bcrypt.lib");
+
+    private bool bcryptGenRandom(T)(out T result) @trusted
+    {
+        import core.sys.windows.windef : PUCHAR, ULONG;
+        import core.sys.windows.ntdef : NT_SUCCESS;
+        import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;
+
+        const gotRandom = BCryptGenRandom(
+            null,
+            cast(PUCHAR) &result,
+            ULONG(T.sizeof),
+            BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+        );
+
+        return NT_SUCCESS(gotRandom);
+    }
 }
 
 /**
index ab6ade0e1d8b3f4247a0a8f004c672dee2c2e2e9..1a26235a08bf689d8957eba8f2306198b19b8f6f 100644 (file)
@@ -32,9 +32,9 @@ version (D_BetterC) {} else
 {
     import std.math.operations : isClose;
 
-    struct Fahrenheit { double degrees; }
-    struct Celsius { double degrees; }
-    struct Kelvin { double degrees; }
+    struct Fahrenheit { double value; }
+    struct Celsius { double value; }
+    struct Kelvin { double value; }
 
     alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin);
 
@@ -48,29 +48,29 @@ version (D_BetterC) {} else
     {
         return Fahrenheit(
             t.match!(
-                (Fahrenheit f) => f.degrees,
-                (Celsius c) => c.degrees * 9.0/5 + 32,
-                (Kelvin k) => k.degrees * 9.0/5 - 459.4
+                (Fahrenheit f) => f.value,
+                (Celsius c) => c.value * 9.0/5 + 32,
+                (Kelvin k) => k.value * 9.0/5 - 459.4
             )
         );
     }
 
-    assert(toFahrenheit(t1).degrees.isClose(98.6));
-    assert(toFahrenheit(t2).degrees.isClose(212));
-    assert(toFahrenheit(t3).degrees.isClose(32));
+    assert(toFahrenheit(t1).value.isClose(98.6));
+    assert(toFahrenheit(t2).value.isClose(212));
+    assert(toFahrenheit(t3).value.isClose(32));
 
     // Use ref to modify the value in place.
     void freeze(ref Temperature t)
     {
         t.match!(
-            (ref Fahrenheit f) => f.degrees = 32,
-            (ref Celsius c) => c.degrees = 0,
-            (ref Kelvin k) => k.degrees = 273
+            (ref Fahrenheit f) => f.value = 32,
+            (ref Celsius c) => c.value = 0,
+            (ref Kelvin k) => k.value = 273
         );
     }
 
     freeze(t1);
-    assert(toFahrenheit(t1).degrees.isClose(32));
+    assert(toFahrenheit(t1).value.isClose(32));
 
     // Use a catch-all handler to give a default result.
     bool isFahrenheit(Temperature t)
index f230aa3b74e43a006243d3983ab705dd0aadc139..9bdd9775f9cb4d231431a3ee00d2492b992af0fe 100644 (file)
@@ -4728,10 +4728,7 @@ It will return `void` if a symbol without a template is given.
 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
 
 /// ditto
-alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
-
-/// ditto
-alias TemplateOf(T) = void;
+alias TemplateOf(alias T) = void;
 
 ///
 @safe unittest
@@ -4768,6 +4765,10 @@ alias TemplateOf(T) = void;
 {
     static assert(is(TemplateOf!(int[]) == void));
     static assert(is(TemplateOf!bool == void));
+
+    // https://github.com/dlang/phobos/issues/10527
+    static void foo() {}
+    static assert(is(TemplateOf!foo == void));
 }
 
 /**
index 09ce2f73f380c1da4da4714210d8d47b9c25c900..3a054a5aef34663b1315de2a83e0f854bdc60d09 100644 (file)
@@ -1204,32 +1204,52 @@ public struct UUID
  *
  * This function is not supported at compile time.
  *
+ * Bugs:
+ * $(LINK2 https://github.com/dlang/phobos/issues/9881, Issue #9881 - Randomness in UUID generation is insufficient)
+ *
+ * Warning:
+ * $(B This function must not be used for cryptographic purposes.)
+ * UUIDs generated by this function do not have sufficient randomness
+ * for all use cases.
+ * This especially applies to the overload that accepts a caller-provided RNG.
+ * At the moment, Phobos does not provide a $(I cryptographically-secure
+ * pseudo-random number generator (CSPRNG)) that could be supplied to this
+ * function.
+ *
+ * While the function overload with no parameters will attempt to use the
+ * system CSPRNG where available and implemented, there are no guarantees.
+ * See $(REF unpredictableSeed, std, random) for details.
+ *
  * Params:
  *      randomGen = uniform RNG
  * See_Also: $(REF isUniformRNG, std,random)
  */
 @nogc nothrow @safe UUID randomUUID()
 {
-    import std.random : rndGen;
-    // A PRNG with fewer than `n` bytes of state cannot produce
-    // every distinct `n` byte sequence.
-    static if (typeof(rndGen).sizeof >= UUID.sizeof)
-    {
-        return randomUUID(rndGen);
-    }
-    else
-    {
-        import std.random : unpredictableSeed, Xorshift192;
-        static assert(Xorshift192.sizeof >= UUID.sizeof);
-        static Xorshift192 rng;
-        static bool initialized;
-        if (!initialized)
-        {
-            rng.seed(unpredictableSeed);
-            initialized = true;
-        }
-        return randomUUID(rng);
-    }
+    import std.conv : bitCast;
+    import std.random : unpredictableSeed;
+
+    enum bufferSize = UUID.data.sizeof;
+    ubyte[bufferSize] data;
+
+    static assert(ulong.sizeof * 2 == bufferSize);
+    const half1 = unpredictableSeed!ulong();
+    const half2 = unpredictableSeed!ulong();
+
+    data[0 .. ulong.sizeof] = (() @trusted => half1.bitCast!(ubyte[ulong.sizeof]))();
+    data[ulong.sizeof .. $] = (() @trusted => half2.bitCast!(ubyte[ulong.sizeof]))();
+
+    // set variant
+    // must be 0b_10xxxxxx
+    data[8] &= 0b_10_111111;
+    data[8] |= 0b_10_000000;
+
+    // set version
+    // must be 0b_0100xxxx
+    data[6] &= 0b_0100_1111;
+    data[6] |= 0b_0100_0000;
+
+    return UUID(data);
 }
 
 /// ditto
index a0b564440120ed0ca96b8fdfee0f4161f8519565..a094aeb3409e6cc65f50abed96c1a9189ee369b6 100644 (file)
@@ -850,7 +850,14 @@ public:
      */
     @property inout(T) get(T)() inout
     {
-        inout(T) result = void;
+        static union SupressDestructor {
+            T val;
+        }
+
+        /* If this function fails and it throws, copy elision will not run and the destructor might be called.
+         * But since this value is void initialized, this is undesireable.
+         */
+        inout(SupressDestructor) result = void;
         static if (is(T == shared))
             alias R = shared Unqual!T;
         else
@@ -861,7 +868,7 @@ public:
         {
             throw new VariantException(type, typeid(T));
         }
-        return result;
+        return result.val;
     }
 
     /// Ditto
@@ -3255,3 +3262,44 @@ if (isAlgebraic!VariantType && Handler.length > 0)
     immutable aa = ["0": 0];
     auto v = Variant(aa); // compile error
 }
+
+// https://github.com/dlang/phobos/issues/9585
+// Verify that alignment is respected
+@safe unittest
+{
+    static struct Foo { double x; }
+    alias AFoo1 = Algebraic!(Foo);
+    static assert(AFoo1.alignof >= double.alignof);
+
+    // Algebraic using a function pointer is an implementation detail. If test fails, this is safe to change
+    enum FP_SIZE = (int function()).sizeof;
+    static assert(AFoo1.sizeof >= double.sizeof + FP_SIZE);
+}
+
+// https://github.com/dlang/phobos/issues/10518
+@system unittest
+{
+    import std.exception : assertThrown;
+
+    struct Huge {
+        real a, b, c, d, e, f, g;
+    }
+    Huge h = {1,1,1,1,1,1,1};
+    Variant variant = Variant([
+            "one": Variant(1),
+    ]);
+    // Testing that this doesn't segfault. Future work might make enable this
+    assertThrown!VariantException(variant["three"] = 3);
+    assertThrown!VariantException(variant["four"] = Variant(4));
+    /* Storing huge works too, value will moved to the heap
+    * Testing this as a regression test here as the AA handling code is still somewhat brittle and might add changes
+    * that depend payload size in the future
+    */
+    assertThrown!VariantException(variant["huge"] = Variant(h));
+    /+
+    assert(variant["one"] == Variant(1));
+    assert(variant["three"] == Variant(3));
+    assert(variant["three"] == 3);
+    assert(variant["huge"] == Variant(h));
+    +/
+}