]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge upstream dmd 568496d5b, druntime 178c44ff, phobos 574bf883b.
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 5 Dec 2021 16:11:12 +0000 (17:11 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Wed, 8 Dec 2021 23:58:58 +0000 (00:58 +0100)
D front-end changes:

    - Import dmd v2.098.0
    - New ImportC module for compiling preprocessed C11 code into D.
    - New -ftransition=in switch.
    - Improved handling of new 'noreturn' type.

Druntime changes:

    - Import druntime v2.098.0
    - Fix broken import in core.sys.linux.perf_event module (PR103558).

Phobos changes:

    - Import phobos v2.098.0
    - All sources are now compiled with -fpreview=fieldwise.

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd 568496d5b.
* Make-lang.in (D_FRONTEND_OBJS): Add d/common-file.o,
d/common-outbuffer.o, d/common-string.o, d/file_manager.o,
d/importc.o.  Remove d/root-outbuffer.o.
(d/common-%.o): New recipe.
* d-builtins.cc (build_frontend_type): Update for new front-end
interface.
(d_build_d_type_nodes): Set noreturn_type_node.
* d-codegen.cc (d_build_call): Don't call function if one of the
arguments is type 'noreturn'.
(build_vthis_function): Propagate TYPE_QUAL_VOLATILE from original
function type.
* d-frontend.cc (eval_builtin): Update signature.
(getTypeInfoType): Likewise.
(toObjFile): New function.
* d-gimplify.cc (d_gimplify_call_expr): Always evaluate arguments from
left to right.
* d-lang.cc (d_handle_option): Handle OPT_ftransition_in.
(d_parse_file): Don't generate D main if it is declared in user code.
* d-tree.h (CALL_EXPR_ARGS_ORDERED): Remove.
(enum d_tree_index): Add DTI_BOTTOM_TYPE.
(noreturn_type_node): New.
* decl.cc (apply_pragma_crt): Remove.
(DeclVisitor::visit): Update for new front-end interface.
(DeclVisitor::visit (PragmaDeclaration *)): Don't handle
crt_constructor and crt_destructor pragmas.
(DeclVisitor::visit (VarDeclaration *)): Don't generate declarations
of type 'noreturn'.
(DeclVisitor::visit (FuncDeclaration *)): Stop adding parameters when
'noreturn' type has been encountered.
(get_symbol_decl): Set DECL_STATIC_CONSTRUCTOR and
DECL_STATIC_DESTRUCTOR on decl node if requested.
(aggregate_initializer_decl): Update for new front-end interface.
* expr.cc (ExprVisitor::visit (CallExp *)): Always use the 'this'
object as the result of calling any constructor function.
(ExprVisitor::visit): Update for new front-end interface.
* gdc.texi (Runtime Options): Document -fmain and -ftransition=in.
* lang.opt (ftransition=in): New option.
* modules.cc (get_internal_fn): Update for new front-end interface.
* types.cc (TypeVisitor::visit): Likewise.
(TypeVisitor::visit (TypeNoreturn *)): Return noreturn_type_node.
(TypeVisitor::visit (TypeFunction *)): Stop adding parameters when
'notreturn' type has been encountered.  Qualify function types that
return 'noreturn' as TYPE_QUAL_VOLATILE.

libphobos/ChangeLog:

PR d/103558
* libdruntime/MERGE: Merge upstream druntime 178c44ff.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES_LINUX): Add
core/sys/linux/syscalls.d.
(DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/pthread_np.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 574bf883b.
* src/Makefile.am (D_EXTRA_DFLAGS): Add -fpreview=fieldwise.
* src/Makefile.in: Regenerate.
* testsuite/libphobos.exceptions/assert_fail.d: Update test.
* testsuite/libphobos.betterc/test22336.d: New test.

443 files changed:
gcc/d/Make-lang.in
gcc/d/d-builtins.cc
gcc/d/d-codegen.cc
gcc/d/d-frontend.cc
gcc/d/d-gimplify.cc
gcc/d/d-lang.cc
gcc/d/d-tree.h
gcc/d/decl.cc
gcc/d/dmd/MERGE
gcc/d/dmd/README.md
gcc/d/dmd/VERSION
gcc/d/dmd/aggregate.d
gcc/d/dmd/aggregate.h
gcc/d/dmd/aliasthis.d
gcc/d/dmd/arrayop.d
gcc/d/dmd/attrib.d
gcc/d/dmd/blockexit.d
gcc/d/dmd/builtin.d
gcc/d/dmd/chkformat.d
gcc/d/dmd/clone.d
gcc/d/dmd/common/README.md [new file with mode: 0644]
gcc/d/dmd/common/file.d [new file with mode: 0644]
gcc/d/dmd/common/outbuffer.d [moved from gcc/d/dmd/root/outbuffer.d with 77% similarity]
gcc/d/dmd/common/outbuffer.h [moved from gcc/d/dmd/root/outbuffer.h with 90% similarity]
gcc/d/dmd/common/string.d [new file with mode: 0644]
gcc/d/dmd/cond.d
gcc/d/dmd/cparse.d
gcc/d/dmd/cppmangle.d
gcc/d/dmd/ctfeexpr.d
gcc/d/dmd/dcast.d
gcc/d/dmd/dclass.d
gcc/d/dmd/declaration.d
gcc/d/dmd/declaration.h
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dmacro.d
gcc/d/dmd/dmangle.d
gcc/d/dmd/dmodule.d
gcc/d/dmd/doc.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/dtoh.d
gcc/d/dmd/dversion.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/file_manager.d [new file with mode: 0644]
gcc/d/dmd/file_manager.h [moved from gcc/d/dmd/root/root.h with 50% similarity]
gcc/d/dmd/func.d
gcc/d/dmd/globals.d
gcc/d/dmd/globals.h
gcc/d/dmd/gluelayer.d
gcc/d/dmd/hdrgen.d
gcc/d/dmd/iasmgcc.d
gcc/d/dmd/id.d
gcc/d/dmd/identifier.d
gcc/d/dmd/importc.d [new file with mode: 0644]
gcc/d/dmd/init.d
gcc/d/dmd/initsem.d
gcc/d/dmd/intrange.h [deleted file]
gcc/d/dmd/json.d
gcc/d/dmd/lambdacomp.d
gcc/d/dmd/lexer.d
gcc/d/dmd/lexer.h [deleted file]
gcc/d/dmd/macro.h [deleted file]
gcc/d/dmd/mars.h [deleted file]
gcc/d/dmd/module.h
gcc/d/dmd/mtype.d
gcc/d/dmd/mtype.h
gcc/d/dmd/ob.d
gcc/d/dmd/objc.d
gcc/d/dmd/opover.d
gcc/d/dmd/optimize.d
gcc/d/dmd/parse.d
gcc/d/dmd/parse.h [deleted file]
gcc/d/dmd/printast.d
gcc/d/dmd/root/README.md
gcc/d/dmd/root/aav.h [deleted file]
gcc/d/dmd/root/checkedint.h [deleted file]
gcc/d/dmd/root/file.d
gcc/d/dmd/root/filename.d
gcc/d/dmd/root/hash.h [deleted file]
gcc/d/dmd/root/rootobject.d
gcc/d/dmd/root/speller.h [deleted file]
gcc/d/dmd/root/stringtable.h [deleted file]
gcc/d/dmd/safe.d
gcc/d/dmd/semantic2.d
gcc/d/dmd/semantic3.d
gcc/d/dmd/statement.d
gcc/d/dmd/statement.h
gcc/d/dmd/statement_rewrite_walker.h [deleted file]
gcc/d/dmd/statementsem.d
gcc/d/dmd/staticcond.d
gcc/d/dmd/target.d
gcc/d/dmd/target.h
gcc/d/dmd/template.h
gcc/d/dmd/tokens.d
gcc/d/dmd/tokens.h
gcc/d/dmd/traits.d
gcc/d/dmd/typesem.d
gcc/d/dmd/typinf.d
gcc/d/dmd/utf.h [deleted file]
gcc/d/dmd/utils.d
gcc/d/expr.cc
gcc/d/gdc.texi
gcc/d/lang.opt
gcc/d/modules.cc
gcc/d/types.cc
gcc/testsuite/gdc.test/compilable/b19294.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/cdcmp.d
gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
gcc/testsuite/gdc.test/compilable/imports/cstuff3.c [deleted file]
gcc/testsuite/gdc.test/compilable/mixintype2.d
gcc/testsuite/gdc.test/compilable/noreturn1.d
gcc/testsuite/gdc.test/compilable/previewall.d [deleted file]
gcc/testsuite/gdc.test/compilable/reinterpretctfe.d
gcc/testsuite/gdc.test/compilable/sroa.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/stc_traits.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test15711.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test16492.d [deleted file]
gcc/testsuite/gdc.test/compilable/test19482.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test21438.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test21794.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test21850.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22214.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22224.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22228.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22292.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22388.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22410.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22420.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test22421.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test318.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test4090.d
gcc/testsuite/gdc.test/compilable/test9766.d
gcc/testsuite/gdc.test/compilable/testcstuff3.d [deleted file]
gcc/testsuite/gdc.test/compilable/transition_in.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/zerosize.d
gcc/testsuite/gdc.test/fail_compilation/diag10327.d
gcc/testsuite/gdc.test/fail_compilation/diag20059.d
gcc/testsuite/gdc.test/fail_compilation/fail20618.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail21091a.d
gcc/testsuite/gdc.test/fail_compilation/fail21091b.d
gcc/testsuite/gdc.test/fail_compilation/fail22084.d
gcc/testsuite/gdc.test/fail_compilation/fail22151.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail22366.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail225.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail287.d
gcc/testsuite/gdc.test/fail_compilation/fail318.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail318_b.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail7173.d
gcc/testsuite/gdc.test/fail_compilation/foreach.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/foreach2.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/ice10212.d
gcc/testsuite/gdc.test/fail_compilation/ice22377.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/ice7782.d
gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/noreturn.d
gcc/testsuite/gdc.test/fail_compilation/noreturn2.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
gcc/testsuite/gdc.test/fail_compilation/test17425.d
gcc/testsuite/gdc.test/fail_compilation/test17868b.d
gcc/testsuite/gdc.test/fail_compilation/test20998.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21093.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21380.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test21930.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test22329.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test22361.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/testOpApply.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/aliasthis.d
gcc/testsuite/gdc.test/runnable/dhry.d
gcc/testsuite/gdc.test/runnable/fix22372.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/interpret.d
gcc/testsuite/gdc.test/runnable/noreturn1.d
gcc/testsuite/gdc.test/runnable/noreturn2.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/sroa13220.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test15624.d [deleted file]
gcc/testsuite/gdc.test/runnable/test21039.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test22205.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test22278.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/testOpApply.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/testmainb.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/uda.d
gcc/testsuite/gdc.test/runnable/ufcs.d
gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable_cxx/test22287.d [new file with mode: 0644]
libphobos/libdruntime/MERGE
libphobos/libdruntime/Makefile.am
libphobos/libdruntime/Makefile.in
libphobos/libdruntime/core/demangle.d
libphobos/libdruntime/core/exception.d
libphobos/libdruntime/core/internal/array/construction.d
libphobos/libdruntime/core/internal/atomic.d
libphobos/libdruntime/core/internal/dassert.d
libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
libphobos/libdruntime/core/internal/gc/os.d
libphobos/libdruntime/core/internal/hash.d
libphobos/libdruntime/core/internal/parseoptions.d
libphobos/libdruntime/core/internal/traits.d
libphobos/libdruntime/core/internal/util/array.d
libphobos/libdruntime/core/lifetime.d
libphobos/libdruntime/core/runtime.d
libphobos/libdruntime/core/stdc/stdlib.d
libphobos/libdruntime/core/sync/rwmutex.d
libphobos/libdruntime/core/sys/freebsd/config.d
libphobos/libdruntime/core/sys/linux/fs.d
libphobos/libdruntime/core/sys/linux/perf_event.d
libphobos/libdruntime/core/sys/linux/sys/mman.d
libphobos/libdruntime/core/sys/linux/syscalls.d [new file with mode: 0644]
libphobos/libdruntime/core/sys/linux/unistd.d
libphobos/libdruntime/core/sys/openbsd/dlfcn.d
libphobos/libdruntime/core/sys/openbsd/pthread_np.d [new file with mode: 0644]
libphobos/libdruntime/core/sys/openbsd/stdlib.d
libphobos/libdruntime/core/sys/openbsd/string.d
libphobos/libdruntime/core/sys/openbsd/sys/mman.d
libphobos/libdruntime/core/sys/openbsd/sys/sysctl.d
libphobos/libdruntime/core/sys/openbsd/unistd.d
libphobos/libdruntime/core/sys/posix/netdb.d
libphobos/libdruntime/core/sys/posix/sys/filio.d
libphobos/libdruntime/core/sys/posix/sys/ioccom.d
libphobos/libdruntime/core/sys/posix/sys/ioctl.d
libphobos/libdruntime/core/sys/posix/sys/mman.d
libphobos/libdruntime/core/sys/posix/sys/socket.d
libphobos/libdruntime/core/sys/posix/sys/ttycom.d
libphobos/libdruntime/core/sys/posix/time.d
libphobos/libdruntime/core/sys/windows/accctrl.d
libphobos/libdruntime/core/sys/windows/aclapi.d
libphobos/libdruntime/core/sys/windows/aclui.d
libphobos/libdruntime/core/sys/windows/basetsd.d
libphobos/libdruntime/core/sys/windows/basetyps.d
libphobos/libdruntime/core/sys/windows/cderr.d
libphobos/libdruntime/core/sys/windows/cguid.d
libphobos/libdruntime/core/sys/windows/comcat.d
libphobos/libdruntime/core/sys/windows/commctrl.d
libphobos/libdruntime/core/sys/windows/commdlg.d
libphobos/libdruntime/core/sys/windows/core.d
libphobos/libdruntime/core/sys/windows/cpl.d
libphobos/libdruntime/core/sys/windows/cplext.d
libphobos/libdruntime/core/sys/windows/custcntl.d
libphobos/libdruntime/core/sys/windows/dbt.d
libphobos/libdruntime/core/sys/windows/dde.d
libphobos/libdruntime/core/sys/windows/ddeml.d
libphobos/libdruntime/core/sys/windows/dhcpcsdk.d
libphobos/libdruntime/core/sys/windows/dlgs.d
libphobos/libdruntime/core/sys/windows/dll.d
libphobos/libdruntime/core/sys/windows/docobj.d
libphobos/libdruntime/core/sys/windows/errorrep.d
libphobos/libdruntime/core/sys/windows/exdisp.d
libphobos/libdruntime/core/sys/windows/exdispid.d
libphobos/libdruntime/core/sys/windows/httpext.d
libphobos/libdruntime/core/sys/windows/idispids.d
libphobos/libdruntime/core/sys/windows/imagehlp.d
libphobos/libdruntime/core/sys/windows/imm.d
libphobos/libdruntime/core/sys/windows/intshcut.d
libphobos/libdruntime/core/sys/windows/ipexport.d
libphobos/libdruntime/core/sys/windows/iphlpapi.d
libphobos/libdruntime/core/sys/windows/ipifcons.d
libphobos/libdruntime/core/sys/windows/iprtrmib.d
libphobos/libdruntime/core/sys/windows/iptypes.d
libphobos/libdruntime/core/sys/windows/isguids.d
libphobos/libdruntime/core/sys/windows/lm.d
libphobos/libdruntime/core/sys/windows/lmaccess.d
libphobos/libdruntime/core/sys/windows/lmalert.d
libphobos/libdruntime/core/sys/windows/lmapibuf.d
libphobos/libdruntime/core/sys/windows/lmat.d
libphobos/libdruntime/core/sys/windows/lmaudit.d
libphobos/libdruntime/core/sys/windows/lmbrowsr.d
libphobos/libdruntime/core/sys/windows/lmchdev.d
libphobos/libdruntime/core/sys/windows/lmconfig.d
libphobos/libdruntime/core/sys/windows/lmcons.d
libphobos/libdruntime/core/sys/windows/lmerr.d
libphobos/libdruntime/core/sys/windows/lmerrlog.d
libphobos/libdruntime/core/sys/windows/lmmsg.d
libphobos/libdruntime/core/sys/windows/lmremutl.d
libphobos/libdruntime/core/sys/windows/lmrepl.d
libphobos/libdruntime/core/sys/windows/lmserver.d
libphobos/libdruntime/core/sys/windows/lmshare.d
libphobos/libdruntime/core/sys/windows/lmsname.d
libphobos/libdruntime/core/sys/windows/lmstats.d
libphobos/libdruntime/core/sys/windows/lmsvc.d
libphobos/libdruntime/core/sys/windows/lmuse.d
libphobos/libdruntime/core/sys/windows/lmuseflg.d
libphobos/libdruntime/core/sys/windows/lmwksta.d
libphobos/libdruntime/core/sys/windows/lzexpand.d
libphobos/libdruntime/core/sys/windows/mapi.d
libphobos/libdruntime/core/sys/windows/mciavi.d
libphobos/libdruntime/core/sys/windows/mcx.d
libphobos/libdruntime/core/sys/windows/mgmtapi.d
libphobos/libdruntime/core/sys/windows/mmsystem.d
libphobos/libdruntime/core/sys/windows/msacm.d
libphobos/libdruntime/core/sys/windows/mshtml.d
libphobos/libdruntime/core/sys/windows/mswsock.d
libphobos/libdruntime/core/sys/windows/nb30.d
libphobos/libdruntime/core/sys/windows/nddeapi.d
libphobos/libdruntime/core/sys/windows/nspapi.d
libphobos/libdruntime/core/sys/windows/ntdef.d
libphobos/libdruntime/core/sys/windows/ntdll.d
libphobos/libdruntime/core/sys/windows/ntldap.d
libphobos/libdruntime/core/sys/windows/ntsecapi.d
libphobos/libdruntime/core/sys/windows/ntsecpkg.d
libphobos/libdruntime/core/sys/windows/oaidl.d
libphobos/libdruntime/core/sys/windows/objbase.d
libphobos/libdruntime/core/sys/windows/objfwd.d
libphobos/libdruntime/core/sys/windows/objidl.d
libphobos/libdruntime/core/sys/windows/objsafe.d
libphobos/libdruntime/core/sys/windows/ocidl.d
libphobos/libdruntime/core/sys/windows/odbcinst.d
libphobos/libdruntime/core/sys/windows/ole.d
libphobos/libdruntime/core/sys/windows/ole2.d
libphobos/libdruntime/core/sys/windows/ole2ver.d
libphobos/libdruntime/core/sys/windows/oleacc.d
libphobos/libdruntime/core/sys/windows/oleauto.d
libphobos/libdruntime/core/sys/windows/olectl.d
libphobos/libdruntime/core/sys/windows/olectlid.d
libphobos/libdruntime/core/sys/windows/oledlg.d
libphobos/libdruntime/core/sys/windows/oleidl.d
libphobos/libdruntime/core/sys/windows/pbt.d
libphobos/libdruntime/core/sys/windows/powrprof.d
libphobos/libdruntime/core/sys/windows/prsht.d
libphobos/libdruntime/core/sys/windows/psapi.d
libphobos/libdruntime/core/sys/windows/rapi.d
libphobos/libdruntime/core/sys/windows/ras.d
libphobos/libdruntime/core/sys/windows/rasdlg.d
libphobos/libdruntime/core/sys/windows/raserror.d
libphobos/libdruntime/core/sys/windows/rassapi.d
libphobos/libdruntime/core/sys/windows/reason.d
libphobos/libdruntime/core/sys/windows/regstr.d
libphobos/libdruntime/core/sys/windows/richedit.d
libphobos/libdruntime/core/sys/windows/richole.d
libphobos/libdruntime/core/sys/windows/rpc.d
libphobos/libdruntime/core/sys/windows/rpcdce.d
libphobos/libdruntime/core/sys/windows/rpcdce2.d
libphobos/libdruntime/core/sys/windows/rpcdcep.d
libphobos/libdruntime/core/sys/windows/rpcndr.d
libphobos/libdruntime/core/sys/windows/rpcnsi.d
libphobos/libdruntime/core/sys/windows/rpcnsip.d
libphobos/libdruntime/core/sys/windows/rpcnterr.d
libphobos/libdruntime/core/sys/windows/schannel.d
libphobos/libdruntime/core/sys/windows/sdkddkver.d
libphobos/libdruntime/core/sys/windows/secext.d
libphobos/libdruntime/core/sys/windows/security.d
libphobos/libdruntime/core/sys/windows/servprov.d
libphobos/libdruntime/core/sys/windows/setupapi.d
libphobos/libdruntime/core/sys/windows/shellapi.d
libphobos/libdruntime/core/sys/windows/shldisp.d
libphobos/libdruntime/core/sys/windows/shlguid.d
libphobos/libdruntime/core/sys/windows/shlobj.d
libphobos/libdruntime/core/sys/windows/shlwapi.d
libphobos/libdruntime/core/sys/windows/snmp.d
libphobos/libdruntime/core/sys/windows/sql.d
libphobos/libdruntime/core/sys/windows/sqlext.d
libphobos/libdruntime/core/sys/windows/sqltypes.d
libphobos/libdruntime/core/sys/windows/sqlucode.d
libphobos/libdruntime/core/sys/windows/sspi.d
libphobos/libdruntime/core/sys/windows/stdc/malloc.d
libphobos/libdruntime/core/sys/windows/subauth.d
libphobos/libdruntime/core/sys/windows/tlhelp32.d
libphobos/libdruntime/core/sys/windows/tmschema.d
libphobos/libdruntime/core/sys/windows/unknwn.d
libphobos/libdruntime/core/sys/windows/vfw.d
libphobos/libdruntime/core/sys/windows/w32api.d
libphobos/libdruntime/core/sys/windows/winbase.d
libphobos/libdruntime/core/sys/windows/winber.d
libphobos/libdruntime/core/sys/windows/wincon.d
libphobos/libdruntime/core/sys/windows/wincrypt.d
libphobos/libdruntime/core/sys/windows/windef.d
libphobos/libdruntime/core/sys/windows/windows.d
libphobos/libdruntime/core/sys/windows/winerror.d
libphobos/libdruntime/core/sys/windows/wingdi.d
libphobos/libdruntime/core/sys/windows/winhttp.d
libphobos/libdruntime/core/sys/windows/wininet.d
libphobos/libdruntime/core/sys/windows/winioctl.d
libphobos/libdruntime/core/sys/windows/winldap.d
libphobos/libdruntime/core/sys/windows/winnetwk.d
libphobos/libdruntime/core/sys/windows/winnls.d
libphobos/libdruntime/core/sys/windows/winnt.d
libphobos/libdruntime/core/sys/windows/winperf.d
libphobos/libdruntime/core/sys/windows/winreg.d
libphobos/libdruntime/core/sys/windows/winspool.d
libphobos/libdruntime/core/sys/windows/winsvc.d
libphobos/libdruntime/core/sys/windows/winuser.d
libphobos/libdruntime/core/sys/windows/winver.d
libphobos/libdruntime/core/sys/windows/wtsapi32.d
libphobos/libdruntime/core/sys/windows/wtypes.d
libphobos/libdruntime/core/thread/fiber.d
libphobos/libdruntime/core/thread/osthread.d
libphobos/libdruntime/core/time.d
libphobos/libdruntime/object.d
libphobos/libdruntime/rt/aApplyR.d
libphobos/libdruntime/rt/aaA.d
libphobos/libdruntime/rt/dmain2.d
libphobos/src/MERGE
libphobos/src/Makefile.am
libphobos/src/Makefile.in
libphobos/src/etc/c/curl.d
libphobos/src/index.dd [moved from libphobos/src/index.d with 100% similarity]
libphobos/src/std/algorithm/comparison.d
libphobos/src/std/algorithm/iteration.d
libphobos/src/std/algorithm/mutation.d
libphobos/src/std/algorithm/searching.d
libphobos/src/std/algorithm/sorting.d
libphobos/src/std/array.d
libphobos/src/std/bitmanip.d
libphobos/src/std/concurrency.d
libphobos/src/std/container/array.d
libphobos/src/std/datetime/systime.d
libphobos/src/std/datetime/timezone.d
libphobos/src/std/digest/ripemd.d
libphobos/src/std/exception.d
libphobos/src/std/experimental/checkedint.d
libphobos/src/std/file.d
libphobos/src/std/format/internal/floats.d
libphobos/src/std/format/internal/write.d
libphobos/src/std/functional.d
libphobos/src/std/getopt.d
libphobos/src/std/internal/math/biguintcore.d
libphobos/src/std/internal/windows/advapi32.d
libphobos/src/std/json.d
libphobos/src/std/math/algebraic.d
libphobos/src/std/math/operations.d
libphobos/src/std/meta.d
libphobos/src/std/parallelism.d
libphobos/src/std/process.d
libphobos/src/std/random.d
libphobos/src/std/range/interfaces.d
libphobos/src/std/range/package.d
libphobos/src/std/range/primitives.d
libphobos/src/std/socket.d
libphobos/src/std/stdio.d
libphobos/src/std/string.d
libphobos/src/std/system.d
libphobos/src/std/traits.d
libphobos/src/std/typecons.d
libphobos/src/std/uni/package.d
libphobos/src/std/variant.d
libphobos/src/std/windows/registry.d
libphobos/testsuite/libphobos.betterc/test22336.d [new file with mode: 0644]
libphobos/testsuite/libphobos.exceptions/assert_fail.d

index 4ce11e3cada88e65d0130fdf9318a8d7bf248feb..d7f714760f7aafd4f43a9e0936da85e256ef0ac1 100644 (file)
@@ -89,6 +89,9 @@ D_FRONTEND_OBJS = \
        d/canthrow.o \
        d/chkformat.o \
        d/clone.o \
+       d/common-file.o \
+       d/common-outbuffer.o \
+       d/common-string.o \
        d/compiler.o \
        d/complex.o \
        d/cond.o \
@@ -120,6 +123,7 @@ D_FRONTEND_OBJS = \
        d/escape.o \
        d/expression.o \
        d/expressionsem.o \
+       d/file_manager.o \
        d/foreachvar.o \
        d/func.o \
        d/globals.o \
@@ -131,6 +135,7 @@ D_FRONTEND_OBJS = \
        d/identifier.o \
        d/impcnvtab.o \
        d/imphint.o \
+       d/importc.o \
        d/init.o \
        d/initsem.o \
        d/inline.o \
@@ -157,7 +162,6 @@ D_FRONTEND_OBJS = \
        d/root-filename.o \
        d/root-hash.o \
        d/root-longdouble.o \
-       d/root-outbuffer.o \
        d/root-port.o \
        d/root-region.o \
        d/root-rmem.o \
@@ -393,6 +397,10 @@ d/%.o: d/dmd/%.d
        $(DCOMPILE) $(D_INCLUDES) $<
        $(DPOSTCOMPILE)
 
+d/common-%.o: d/dmd/common/%.d
+       $(DCOMPILE) $(D_INCLUDES) $<
+       $(DPOSTCOMPILE)
+
 d/root-%.o: d/dmd/root/%.d
        $(DCOMPILE) $(D_INCLUDES) $<
        $(DPOSTCOMPILE)
index ab3a950689f960dfdd60b99a867504772eade3d2..ea8e1eda24419aef128456f4df6df8292ad1af92 100644 (file)
@@ -236,7 +236,7 @@ build_frontend_type (tree type)
       sdecl->parent = stubmod;
       sdecl->structsize = int_size_in_bytes (type);
       sdecl->alignsize = TYPE_ALIGN_UNIT (type);
-      sdecl->alignment = STRUCTALIGN_DEFAULT;
+      sdecl->alignment.setDefault ();
       sdecl->sizeok = Sizeok::done;
       sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
       sdecl->type->ctype = type;
@@ -275,7 +275,7 @@ build_frontend_type (tree type)
                                                       NULL);
          vd->parent = sdecl;
          vd->offset = tree_to_uhwi (byte_position (field));
-         vd->semanticRun = PASSsemanticdone;
+         vd->semanticRun = PASS::semanticdone;
          vd->csym = field;
          sdecl->members->push (vd);
          sdecl->fields.push (vd);
@@ -856,6 +856,9 @@ d_build_d_type_nodes (void)
   ireal_type_node = build_distinct_type_copy (long_double_type_node);
   TYPE_IMAGINARY_FLOAT (ireal_type_node) = 1;
 
+  /* Noreturn type.  */
+  noreturn_type_node = build_distinct_type_copy (void_type_node);
+
   /* Calling build_ctype() links the front-end Type to the GCC node,
      and sets the TYPE_NAME to the D language type.  */
   for (unsigned ty = 0; ty < (unsigned) TY::TMAX; ty++)
index 403e3c7437709f103a21bea2d8d4f61b4012849b..c082ac5ab80fd73da87ff3d468a5ac178e6cc000 100644 (file)
@@ -2140,6 +2140,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
   /* Build the argument list for the call.  */
   vec <tree, va_gc> *args = NULL;
   tree saved_args = NULL_TREE;
+  bool noreturn_call = false;
 
   /* If this is a delegate call or a nested function being called as
      a delegate, the object should not be NULL.  */
@@ -2165,9 +2166,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
            }
        }
 
-      size_t nparams = tf->parameterList.length ();
+      const size_t nparams = tf->parameterList.length ();
       /* if _arguments[] is the first argument.  */
-      size_t varargs = tf->isDstyleVariadic ();
+      const size_t varargs = tf->isDstyleVariadic ();
 
       /* Assumes arguments->length <= formal_args->length if (!tf->varargs).  */
       for (size_t i = 0; i < arguments->length; ++i)
@@ -2206,6 +2207,11 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
                              build_address (targ));
            }
 
+         /* Type `noreturn` is a terminator, as no other arguments can possibly
+            be evaluated after it.  */
+         if (TREE_TYPE (targ) == noreturn_type_node)
+           noreturn_call = true;
+
          vec_safe_push (args, targ);
        }
     }
@@ -2217,13 +2223,27 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
       saved_args = compound_expr (callee, saved_args);
     }
 
+  /* If we saw a `noreturn` parameter, any unreachable argument evaluations
+     after it are discarded, as well as the function call itself.  */
+  if (noreturn_call)
+    {
+      if (TREE_SIDE_EFFECTS (callee))
+       saved_args = compound_expr (callee, saved_args);
+
+      tree arg;
+      unsigned int ix;
+
+      FOR_EACH_VEC_SAFE_ELT (args, ix, arg)
+       saved_args = compound_expr (saved_args, arg);
+
+      /* Add a stub result type for the expression.  */
+      tree result = build_zero_cst (TREE_TYPE (ctype));
+      return compound_expr (saved_args, result);
+    }
+
   tree result = build_call_vec (TREE_TYPE (ctype), callee, args);
   SET_EXPR_LOCATION (result, input_location);
 
-  /* Enforce left to right evaluation.  */
-  if (tf->linkage == LINK::d)
-    CALL_EXPR_ARGS_ORDERED (result) = 1;
-
   result = maybe_expand_intrinsic (result);
 
   /* Return the value in a temporary slot so that it can be evaluated
@@ -2296,6 +2316,10 @@ build_vthis_function (tree basetype, tree type)
                             TYPE_ARG_TYPES (type));
   tree fntype = build_function_type (TREE_TYPE (type), argtypes);
 
+  /* Copy volatile qualifiers from the original function type.  */
+  if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE)
+    fntype = build_qualified_type (fntype, TYPE_QUAL_VOLATILE);
+
   if (RECORD_OR_UNION_TYPE_P (basetype))
     TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
   else
index 522095f12c56f478734883d86f7482ea3c8bc6f9..b2e52c0c5e7de04cc7dcea97401fab101574346b 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 
 #include "d-tree.h"
+#include "d-frontend.h"
 
 /* Implements back-end specific interfaces used by the frontend.  */
 
@@ -51,7 +52,7 @@ isBuiltin (FuncDeclaration *fd)
    Return result; NULL if cannot evaluate it.  */
 
 Expression *
-eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
+eval_builtin (const Loc &loc, FuncDeclaration *fd, Expressions *arguments)
 {
   if (fd->builtin == BUILTIN::unimp)
     return NULL;
@@ -78,10 +79,16 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
 /* Build and return typeinfo type for TYPE.  */
 
 Type *
-getTypeInfoType (Loc loc, Type *type, Scope *sc)
+getTypeInfoType (const Loc &loc, Type *type, Scope *sc)
 {
   gcc_assert (type->ty != TY::Terror);
   check_typeinfo_type (loc, sc);
   create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
   return type->vtinfo->type;
 }
+
+void
+toObjFile (Dsymbol *ds, bool)
+{
+  build_decl_tree (ds);
+}
index 0fa744247ffc4857bfaa309f0e7bf792be1bc38c..e3668815731326230030c0fe1358cbcaa52284db 100644 (file)
@@ -120,52 +120,47 @@ d_gimplify_addr_expr (tree *expr_p)
 static gimplify_status
 d_gimplify_call_expr (tree *expr_p, gimple_seq *pre_p)
 {
-  if (CALL_EXPR_ARGS_ORDERED (*expr_p))
-    {
-      /* Strictly evaluate all arguments from left to right.  */
-      int nargs = call_expr_nargs (*expr_p);
-      location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
+  /* Strictly evaluate all arguments from left to right.  */
+  int nargs = call_expr_nargs (*expr_p);
+  location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
 
-      /* No need to enforce evaluation order if only one argument.  */
-      if (nargs < 2)
-       return GS_UNHANDLED;
+  /* No need to enforce evaluation order if only one argument.  */
+  if (nargs < 2)
+    return GS_UNHANDLED;
 
-      /* Or if all arguments are already free of side-effects.  */
-      bool has_side_effects = false;
-      for (int i = 0; i < nargs; i++)
+  /* Or if all arguments are already free of side-effects.  */
+  bool has_side_effects = false;
+  for (int i = 0; i < nargs; i++)
+    {
+      if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
        {
-         if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
-           {
-             has_side_effects = true;
-             break;
-           }
+         has_side_effects = true;
+         break;
        }
+    }
 
-      if (!has_side_effects)
-       return GS_UNHANDLED;
-
-      /* Leave the last argument for gimplify_call_expr.  */
-      for (int i = 0; i < nargs - 1; i++)
-       {
-         tree new_arg = CALL_EXPR_ARG (*expr_p, i);
+  if (!has_side_effects)
+    return GS_UNHANDLED;
 
-         /* If argument has a side-effect, gimplify_arg will handle it.  */
-         if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
-           return GS_ERROR;
+  /* Leave the last argument for gimplify_call_expr.  */
+  for (int i = 0; i < nargs - 1; i++)
+    {
+      tree new_arg = CALL_EXPR_ARG (*expr_p, i);
 
-         /* Even if an argument itself doesn't have any side-effects, it
-            might be altered by another argument in the list.  */
-         if (new_arg == CALL_EXPR_ARG (*expr_p, i)
-             && !really_constant_p (new_arg))
-           new_arg = get_formal_tmp_var (new_arg, pre_p);
+      /* If argument has a side-effect, gimplify_arg will handle it.  */
+      if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
+       return GS_ERROR;
 
-         CALL_EXPR_ARG (*expr_p, i) = new_arg;
-       }
+      /* Even if an argument itself doesn't have any side-effects, it
+        might be altered by another argument in the list.  */
+      if (new_arg == CALL_EXPR_ARG (*expr_p, i)
+         && !really_constant_p (new_arg))
+       new_arg = get_formal_tmp_var (new_arg, pre_p);
 
-      return GS_OK;
+      CALL_EXPR_ARG (*expr_p, i) = new_arg;
     }
 
-  return GS_UNHANDLED;
+  return GS_OK;
 }
 
 /* Gimplify an UNSIGNED_RSHIFT_EXPR node.  */
index dbf7a8b60b9353421f746ea838a67ed7a727392f..576eefcc01f21ae2cbbe99d4795cb87cc442aa2d 100644 (file)
@@ -674,6 +674,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
     case OPT_ftransition_all:
       global.params.vfield = value;
       global.params.vgc = value;
+      global.params.vin = value;
       global.params.vmarkdown= value;
       global.params.vtls = value;
       break;
@@ -682,6 +683,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.vfield = value;
       break;
 
+    case OPT_ftransition_in:
+      global.params.vin = value;
+      break;
+
     case OPT_ftransition_nogc:
       global.params.vgc = value;
       break;
@@ -1176,6 +1181,14 @@ d_parse_file (void)
     {
       Module *m = modules[i];
 
+      /* If this is the `__main` module, check that `D main` hasn't already
+        been declared in user code before running semantic on it.  */
+      if (m == main_module && global.hasMainFunction)
+       {
+         modules.remove (i);
+         continue;
+       }
+
       if (global.params.verbose)
        message ("semantic  %s", m->toChars ());
 
@@ -1357,6 +1370,9 @@ d_parse_file (void)
   for (size_t i = 0; i < modules.length; i++)
     {
       Module *m = modules[i];
+
+      /* Skip generating code for header files, or when the module wasn't
+        specified by `-fonly=`.  */
       if ((m->isHdrFile && m != main_module)
          || (d_option.fonly && m != Module::rootModule))
        continue;
index 328b6b861d287c28814c07a9b0be4a4e2a6fe21f..a5970d8a2e3034e07c3626a818d0deeaccf4b49e 100644 (file)
@@ -47,7 +47,6 @@ typedef Array <Expression *> Expressions;
 
 /* Usage of TREE_LANG_FLAG_?:
    0: METHOD_CALL_EXPR
-   1: CALL_EXPR_ARGS_ORDERED (in CALL_EXPR).
 
    Usage of TYPE_LANG_FLAG_?:
    0: TYPE_SHARED
@@ -351,11 +350,6 @@ lang_tree_node
 #define METHOD_CALL_EXPR(NODE) \
   (TREE_LANG_FLAG_0 (NODE))
 
-/* True if all arguments in a call expression should be evaluated in the
-   order they are given (left to right).  */
-#define CALL_EXPR_ARGS_ORDERED(NODE) \
-  (TREE_LANG_FLAG_1 (CALL_EXPR_CHECK (NODE)))
-
 /* True if the type was declared 'shared'.  */
 #define TYPE_SHARED(NODE) \
   (TYPE_LANG_FLAG_0 (NODE))
@@ -430,6 +424,7 @@ enum d_tree_index
 
   DTI_ARRAY_TYPE,
   DTI_NULL_ARRAY,
+  DTI_BOTTOM_TYPE,
 
   DTI_MAX
 };
@@ -465,6 +460,8 @@ extern GTY(()) tree d_global_trees[DTI_MAX];
 #define array_type_node                        d_global_trees[DTI_ARRAY_TYPE]
 /* Null initializer for dynamic arrays.  */
 #define null_array_node                        d_global_trees[DTI_NULL_ARRAY]
+/* The bottom type, referred to as `noreturn` in code.  */
+#define noreturn_type_node             d_global_trees[DTI_BOTTOM_TYPE]
 
 /* A prefix for internal variables, which are not user-visible.  */
 #if !defined (NO_DOT_IN_LABEL)
index e28a581a7ec82786ef2e72c46a1688d1189a4021..a4976b68bf001b48135e2ec9868fd541f6a386b6 100644 (file)
@@ -116,59 +116,6 @@ gcc_attribute_p (Dsymbol *decl)
   return false;
 }
 
-/* Subroutine of pragma declaration visitor for marking the function in the
-   defined in SYM as a global constructor or destructor.  If ISCTOR is true,
-   then we're applying pragma(crt_constructor).  */
-
-static int
-apply_pragma_crt (Dsymbol *sym, bool isctor)
-{
-  AttribDeclaration *ad = sym->isAttribDeclaration ();
-  if (ad != NULL)
-    {
-      int nested = 0;
-
-      /* Walk all declarations of the attribute scope.  */
-      Dsymbols *ds = ad->include (NULL);
-      if (ds)
-       {
-         for (size_t i = 0; i < ds->length; i++)
-           nested += apply_pragma_crt ((*ds)[i], isctor);
-       }
-
-      return nested;
-    }
-
-  FuncDeclaration *fd = sym->isFuncDeclaration ();
-  if (fd != NULL)
-    {
-      tree decl = get_decl_tree (fd);
-
-      /* Apply flags to the function.  */
-      if (isctor)
-       {
-         DECL_STATIC_CONSTRUCTOR (decl) = 1;
-         decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY);
-       }
-      else
-       {
-         DECL_STATIC_DESTRUCTOR (decl) = 1;
-         decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
-       }
-
-      if (fd->linkage != LINK::c)
-       {
-         error_at (make_location_t (fd->loc),
-                   "must be %<extern(C)%> for %<pragma(%s)%>",
-                   isctor ? "crt_constructor" : "crt_destructor");
-       }
-
-      return 1;
-    }
-
-  return 0;
-}
-
 /* Implements the visitor interface to lower all Declaration AST classes
    emitted from the D Front-end to GCC trees.
    All visit methods accept one parameter D, which holds the frontend AST
@@ -210,18 +157,18 @@ public:
 
   void visit (Module *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     build_module_tree (d);
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Write the imported symbol to debug.  */
 
   void visit (Import *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     /* Implements import declarations by telling the debug back-end we are
@@ -266,7 +213,7 @@ public:
                                              false, false);
       }
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Expand any local variables found in tuples.  */
@@ -312,18 +259,6 @@ public:
                        "pragma(%s) not implemented", d->ident->toChars ());
          }
       }
-    else if (d->ident == Identifier::idPool ("crt_constructor")
-            || d->ident == Identifier::idPool ("crt_destructor"))
-      {
-       /* Handle pragma(crt_constructor) and pragma(crt_destructor).  Apply
-          flag to indicate that the functions enclosed should run automatically
-          at the beginning or end of execution.  */
-       bool isctor = (d->ident == Identifier::idPool ("crt_constructor"));
-
-       if (apply_pragma_crt (d, isctor) > 1)
-         error_at (make_location_t (d->loc),
-                   "can only apply to a single declaration");
-      }
 
     visit ((AttribDeclaration *) d);
   }
@@ -422,7 +357,7 @@ public:
 
   void visit (StructDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -470,7 +405,7 @@ public:
     if (d->xhash)
       this->build_dsymbol (d->xhash);
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Finish semantic analysis of functions in vtbl for class CD.  */
@@ -537,7 +472,7 @@ public:
 
   void visit (ClassDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -603,7 +538,7 @@ public:
     if (TYPE_NAME (ctype))
       d_pushdecl (TYPE_NAME (ctype));
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Write out compiler generated TypeInfo and vtables for the given interface
@@ -611,7 +546,7 @@ public:
 
   void visit (InterfaceDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -646,7 +581,7 @@ public:
     if (TYPE_NAME (ctype))
       d_pushdecl (TYPE_NAME (ctype));
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Write out compiler generated TypeInfo and initializer for the given
@@ -654,7 +589,7 @@ public:
 
   void visit (EnumDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (d->errors || d->type->ty == TY::Terror)
@@ -685,7 +620,7 @@ public:
     if (TYPE_NAME (ctype))
       d_pushdecl (TYPE_NAME (ctype));
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Finish up a variable declaration and push it into the current scope.
@@ -693,7 +628,7 @@ public:
 
   void visit (VarDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -703,6 +638,21 @@ public:
        return;
       }
 
+    /* Variables of type `noreturn` are just placeholders, and evaluate to
+       `assert(0)` if ever read.  */
+    if (d->type->isTypeNoreturn ())
+      {
+       if (!d->isDataseg () && !d->isMember ()
+           && d->_init && !d->_init->isVoidInitializer ())
+         {
+           Expression *e = d->type->defaultInitLiteral (d->loc);
+           tree exp = build_expr (e);
+           add_stmt (exp);
+         }
+
+       return;
+      }
+
     if (d->aliassym)
       {
        this->build_dsymbol (d->toAlias ());
@@ -762,7 +712,7 @@ public:
 
        /* Frontend should have already caught this.  */
        gcc_assert (!integer_zerop (size)
-                   || d->type->toBasetype ()->ty == TY::Tsarray);
+                   || d->type->toBasetype ()->isTypeSArray ());
 
        d_finish_decl (decl);
 
@@ -797,7 +747,7 @@ public:
          }
       }
 
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Generate and compile a static TypeInfo declaration, but only if it is
@@ -805,7 +755,7 @@ public:
 
   void visit (TypeInfoDeclaration *d)
   {
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     if (speculative_type_p (d->tinfo))
@@ -814,7 +764,7 @@ public:
     tree t = get_typeinfo_decl (d);
     DECL_INITIAL (t) = layout_typeinfo (d);
     d_finish_decl (t);
-    d->semanticRun = PASSobj;
+    d->semanticRun = PASS::obj;
   }
 
   /* Finish up a function declaration and compile it all the way
@@ -823,7 +773,7 @@ public:
   void visit (FuncDeclaration *d)
   {
     /* Already generated the function.  */
-    if (d->semanticRun >= PASSobj)
+    if (d->semanticRun >= PASS::obj)
       return;
 
     /* Don't emit any symbols from gcc.attribute module.  */
@@ -861,7 +811,7 @@ public:
       }
 
     /* Ensure all semantic passes have run.  */
-    if (d->semanticRun < PASSsemantic3)
+    if (d->semanticRun < PASS::semantic3)
       {
        d->functionSemantic3 ();
        Module::runDeferredSemantic3 ();
@@ -887,8 +837,8 @@ public:
       message ("function  %s", d->toPrettyChars ());
 
     /* Start generating code for this function.  */
-    gcc_assert (d->semanticRun == PASSsemantic3done);
-    d->semanticRun = PASSobj;
+    gcc_assert (d->semanticRun == PASS::semantic3done);
+    d->semanticRun = PASS::obj;
 
     tree old_context = start_function (d);
 
@@ -927,12 +877,19 @@ public:
       }
 
     /* formal function parameters.  */
-    size_t n_parameters = d->parameters ? d->parameters->length : 0;
+    const size_t n_parameters = d->parameters ? d->parameters->length : 0;
 
     for (size_t i = 0; i < n_parameters; i++)
       {
        VarDeclaration *param = (*d->parameters)[i];
+
        parm_decl = get_symbol_decl (param);
+
+       /* Type `noreturn` is a terminator, as no other arguments can possibly
+          be evaluated after it.  */
+       if (TREE_TYPE (parm_decl) == noreturn_type_node)
+         break;
+
        /* Chain them in the correct order.  */
        param_list = chainon (param_list, parm_decl);
       }
@@ -1136,9 +1093,9 @@ get_symbol_decl (Declaration *decl)
                               declaration_type (vd));
 
       /* If any alignment was set on the declaration.  */
-      if (vd->alignment != STRUCTALIGN_DEFAULT)
+      if (!vd->alignment.isDefault ())
        {
-         SET_DECL_ALIGN (decl->csym, vd->alignment * BITS_PER_UNIT);
+         SET_DECL_ALIGN (decl->csym, vd->alignment.get () * BITS_PER_UNIT);
          DECL_USER_ALIGN (decl->csym) = 1;
        }
 
@@ -1321,6 +1278,20 @@ get_symbol_decl (Declaration *decl)
       else if (fd->inlining == PINLINE::never)
        DECL_UNINLINABLE (decl->csym) = 1;
 
+      /* In [pragma/crtctor], Annotates a function so it is run after the C
+        runtime library is initialized and before the D runtime library is
+        initialized.  */
+      if (fd->isCrtCtorDtor == 1)
+       {
+         DECL_STATIC_CONSTRUCTOR (decl->csym) = 1;
+         decl_init_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
+       }
+      else if (fd->isCrtCtorDtor == 2)
+       {
+         DECL_STATIC_DESTRUCTOR (decl->csym) = 1;
+         decl_fini_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
+               }
+
       /* Function was declared `naked'.  */
       if (fd->naked)
        {
@@ -1342,7 +1313,7 @@ get_symbol_decl (Declaration *decl)
        DECL_FINAL_P (decl->csym) = 1;
 
       /* Function is of type `noreturn' or `typeof(*null)'.  */
-      if (fd->type->nextOf ()->ty == TY::Tnoreturn)
+      if (fd->type->nextOf ()->isTypeNoreturn ())
        TREE_THIS_VOLATILE (decl->csym) = 1;
 
       /* Check whether this function is expanded by the frontend.  */
@@ -2246,9 +2217,9 @@ aggregate_initializer_decl (AggregateDeclaration *decl)
   TREE_READONLY (sinit) = 1;
 
   /* Honor struct alignment set by user.  */
-  if (sd && sd->alignment != STRUCTALIGN_DEFAULT)
+  if (sd && !sd->alignment.isDefault ())
     {
-      SET_DECL_ALIGN (sinit, sd->alignment * BITS_PER_UNIT);
+      SET_DECL_ALIGN (sinit, sd->alignment.get () * BITS_PER_UNIT);
       DECL_USER_ALIGN (sinit) = true;
     }
 
index 129050b6780452076f4b338a8900e59e3ff1ef5b..d23e1fedba4821db9501d045e8d2af869ac6dc6b 100644 (file)
@@ -1,4 +1,4 @@
-b8384668f28741ad5884fc055a2bdb9c05fd95ec
+568496d5b6ed02d577dfa86f73c7bb4edee05813
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 720d25683af95343b219622671b4df77f8030281..3cb7e127bb6c00cbd126f57f4d257a580b84b451 100644 (file)
@@ -20,6 +20,7 @@ this license for that file.
 |--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 | [dmd/](https://github.com/dlang/dmd/tree/master/src/dmd)                 | The dmd driver and front-end                                                                                                                                                                                  |
 | [dmd/backend/](https://github.com/dlang/dmd/tree/master/src/dmd/backend) | Code generation for x86 or x86-64. Shared by the [Digital Mars C compiler](https://github.com/DigitalMars/Compiler/), but not [LDC](https://github.com/ldc-developers/ldc) or [GDC](https://gdcproject.org/). |
+| [dmd/common/](https://github.com/dlang/dmd/tree/master/src/dmd/common)   | Code shared by the front-end and back-end                                                                                                                                                                     |
 | [dmd/root/](https://github.com/dlang/dmd/tree/master/src/dmd/root)       | Meant as a portable utility library, but ["it wasn't very good and the only project left using it is dmd"](https://github.com/dlang/dmd/pull/9844#issuecomment-498479516).                                    |
 
 DMD has a mostly flat directory structure, so this section aims to divide all source files into logical groups for easier navigation.
@@ -126,6 +127,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
 | [optimize.d](https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d)     | Do constant folding more generally                                                         |
 | [dcast.d](https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d)           | Implicit or explicit cast(), finding common types e.g. in `x ? a : b`, integral promotions |
 | [impcnvtab.d](https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d)   | Define an implicit conversion table for basic types                                        |
+| [importc.d](https://github.com/dlang/dmd/blob/master/src/dmd/importc.d)       | Helpers specific to ImportC                                                                |
 | [sideeffect.d](https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d) | Extract side-effects of expressions for certain lowerings.                                 |
 
 **Compile Time Function Execution (CTFE)**
@@ -243,14 +245,14 @@ Note that these groups have no strict meaning, the category assignments are a bi
 
 Note: many other utilities are in [dmd/root](https://github.com/dlang/dmd/tree/master/src/dmd/root).
 
-| File                                                                        | Purpose                                           |
-|-----------------------------------------------------------------------------|---------------------------------------------------|
-| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d)             | Modify environment variables                      |
-| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d)     | Print error messages in color                     |
-| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d)             | Encoding/decoding Unicode text                    |
-| [filecache.d](https://github.com/dlang/dmd/blob/master/src/dmd/filecache.d) | Keep file contents in memory                      |
-| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d)         | Utility functions related to files and file paths |
-| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d)     | A complex number type                             |
+| File                                                                              | Purpose                                           |
+|-----------------------------------------------------------------------------------|---------------------------------------------------|
+| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d)                   | Modify environment variables                      |
+| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d)           | Print error messages in color                     |
+| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d)                   | Encoding/decoding Unicode text                    |
+| [file_manager.d](https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d) | Keep file contents in memory                      |
+| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d)               | Utility functions related to files and file paths |
+| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d)           | A complex number type                             |
 
 | File                                                                            | Purpose                                                       |
 |---------------------------------------------------------------------------------|---------------------------------------------------------------|
index 64ce79a7c451e51349b4a8b405cdeaff4047e5c8..fa5940ed249d59ddb7b55be9f7d4a381d5251a9c 100644 (file)
@@ -1 +1 @@
-v2.097.2
+v2.098.0
index cff4b9feb45f9c0cf1388d602baf1b641b987a76..1fe8e809aa552d36d12eca6751d7919574ddaaf2 100644 (file)
@@ -21,6 +21,7 @@ import dmd.aliasthis;
 import dmd.apply;
 import dmd.arraytypes;
 import dmd.astenums;
+import dmd.attrib;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dstruct;
@@ -115,11 +116,12 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
 
     AliasThis aliasthis;    /// forward unresolved lookups to aliasthis
 
-    DtorDeclarations dtors;     /// Array of destructors
-    DtorDeclaration dtor;       /// aggregate destructor calling dtors and member constructors
-    DtorDeclaration primaryDtor;/// non-deleting C++ destructor, same as dtor for D
+    DtorDeclarations userDtors; /// user-defined destructors (`~this()`) - mixins can yield multiple ones
+    DtorDeclaration aggrDtor;   /// aggregate destructor calling userDtors and fieldDtor (and base class aggregate dtor for C++ classes)
+    DtorDeclaration dtor;       /// the aggregate destructor exposed as `__xdtor` alias
+                                /// (same as aggrDtor, except for C++ classes with virtual dtor on Windows)
     DtorDeclaration tidtor;     /// aggregate destructor used in TypeInfo (must have extern(D) ABI)
-    FuncDeclaration fieldDtor;  /// aggregate destructor for just the fields
+    DtorDeclaration fieldDtor;  /// function destructing (non-inherited) fields
 
     Expression getRTInfo;   /// pointer to GC info generated by object.RTInfo(this)
 
@@ -177,7 +179,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      * Returns:
      *      false if failed to determine the size.
      */
-    final bool determineSize(Loc loc)
+    final bool determineSize(const ref Loc loc)
     {
         //printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok);
 
@@ -331,7 +333,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      *      false if any errors occur.
      *      Otherwise, returns true and the missing arguments will be pushed in elements[].
      */
-    final bool fill(Loc loc, Expressions* elements, bool ctorinit)
+    final bool fill(const ref Loc loc, Expressions* elements, bool ctorinit)
     {
         //printf("AggregateDeclaration::fill() %s\n", toChars());
         assert(sizeok == Sizeok.done);
@@ -482,45 +484,52 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      * Align sizes of 0, as we may not know array sizes yet.
      * Params:
      *   alignment = struct alignment that is in effect
-     *   size = alignment requirement of field
+     *   memalignsize = natural alignment of field
      *   poffset = pointer to offset to be aligned
      */
-    extern (D) static void alignmember(structalign_t alignment, uint size, uint* poffset) pure nothrow @safe
+    extern (D) static void alignmember(structalign_t alignment, uint memalignsize, uint* poffset) pure nothrow @safe
     {
-        //printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
-        switch (alignment)
-        {
-        case cast(structalign_t)1:
-            // No alignment
-            break;
+        //debug printf("alignment = %u %d, size = %u, offset = %u\n", alignment.get(), alignment.isPack(), memalignsize, *poffset);
+        uint alignvalue;
 
-        case cast(structalign_t)STRUCTALIGN_DEFAULT:
+        if (alignment.isDefault())
+        {
             // Alignment in Target::fieldalignsize must match what the
             // corresponding C compiler's default alignment behavior is.
-            assert(size > 0 && !(size & (size - 1)));
-            *poffset = (*poffset + size - 1) & ~(size - 1);
-            break;
-
-        default:
+            alignvalue = memalignsize;
+        }
+        else if (alignment.isPack())    // #pragma pack semantics
+        {
+            alignvalue = alignment.get();
+            if (memalignsize < alignvalue)
+                alignvalue = memalignsize;      // align to min(memalignsize, alignment)
+        }
+        else if (alignment.get() > 1)
+        {
             // Align on alignment boundary, which must be a positive power of 2
-            assert(alignment > 0 && !(alignment & (alignment - 1)));
-            *poffset = (*poffset + alignment - 1) & ~(alignment - 1);
-            break;
+            alignvalue = alignment.get();
         }
+        else
+            return;
+
+        assert(alignvalue > 0 && !(alignvalue & (alignvalue - 1)));
+        *poffset = (*poffset + alignvalue - 1) & ~(alignvalue - 1);
     }
 
     /****************************************
-     * Place a member (mem) into an aggregate (agg), which can be a struct, union or class
+     * Place a field (mem) into an aggregate (agg), which can be a struct, union or class
+     * Params:
+     *    nextoffset    = location just past the end of the previous field in the aggregate.
+     *                    Updated to be just past the end of this field to be placed, i.e. the future nextoffset
+     *    memsize       = size of field
+     *    memalignsize  = natural alignment of field
+     *    alignment     = alignment in effect for this field
+     *    paggsize      = size of aggregate (updated)
+     *    paggalignsize = alignment of aggregate (updated)
+     *    isunion       = the aggregate is a union
      * Returns:
-     *      offset to place field at
+     *    aligned offset to place field at
      *
-     * nextoffset:    next location in aggregate
-     * memsize:       size of member
-     * memalignsize:  natural alignment of member
-     * alignment:     alignment in effect for this member
-     * paggsize:      size of aggregate (updated)
-     * paggalignsize: alignment of aggregate (updated)
-     * isunion:       the aggregate is a union
      */
     extern (D) static uint placeField(uint* nextoffset, uint memsize, uint memalignsize,
         structalign_t alignment, uint* paggsize, uint* paggalignsize, bool isunion)
@@ -528,7 +537,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
         uint ofs = *nextoffset;
 
         const uint actualAlignment =
-            alignment == STRUCTALIGN_DEFAULT ? memalignsize : alignment;
+            alignment.isDefault() || alignment.isPack() && memalignsize < alignment.get()
+                        ? memalignsize : alignment.get();
 
         // Ensure no overflow
         bool overflow;
@@ -536,7 +546,10 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
         addu(ofs, sz, overflow);
         if (overflow) assert(0);
 
-        alignmember(alignment, memalignsize, &ofs);
+        // Skip no-op for noreturn without custom aligment
+        if (memsize != 0 || !alignment.isDefault())
+            alignmember(alignment, memalignsize, &ofs);
+
         uint memoffset = ofs;
         ofs += memsize;
         if (ofs > *paggsize)
index f8d2f45706ae5f066c097fe6e30c4f555cc8bdf2..48e5f4a806234fe19ba7ced1fd541c0f6a565c09 100644 (file)
@@ -105,11 +105,12 @@ public:
 
     AliasThis *aliasthis;       // forward unresolved lookups to aliasthis
 
-    DtorDeclarations dtors;     // Array of destructors
-    DtorDeclaration *dtor;      // aggregate destructor
-    DtorDeclaration *primaryDtor; // non-deleting C++ destructor, same as dtor for D
+    DtorDeclarations userDtors; // user-defined destructors (`~this()`) - mixins can yield multiple ones
+    DtorDeclaration *aggrDtor;  // aggregate destructor calling userDtors and fieldDtor (and base class aggregate dtor for C++ classes)
+    DtorDeclaration *dtor;      // the aggregate destructor exposed as `__xdtor` alias
+                                // (same as aggrDtor, except for C++ classes with virtual dtor on Windows)
     DtorDeclaration *tidtor;    // aggregate destructor used in TypeInfo (must have extern(D) ABI)
-    FuncDeclaration *fieldDtor;   // aggregate destructor for just the fields
+    DtorDeclaration *fieldDtor; // function destructing (non-inherited) fields
 
     Expression *getRTInfo;      // pointer to GC info generated by object.RTInfo(this)
 
@@ -121,10 +122,10 @@ public:
     virtual Scope *newScope(Scope *sc);
     void setScope(Scope *sc);
     size_t nonHiddenFields();
-    bool determineSize(Loc loc);
+    bool determineSize(const Loc &loc);
     virtual void finalizeSize() = 0;
     d_uns64 size(const Loc &loc);
-    bool fill(Loc loc, Expressions *elements, bool ctorinit);
+    bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
     Type *getType();
     bool isDeprecated() const;         // is aggregate deprecated?
     void setDeprecated();
@@ -184,7 +185,7 @@ public:
     // ABI-specific type(s) if the struct can be passed in registers
     TypeTuple *argTypes;
 
-    static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
+    static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
     StructDeclaration *syntaxCopy(Dsymbol *s);
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     const char *kind() const;
@@ -277,7 +278,7 @@ public:
     ObjcClassDeclaration objc;          // Data for a class declaration that is needed for the Objective-C integration
     Symbol *cpp_type_info_ptr_sym;      // cached instance of class Id.cpp_type_info_ptr
 
-    static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
+    static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
     const char *toPrettyChars(bool QualifyTypes = false);
     ClassDeclaration *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
index 81e0d7e64bead010f8505543d26c12046510cd86..e048cdc2e1b4a2896547585b993185b36d47054c 100644 (file)
@@ -72,17 +72,32 @@ extern (C++) final class AliasThis : Dsymbol
     }
 }
 
-Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false)
+/*************************************
+ * Find the `alias this` symbol of e's type.
+ * Params:
+ *      sc = context
+ *      e = expression forming the `this`
+ *      gag = if true do not print errors, return null instead
+ *      findOnly = don't do further processing like resolving properties,
+ *                 i.e. just return plain dotExp() result.
+ * Returns:
+ *      Expression that is `e.aliasthis`
+ */
+Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false)
 {
+    import dmd.typesem : dotExp;
     for (AggregateDeclaration ad = isAggregate(e.type); ad;)
     {
         if (ad.aliasthis)
         {
-            uint olderrors = gag ? global.startGagging() : 0;
             Loc loc = e.loc;
             Type tthis = (e.op == TOK.type ? e.type : null);
-            e = new DotIdExp(loc, e, ad.aliasthis.ident);
-            e = e.expressionSemantic(sc);
+            const flags = DotExpFlag.noAliasThis | (gag ? DotExpFlag.gag : 0);
+            uint olderrors = gag ? global.startGagging() : 0;
+            e = dotExp(e.type, sc, e, ad.aliasthis.ident, flags);
+            if (!e || findOnly)
+                return gag && global.endGagging(olderrors) ? null : e;
+
             if (tthis && ad.aliasthis.sym.needThis())
             {
                 if (e.op == TOK.variable)
index 66be73ea21fee3149dc073385d0bcd96a106aae4..e2b33194f060417a891e3fbe222f57382ff91208 100644 (file)
@@ -26,7 +26,7 @@ import dmd.globals;
 import dmd.id;
 import dmd.identifier;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.statement;
 import dmd.tokens;
 import dmd.visitor;
index ae8f65b6daa06c2caf3d3cfc6fa405c8d0c77f86..0bf40ef9a728d4cce3518269c3f58c49930a5ebc 100644 (file)
@@ -42,7 +42,7 @@ import dmd.id;
 import dmd.identifier;
 import dmd.mtype;
 import dmd.objc; // for objc.addSymbols
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.target; // for target.systemLinkage
 import dmd.tokens;
 import dmd.visitor;
@@ -696,12 +696,9 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
 {
     Expressions* exps;                              /// Expression(s) yielding the desired alignment,
                                                     /// the largest value wins
-    enum structalign_t UNKNOWN = 0;                 /// alignment not yet computed
-    static assert(STRUCTALIGN_DEFAULT != UNKNOWN);
-
-    /// the actual alignment, `UNKNOWN` until it's either set to the value of `ealign`
-    /// or `STRUCTALIGN_DEFAULT` if `ealign` is null ( / an error ocurred)
-    structalign_t salign = UNKNOWN;
+    /// the actual alignment is Unknown until it's either set to the value of `ealign`
+    /// or the default if `ealign` is null ( / an error ocurred)
+    structalign_t salign;
 
 
     extern (D) this(const ref Loc loc, Expression exp, Dsymbols* decl)
@@ -709,8 +706,7 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
         super(loc, null, decl);
         if (exp)
         {
-            if (!exps)
-                exps = new Expressions();
+            exps = new Expressions();
             exps.push(exp);
         }
     }
@@ -721,6 +717,12 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
         this.exps = exps;
     }
 
+    extern (D) this(const ref Loc loc, structalign_t salign, Dsymbols* decl)
+    {
+        super(loc, null, decl);
+        this.salign = salign;
+    }
+
     override AlignDeclaration syntaxCopy(Dsymbol s)
     {
         assert(!s);
@@ -1196,7 +1198,7 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
 
         // expand static foreach
         import dmd.statementsem: makeTupleForeach;
-        Dsymbols* d = makeTupleForeach!(true,true)(_scope, sfe.aggrfe, decl, sfe.needExpansion);
+        Dsymbols* d = makeTupleForeach!(true,true)(_scope, sfe.aggrfe, decl, sfe.needExpansion).decl;
         if (d) // process generated declarations
         {
             // Add members lazily.
index 1fd9005183010263b4ed697bd38bd9b110972a37..0ecd6351f7d6181aed48000c9d226c5ac2461024 100644 (file)
@@ -108,7 +108,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                         return;
                     }
                 }
-                if (s.exp.type.toBasetype().isTypeNoreturn())
+                if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
                     result = BE.halt;
                 if (canThrow(s.exp, func, mustNotThrow))
                     result |= BE.throw_;
@@ -146,7 +146,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                             else if (sd && (!sd.statement.hasCode() || sd.statement.isCaseStatement() || sd.statement.isErrorStatement()))
                             {
                             }
-                            else
+                            else if (!func.getModule().isCFile)
                             {
                                 const(char)* gototype = s.isCaseStatement() ? "case" : "default";
                                 s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
index b99f690e156d2a9c3041677d4bc0f515fab181f3..c4f84b129686ed0e2b81f24d9cc699beeba6d099 100644 (file)
@@ -30,4 +30,4 @@ public extern (C++) BUILTIN isBuiltin(FuncDeclaration fd);
  * Evaluate builtin function.
  * Return result; NULL if cannot evaluate it.
  */
-public extern (C++) Expression eval_builtin(Loc loc, FuncDeclaration fd, Expressions* arguments);
+public extern (C++) Expression eval_builtin(const ref Loc loc, FuncDeclaration fd, Expressions* arguments);
index 97adc5ad8ac49139b8e68b2f5553ce2874753f27..b168b4f7e0a3be86273be255428b6d81ad5f4f00 100644 (file)
@@ -690,8 +690,8 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
                 return error();
             while ('0' <= format[i] && format[i] <= '9')
             {
-               ++i;
-               if (i == length)
+                ++i;
+                if (i == length)
                     return error();
             }
         }
@@ -720,8 +720,8 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
                 return error();
             while ('0' <= format[i] && format[i] <= '9')
             {
-               ++i;
-               if (i == length)
+                ++i;
+                if (i == length)
                     return error();
             }
         }
index d3006170be76b0bcde2e68d0f6df5b87a6a89005..da66812b954843c622d4053f9879015a490101bb 100644 (file)
@@ -794,6 +794,19 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
     if (!needToHash(sd))
         return null;
 
+    /* The trouble is that the following code relies on .tupleof, but .tupleof
+     * is not allowed for C files. If we allow it for C files, then that turns on
+     * the other D properties, too, such as .dup which will then conflict with allowed
+     * field names.
+     * One way to fix it is to replace the following foreach and .tupleof with C
+     * statements and expressions.
+     * But, it's debatable whether C structs should even need toHash().
+     * Note that it would only be necessary if it has floating point fields.
+     * For now, we'll just not generate a toHash() for C files.
+     */
+    if (sc.flags & SCOPE.Cfile)
+        return null;
+
     //printf("StructDeclaration::buildXtoHash() %s\n", sd.toPrettyChars());
     Loc declLoc; // loc is unnecessary so __xtoHash is never called directly
     Loc loc; // internal code should have no loc to prevent coverage
@@ -831,31 +844,31 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
 }
 
 /*****************************************
- * Create inclusive destructor for struct/class by aggregating
- * all the destructors in dtors[] with the destructors for
+ * Create aggregate destructor for struct/class by aggregating
+ * all the destructors in userDtors[] with the destructors for
  * all the members.
+ * Sets ad's fieldDtor, aggrDtor, dtor and tidtor fields.
  * Params:
  *      ad = struct or class to build destructor for
  *      sc = context
- * Returns:
- *      generated function, null if none needed
  * Note:
  * Close similarity with StructDeclaration::buildPostBlit(),
  * and the ordering changes (runs backward instead of forwards).
  */
-DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
+void buildDtors(AggregateDeclaration ad, Scope* sc)
 {
     //printf("AggregateDeclaration::buildDtor() %s\n", ad.toChars());
     if (ad.isUnionDeclaration())
-        return null;                    // unions don't have destructors
+        return;                    // unions don't have destructors
 
     StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
-    Loc declLoc = ad.dtors.dim ? ad.dtors[0].loc : ad.loc;
+    Loc declLoc = ad.userDtors.dim ? ad.userDtors[0].loc : ad.loc;
     Loc loc; // internal code should have no loc to prevent coverage
     FuncDeclaration xdtor_fwd = null;
 
-    // if the dtor is an extern(C++) prototype, then we expect it performs a full-destruction; we don't need to build a full-dtor
-    const bool dtorIsCppPrototype = ad.dtors.dim == 1 && ad.dtors[0].linkage == LINK.cpp && !ad.dtors[0].fbody;
+    // Build the field destructor (`ad.fieldDtor`), if needed.
+    // If the user dtor is an extern(C++) prototype, then we expect it performs a full-destruction and skip building.
+    const bool dtorIsCppPrototype = ad.userDtors.dim && ad.userDtors[0].linkage == LINK.cpp && !ad.userDtors[0].fbody;
     if (!dtorIsCppPrototype)
     {
         Expression e = null;
@@ -936,36 +949,6 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
             e = Expression.combine(ex, e); // combine in reverse order
         }
 
-        /* extern(C++) destructors call into super to destruct the full hierarchy
-        */
-        ClassDeclaration cldec = ad.isClassDeclaration();
-        if (cldec && cldec.classKind == ClassKind.cpp && cldec.baseClass && cldec.baseClass.primaryDtor)
-        {
-            // WAIT BUT: do I need to run `cldec.baseClass.dtor` semantic? would it have been run before?
-            cldec.baseClass.dtor.functionSemantic();
-
-            stc = mergeFuncAttrs(stc, cldec.baseClass.primaryDtor);
-            if (!(stc & STC.disable))
-            {
-                // super.__xdtor()
-
-                Expression ex = new SuperExp(loc);
-
-                // This is a hack so we can call destructors on const/immutable objects.
-                // Do it as a type 'paint'.
-                ex = new CastExp(loc, ex, cldec.baseClass.type.mutableOf());
-                if (stc & STC.safe)
-                    stc = (stc & ~STC.safe) | STC.trusted;
-
-                ex = new DotVarExp(loc, ex, cldec.baseClass.primaryDtor, false);
-                ex = new CallExp(loc, ex);
-
-                e = Expression.combine(e, ex); // super dtor last
-            }
-        }
-
-        /* Build our own "destructor" which executes e
-         */
         if (e || (stc & STC.disable))
         {
             //printf("Building __fieldDtor(), %s\n", e.toChars());
@@ -973,29 +956,45 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
             dd.generated = true;
             dd.storage_class |= STC.inference;
             dd.fbody = new ExpStatement(loc, e);
-            ad.dtors.shift(dd);
             ad.members.push(dd);
             dd.dsymbolSemantic(sc);
             ad.fieldDtor = dd;
         }
     }
 
-    DtorDeclaration xdtor = null;
-    switch (ad.dtors.dim)
+    // Generate list of dtors to call in that order
+    DtorDeclarations dtors;
+    foreach_reverse (userDtor; ad.userDtors[])
+        dtors.push(userDtor);
+    if (ad.fieldDtor)
+        dtors.push(ad.fieldDtor);
+    if (!dtorIsCppPrototype)
+    {
+        // extern(C++) destructors call into super to destruct the full hierarchy
+        ClassDeclaration cldec = ad.isClassDeclaration();
+        if (cldec && cldec.classKind == ClassKind.cpp && cldec.baseClass && cldec.baseClass.aggrDtor)
+            dtors.push(cldec.baseClass.aggrDtor);
+    }
+
+    // Set/build `ad.aggrDtor`
+    switch (dtors.dim)
     {
     case 0:
         break;
 
     case 1:
-        xdtor = ad.dtors[0];
+        // Use the single existing dtor directly as aggregate dtor.
+        // Note that this might be `cldec.baseClass.aggrDtor`.
+        ad.aggrDtor = dtors[0];
         break;
 
     default:
+        // Build the aggregate destructor, calling all dtors in order.
         assert(!dtorIsCppPrototype);
         Expression e = null;
         e = null;
         stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
-        foreach (FuncDeclaration fd; ad.dtors)
+        foreach (FuncDeclaration fd; dtors)
         {
             stc = mergeFuncAttrs(stc, fd);
             if (stc & STC.disable)
@@ -1005,8 +1004,9 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
             }
             Expression ex = new ThisExp(loc);
             ex = new DotVarExp(loc, ex, fd, false);
-            ex = new CallExp(loc, ex);
-            e = Expression.combine(ex, e);
+            CallExp ce = new CallExp(loc, ex);
+            ce.directcall = true;
+            e = Expression.combine(e, ce);
         }
         auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__aggrDtor);
         dd.generated = true;
@@ -1014,19 +1014,20 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
         dd.fbody = new ExpStatement(loc, e);
         ad.members.push(dd);
         dd.dsymbolSemantic(sc);
-        xdtor = dd;
+        ad.aggrDtor = dd;
         break;
     }
 
-    ad.primaryDtor = xdtor;
-
-    if (xdtor && xdtor.linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
-        xdtor = buildWindowsCppDtor(ad, xdtor, sc);
+    // Set/build `ad.dtor`.
+    // On Windows, the dtor in the vtable is a shim with different signature.
+    ad.dtor = (ad.aggrDtor && ad.aggrDtor.linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
+        ? buildWindowsCppDtor(ad, ad.aggrDtor, sc)
+        : ad.aggrDtor;
 
-    // Add an __xdtor alias to make the inclusive dtor accessible
-    if (xdtor)
+    // Add an __xdtor alias to make `ad.dtor` accessible
+    if (ad.dtor)
     {
-        auto _alias = new AliasDeclaration(Loc.initial, Id.__xdtor, xdtor);
+        auto _alias = new AliasDeclaration(Loc.initial, Id.__xdtor, ad.dtor);
         _alias.dsymbolSemantic(sc);
         ad.members.push(_alias);
         if (xdtor_fwd)
@@ -1035,7 +1036,8 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
             _alias.addMember(sc, ad); // add to symbol table
     }
 
-    return xdtor;
+    // Set/build `ad.tidtor`
+    ad.tidtor = buildExternDDtor(ad, sc);
 }
 
 /**
@@ -1069,17 +1071,16 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
     auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, dtor.storage_class);
     auto func = new DtorDeclaration(dtor.loc, dtor.loc, dtor.storage_class, Id.cppdtor);
     func.type = ftype;
-    if (dtor.fbody)
-    {
-        const loc = dtor.loc;
-        auto stmts = new Statements;
-        auto call = new CallExp(loc, dtor, null);
-        call.directcall = true;
-        stmts.push(new ExpStatement(loc, call));
-        stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
-        func.fbody = new CompoundStatement(loc, stmts);
-        func.generated = true;
-    }
+
+    // Always generate the function with body, because it is not exported from DLLs.
+    const loc = dtor.loc;
+    auto stmts = new Statements;
+    auto call = new CallExp(loc, dtor, null);
+    call.directcall = true;
+    stmts.push(new ExpStatement(loc, call));
+    stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
+    func.fbody = new CompoundStatement(loc, stmts);
+    func.generated = true;
 
     auto sc2 = sc.push();
     sc2.stc &= ~STC.static_; // not a static destructor
@@ -1094,7 +1095,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
 }
 
 /**
- * build a shim function around the compound dtor that translates
+ * build a shim function around the aggregate dtor that translates
  *  a C++ destructor to a destructor with extern(D) calling convention
  *
  * Params:
@@ -1104,9 +1105,9 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
  * Returns:
  *  the shim destructor, semantically analyzed and added to the class as a member
  */
-DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
+private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
 {
-    auto dtor = ad.primaryDtor;
+    auto dtor = ad.aggrDtor;
     if (!dtor)
         return null;
 
diff --git a/gcc/d/dmd/common/README.md b/gcc/d/dmd/common/README.md
new file mode 100644 (file)
index 0000000..a9b65c3
--- /dev/null
@@ -0,0 +1,7 @@
+# Table of contents
+
+| File                                                                               | Purpose                                                         |
+|------------------------------------------------------------------------------------|-----------------------------------------------------------------|
+| [file.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d)           | Functions and objects dedicated to file I/O and management      |
+| [outbuffer.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data |
+| [string.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d)       | Common string functions including filename manipulation         |
diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d
new file mode 100644 (file)
index 0000000..b8cde37
--- /dev/null
@@ -0,0 +1,576 @@
+/**
+ * File utilities.
+ *
+ * Functions and objects dedicated to file I/O and management. TODO: Move here artifacts
+ * from places such as root/ so both the frontend and the backend have access to them.
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * Authors:   Walter Bright, http://www.digitalmars.com
+ * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d, common/_file.d)
+ * Documentation: https://dlang.org/phobos/dmd_common_file.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/file.d
+ */
+
+module dmd.common.file;
+
+import core.stdc.errno : errno;
+import core.stdc.stdio : fprintf, remove, rename, stderr;
+import core.stdc.stdlib : exit;
+import core.stdc.string : strerror;
+import core.sys.windows.winbase;
+import core.sys.windows.winnt;
+import core.sys.posix.fcntl;
+import core.sys.posix.unistd;
+
+import dmd.common.string;
+
+/**
+Encapsulated management of a memory-mapped file.
+
+Params:
+Datum = the mapped data type: Use a POD of size 1 for read/write mapping
+and a `const` version thereof for read-only mapping. Other primitive types
+should work, but have not been yet tested.
+*/
+struct FileMapping(Datum)
+{
+    static assert(__traits(isPOD, Datum) && Datum.sizeof == 1,
+        "Not tested with other data types yet. Add new types with care.");
+
+    version(Posix) enum invalidHandle = -1;
+    else version(Windows) enum invalidHandle = INVALID_HANDLE_VALUE;
+
+    // state {
+    /// Handle of underlying file
+    private auto handle = invalidHandle;
+    /// File mapping object needed on Windows
+    version(Windows) private HANDLE fileMappingObject = invalidHandle;
+    /// Memory-mapped array
+    private Datum[] data;
+    /// Name of underlying file, zero-terminated
+    private const(char)* name;
+    // state }
+
+    /**
+    Open `filename` and map it in memory. If `Datum` is `const`, opens for
+    read-only and maps the content in memory; no error is issued if the file
+    does not exist. This makes it easy to treat a non-existing file as empty.
+
+    If `Datum` is mutable, opens for read/write (creates file if it does not
+    exist) and fails fatally on any error.
+
+    Due to quirks in `mmap`, if the file is empty, `handle` is valid but `data`
+    is `null`. This state is valid and accounted for.
+
+    Params:
+    filename = the name of the file to be mapped in memory
+    */
+    this(const char* filename)
+    {
+        version (Posix)
+        {
+            import core.sys.posix.sys.mman;
+            import core.sys.posix.fcntl : open, O_CREAT, O_RDONLY, O_RDWR, S_IRGRP, S_IROTH, S_IRUSR, S_IWUSR;
+
+            handle = open(filename, is(Datum == const) ? O_RDONLY : (O_CREAT | O_RDWR),
+                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+            if (handle == invalidHandle)
+            {
+                static if (is(Datum == const))
+                {
+                    // No error, nonexisting file in read mode behaves like an empty file.
+                    return;
+                }
+                else
+                {
+                    fprintf(stderr, "open(\"%s\") failed: %s\n", filename, strerror(errno));
+                    exit(1);
+                }
+            }
+
+            const size = fileSize(handle);
+
+            if (size > 0 && size != ulong.max && size <= size_t.max)
+            {
+                auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : PROT_WRITE, MAP_SHARED, handle, 0);
+                if (p == MAP_FAILED)
+                {
+                    fprintf(stderr, "mmap(null, %zu) for \"%s\" failed: %s\n", cast(size_t) size, filename, strerror(errno));
+                    exit(1);
+                }
+                // The cast below will always work because it's gated by the `size <= size_t.max` condition.
+                data = cast(Datum[]) p[0 .. cast(size_t) size];
+            }
+        }
+        else version(Windows)
+        {
+            static if (is(Datum == const))
+            {
+                enum createFileMode = GENERIC_READ;
+                enum openFlags = OPEN_EXISTING;
+            }
+            else
+            {
+                enum createFileMode = GENERIC_READ | GENERIC_WRITE;
+                enum openFlags = CREATE_ALWAYS;
+            }
+
+            handle = filename.asDString.extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null));
+            if (handle == invalidHandle)
+            {
+                static if (is(Datum == const))
+                {
+                    return;
+                }
+                else
+                {
+                    fprintf(stderr, "CreateFileW() failed for \"%s\": %d\n", filename, GetLastError());
+                    exit(1);
+                }
+            }
+            createMapping(filename, fileSize(handle));
+        }
+        else static assert(0);
+
+        // Save the name for later. Technically there's no need: on Linux one can use readlink on /proc/self/fd/NNN.
+        // On BSD and OSX one can use fcntl with F_GETPATH. On Windows one can use GetFileInformationByHandleEx.
+        // But just saving the name is simplest, fastest, and most portable...
+        import core.stdc.string : strlen;
+        import core.stdc.stdlib : malloc;
+        import core.stdc.string : memcpy;
+        auto totalNameLength = filename.strlen() + 1;
+        name = cast(char*) memcpy(malloc(totalNameLength), filename, totalNameLength);
+        name || assert(0, "FileMapping: Out of memory.");
+    }
+
+    /**
+    Common code factored opportunistically. Windows only. Assumes `handle` is
+    already pointing to an opened file. Initializes the `fileMappingObject`
+    and `data` members.
+
+    Params:
+    filename = the file to be mapped
+    size = the size of the file in bytes
+    */
+    version(Windows) private void createMapping(const char* filename, ulong size)
+    {
+        assert(size <= size_t.max || size == ulong.max);
+        assert(handle != invalidHandle);
+        assert(data is null);
+        assert(fileMappingObject == invalidHandle);
+
+        if (size == 0 || size == ulong.max)
+            return;
+
+        static if (is(Datum == const))
+        {
+            enum fileMappingFlags = PAGE_READONLY;
+            enum mapViewFlags = FILE_MAP_READ;
+        }
+        else
+        {
+            enum fileMappingFlags = PAGE_READWRITE;
+            enum mapViewFlags = FILE_MAP_WRITE;
+        }
+
+        fileMappingObject = CreateFileMappingW(handle, null, fileMappingFlags, 0, 0, null);
+        if (!fileMappingObject)
+        {
+            fprintf(stderr, "CreateFileMappingW(%p) failed for %llu bytes of \"%s\": %d\n",
+                handle, size, filename, GetLastError());
+            fileMappingObject = invalidHandle;  // by convention always use invalidHandle, not null
+            exit(1);
+        }
+        auto p = MapViewOfFile(fileMappingObject, mapViewFlags, 0, 0, 0);
+        if (!p)
+        {
+            fprintf(stderr, "MapViewOfFile() failed for \"%s\": %d\n", filename, GetLastError());
+            exit(1);
+        }
+        data = cast(Datum[]) p[0 .. cast(size_t) size];
+    }
+
+    // Not copyable or assignable (for now).
+    @disable this(const FileMapping!Datum rhs);
+    @disable void opAssign(const ref FileMapping!Datum rhs);
+
+    /**
+    Frees resources associated with this mapping. However, it does not deallocate the name.
+    */
+    ~this() pure nothrow
+    {
+        if (!active)
+            return;
+        fakePure({
+            version (Posix)
+            {
+                import core.sys.posix.sys.mman : munmap;
+                import core.sys.posix.unistd : close;
+
+                // Cannot call fprintf from inside a destructor, so exiting silently.
+
+                if (data.ptr && munmap(cast(void*) data.ptr, data.length) != 0)
+                {
+                    exit(1);
+                }
+                data = null;
+                if (handle != invalidHandle && close(handle) != 0)
+                {
+                    exit(1);
+                }
+                handle = invalidHandle;
+            }
+            else version(Windows)
+            {
+                if (data.ptr !is null && UnmapViewOfFile(cast(void*) data.ptr) == 0)
+                {
+                    exit(1);
+                }
+                data = null;
+                if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
+                {
+                    exit(1);
+                }
+                fileMappingObject = invalidHandle;
+                if (handle != invalidHandle && CloseHandle(handle) == 0)
+                {
+                    exit(1);
+                }
+                handle = invalidHandle;
+            }
+            else static assert(0);
+        });
+    }
+
+    /**
+    Returns the zero-terminated file name associated with the mapping. Can NOT
+    be saved beyond the lifetime of `this`.
+    */
+    private const(char)* filename() const pure @nogc @safe nothrow { return name; }
+
+    /**
+    Frees resources associated with this mapping. However, it does not deallocate the name.
+    Reinitializes `this` as a fresh object that can be reused.
+    */
+    void close()
+    {
+        __dtor();
+        handle = invalidHandle;
+        version(Windows) fileMappingObject = invalidHandle;
+        data = null;
+        name = null;
+    }
+
+    /**
+    Deletes the underlying file and frees all resources associated.
+    Reinitializes `this` as a fresh object that can be reused.
+
+    This function does not abort if the file cannot be deleted, but does print
+    a message on `stderr` and returns `false` to the caller. The underlying
+    rationale is to give the caller the option to continue execution if
+    deleting the file is not important.
+
+    Returns: `true` iff the file was successfully deleted. If the file was not
+    deleted, prints a message to `stderr` and returns `false`.
+    */
+    static if (!is(Datum == const))
+    bool discard()
+    {
+        // Truncate file to zero so unflushed buffers are not flushed unnecessarily.
+        resize(0);
+        auto deleteme = name;
+        close();
+        // In-memory resource freed, now get rid of the underlying temp file.
+        version(Posix)
+        {
+            import core.sys.posix.unistd : unlink;
+            if (unlink(deleteme) != 0)
+            {
+                fprintf(stderr, "unlink(\"%s\") failed: %s\n", filename, strerror(errno));
+                return false;
+            }
+        }
+        else version(Windows)
+        {
+            import core.sys.windows.winbase;
+            if (deleteme.asDString.extendedPathThen!(p => DeleteFileW(p.ptr)) == 0)
+            {
+                fprintf(stderr, "DeleteFileW error %d\n", GetLastError());
+                return false;
+            }
+        }
+        else static assert(0);
+        return true;
+    }
+
+    /**
+    Queries whether `this` is currently associated with a file.
+
+    Returns: `true` iff there is an active mapping.
+    */
+    bool active() const pure @nogc nothrow
+    {
+        return handle !is invalidHandle;
+    }
+
+    /**
+    Queries the length of the file associated with this mapping.  If not
+    active, returns 0.
+
+    Returns: the length of the file, or 0 if no file associated.
+    */
+    size_t length() const pure @nogc @safe nothrow { return data.length; }
+
+    /**
+    Get a slice to the contents of the entire file.
+
+    Returns: the contents of the file. If not active, returns the `null` slice.
+    */
+    auto opSlice() pure @nogc @safe nothrow { return data; }
+
+    /**
+    Resizes the file and mapping to the specified `size`.
+
+    Params:
+    size = new length requested
+    */
+    static if (!is(Datum == const))
+    void resize(size_t size) pure
+    {
+        assert(handle != invalidHandle);
+        fakePure({
+            version(Posix)
+            {
+                import core.sys.posix.unistd : ftruncate;
+                import core.sys.posix.sys.mman;
+
+                if (data.length)
+                {
+                    assert(data.ptr, "Corrupt memory mapping");
+                    // assert(0) here because it would indicate an internal error
+                    munmap(cast(void*) data.ptr, data.length) == 0 || assert(0);
+                    data = null;
+                }
+                if (ftruncate(handle, size) != 0)
+                {
+                    fprintf(stderr, "ftruncate() failed for \"%s\": %s\n", filename, strerror(errno));
+                    exit(1);
+                }
+                if (size > 0)
+                {
+                    auto p = mmap(null, size, PROT_WRITE, MAP_SHARED, handle, 0);
+                    if (cast(ssize_t) p == -1)
+                    {
+                        fprintf(stderr, "mmap() failed for \"%s\": %s\n", filename, strerror(errno));
+                        exit(1);
+                    }
+                    data = cast(Datum[]) p[0 .. size];
+                }
+            }
+            else version(Windows)
+            {
+                // Per documentation, must unmap first.
+                if (data.length > 0 && UnmapViewOfFile(cast(void*) data.ptr) == 0)
+                {
+                    fprintf(stderr, "UnmapViewOfFile(%p) failed for memory mapping of \"%s\": %d\n",
+                        data.ptr, filename, GetLastError());
+                    exit(1);
+                }
+                data = null;
+                if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
+                {
+                    fprintf(stderr, "CloseHandle() failed for memory mapping of \"%s\": %d\n", filename, GetLastError());
+                    exit(1);
+                }
+                fileMappingObject = invalidHandle;
+                LARGE_INTEGER biggie;
+                biggie.QuadPart = size;
+                if (SetFilePointerEx(handle, biggie, null, FILE_BEGIN) == 0 || SetEndOfFile(handle) == 0)
+                {
+                    fprintf(stderr, "SetFilePointer() failed for \"%s\": %d\n", filename, GetLastError());
+                    exit(1);
+                }
+                createMapping(name, size);
+            }
+            else static assert(0);
+        });
+    }
+
+    /**
+    Unconditionally and destructively moves the underlying file to `filename`.
+    If the operation succeeds, returns true. Upon failure, prints a message to
+    `stderr` and returns `false`. In all cases it closes the underlying file.
+
+    Params: filename = zero-terminated name of the file to move to.
+
+    Returns: `true` iff the operation was successful.
+    */
+    bool moveToFile(const char* filename)
+    {
+        assert(name !is null);
+
+        // Fetch the name and then set it to `null` so it doesn't get deallocated
+        auto oldname = name;
+        import core.stdc.stdlib;
+        scope(exit) free(cast(void*) oldname);
+        name = null;
+        close();
+
+        // Rename the underlying file to the target, no copy necessary.
+        version(Posix)
+        {
+            if (.rename(oldname, filename) != 0)
+            {
+                fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", oldname, filename, strerror(errno));
+                return false;
+            }
+        }
+        else version(Windows)
+        {
+            import core.sys.windows.winbase;
+            auto r = oldname.asDString.extendedPathThen!(
+                p1 => filename.asDString.extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING))
+            );
+            if (r == 0)
+            {
+                fprintf(stderr, "MoveFileExW(\"%s\", \"%s\") failed: %d\n", oldname, filename, GetLastError());
+                return false;
+            }
+        }
+        else static assert(0);
+        return true;
+    }
+}
+
+/// Write a file, returning `true` on success.
+extern(D) static bool writeFile(const(char)* name, const void[] data) nothrow
+{
+    version (Posix)
+    {
+        int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
+        if (fd == -1)
+            goto err;
+        if (.write(fd, data.ptr, data.length) != data.length)
+            goto err2;
+        if (close(fd) == -1)
+            goto err;
+        return true;
+    err2:
+        close(fd);
+        .remove(name);
+    err:
+        return false;
+    }
+    else version (Windows)
+    {
+        DWORD numwritten; // here because of the gotos
+        const nameStr = name.asDString;
+        // work around Windows file path length limitation
+        // (see documentation for extendedPathThen).
+        HANDLE h = nameStr.extendedPathThen!
+            (p => CreateFileW(p.ptr,
+                                GENERIC_WRITE,
+                                0,
+                                null,
+                                CREATE_ALWAYS,
+                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                null));
+        if (h == INVALID_HANDLE_VALUE)
+            goto err;
+
+        if (WriteFile(h, data.ptr, cast(DWORD)data.length, &numwritten, null) != TRUE)
+            goto err2;
+        if (numwritten != data.length)
+            goto err2;
+        if (!CloseHandle(h))
+            goto err;
+        return true;
+    err2:
+        CloseHandle(h);
+        nameStr.extendedPathThen!(p => DeleteFileW(p.ptr));
+    err:
+        return false;
+    }
+    else
+    {
+        static assert(0);
+    }
+}
+
+/// Touch a file to current date
+bool touchFile(const char* namez)
+{
+    version (Windows)
+    {
+        FILETIME ft = void;
+        SYSTEMTIME st = void;
+        GetSystemTime(&st);
+        SystemTimeToFileTime(&st, &ft);
+
+        import core.stdc.string : strlen;
+
+        // get handle to file
+        HANDLE h = namez[0 .. namez.strlen()].extendedPathThen!(p => CreateFile(p.ptr,
+            FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
+            null, OPEN_EXISTING,
+            FILE_ATTRIBUTE_NORMAL, null));
+        if (h == INVALID_HANDLE_VALUE)
+            return false;
+
+        const f = SetFileTime(h, null, null, &ft); // set last write time
+
+        if (!CloseHandle(h))
+            return false;
+
+        return f != 0;
+    }
+    else version (Posix)
+    {
+        import core.sys.posix.utime;
+        return utime(namez, null) == 0;
+    }
+    else
+        static assert(0);
+}
+
+// Feel free to make these public if used elsewhere.
+/**
+Size of a file in bytes.
+Params: fd = file handle
+Returns: file size in bytes, or `ulong.max` on any error.
+*/
+version (Posix)
+private ulong fileSize(int fd)
+{
+    import core.sys.posix.sys.stat;
+    stat_t buf;
+    if (fstat(fd, &buf) == 0)
+        return buf.st_size;
+    return ulong.max;
+}
+
+/// Ditto
+version (Windows)
+private ulong fileSize(HANDLE fd)
+{
+    ulong result;
+    if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
+        return result;
+    return ulong.max;
+}
+
+/**
+Runs a non-pure function or delegate as pure code. Use with caution.
+
+Params:
+fun = the delegate to run, usually inlined: `fakePure({ ... });`
+
+Returns: whatever `fun` returns.
+*/
+private auto ref fakePure(F)(scope F fun) pure
+{
+    mixin("alias PureFun = " ~ F.stringof ~ " pure;");
+    return (cast(PureFun) fun)();
+}
similarity index 77%
rename from gcc/d/dmd/root/outbuffer.d
rename to gcc/d/dmd/common/outbuffer.d
index e756917b88da81da8b02220bafb331cf079655ac..c5a84375aaaa9356a25d445b9d3f82698e68b1bf 100644 (file)
@@ -9,14 +9,21 @@
  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/outbuffer.d
  */
 
-module dmd.root.outbuffer;
+module dmd.common.outbuffer;
 
 import core.stdc.stdarg;
 import core.stdc.stdio;
 import core.stdc.string;
-import dmd.root.rmem;
-import dmd.root.rootobject;
-import dmd.root.string;
+import core.stdc.stdlib;
+
+// In theory these functions should also restore errno, but we don't care because
+// we abort application on error anyway.
+extern (C) private pure @system @nogc nothrow
+{
+    pragma(mangle, "malloc") void* pureMalloc(size_t);
+    pragma(mangle, "realloc") void* pureRealloc(void* ptr, size_t size);
+    pragma(mangle, "free") void pureFree(void* ptr);
+}
 
 debug
 {
@@ -29,7 +36,7 @@ a contiguous array or a memory-mapped file.
 */
 struct OutBuffer
 {
-    import dmd.root.file : FileMapping;
+    import dmd.common.file : FileMapping, touchFile, writeFile;
 
     // IMPORTANT: PLEASE KEEP STATE AND DESTRUCTOR IN SYNC WITH DEFINITION IN ./outbuffer.h.
     // state {
@@ -47,6 +54,14 @@ struct OutBuffer
     int level;
     // state }
 
+    /**
+    Construct given size.
+    */
+    this(size_t initialSize) nothrow
+    {
+        reserve(initialSize);
+    }
+
     /**
     Construct from filename. Will map the file into memory (or create it anew
     if necessary) and start writing at the beginning of it.
@@ -56,14 +71,36 @@ struct OutBuffer
     */
     @trusted this(const(char)* filename)
     {
-        fileMapping = new FileMapping!ubyte(filename);
+        FileMapping!ubyte model;
+        fileMapping = cast(FileMapping!ubyte*) malloc(model.sizeof);
+        memcpy(fileMapping, &model, model.sizeof);
+        fileMapping.__ctor(filename);
+        //fileMapping = new FileMapping!ubyte(filename);
         data = (*fileMapping)[];
     }
 
+    /**
+    Frees resources associated.
+    */
+    extern (C++) void dtor() nothrow @trusted
+    {
+        if (fileMapping)
+        {
+            if (fileMapping.active)
+                fileMapping.close();
+            fileMapping = null;
+        }
+        else
+        {
+            debug (stomp) memset(data.ptr, 0xFF, data.length);
+            free(data.ptr);
+        }
+    }
+
     /**
     Frees resources associated automatically.
     */
-    extern (C++) ~this() pure nothrow
+    extern (C++) ~this() pure nothrow @trusted
     {
         if (fileMapping)
         {
@@ -74,10 +111,23 @@ struct OutBuffer
         else
         {
             debug (stomp) memset(data.ptr, 0xFF, data.length);
-            mem.xfree(data.ptr);
+            pureFree(data.ptr);
         }
     }
 
+    /// For porting with ease from dmd.backend.outbuf.Outbuffer
+    ubyte* buf() nothrow {
+        return data.ptr;
+    }
+
+    /// For porting with ease from dmd.backend.outbuf.Outbuffer
+    ubyte** bufptr() nothrow {
+        static struct Array { size_t length; ubyte* ptr; }
+        auto a = cast(Array*) &data;
+        assert(a.length == data.length && a.ptr == data.ptr);
+        return &a.ptr;
+    }
+
     extern (C++) size_t length() const pure @nogc @safe nothrow { return offset; }
 
     /**********************
@@ -109,7 +159,7 @@ struct OutBuffer
         else
         {
             debug (stomp) memset(data.ptr, 0xFF, data.length);
-            mem.xfree(extractData());
+            pureFree(extractData());
         }
     }
 
@@ -141,17 +191,18 @@ struct OutBuffer
         {
             debug (stomp)
             {
-                auto p = cast(ubyte*)mem.xmalloc(size);
+                auto p = cast(ubyte*) pureMalloc(size);
+                p || assert(0, "OutBuffer: out of memory.");
                 memcpy(p, data.ptr, offset);
                 memset(data.ptr, 0xFF, data.length);  // stomp old location
-                mem.xfree(data.ptr);
+                pureFree(data.ptr);
                 memset(p + offset, 0xff, size - offset); // stomp unused data
             }
             else
             {
-                auto p = cast(ubyte*)mem.xrealloc(data.ptr, size);
-                if (mem.isGCEnabled) // clear currently unused data to avoid false pointers
-                    memset(p + offset + nbytes, 0xff, size - offset - nbytes);
+                auto p = cast(ubyte*) pureRealloc(data.ptr, size);
+                p || assert(0, "OutBuffer: out of memory.");
+                memset(p + offset + nbytes, 0xff, size - offset - nbytes);
             }
             data = p[0 .. size];
         }
@@ -164,7 +215,7 @@ struct OutBuffer
      */
     extern (C++) void setsize(size_t size) pure nothrow @nogc @safe
     {
-        assert(size <= offset);
+        assert(size <= data.length);
         offset = size;
     }
 
@@ -185,6 +236,14 @@ struct OutBuffer
         notlinehead = true;
     }
 
+    // Write an array to the buffer, no reserve check
+    @trusted nothrow
+    void writen(const void *b, size_t len)
+    {
+        memcpy(data.ptr + offset, b, len);
+        offset += len;
+    }
+
     extern (C++) void write(const(void)* data, size_t nbytes) pure nothrow
     {
         write(data[0 .. nbytes]);
@@ -199,27 +258,90 @@ struct OutBuffer
         offset += buf.length;
     }
 
-    extern (C++) void writestring(const(char)* string) pure nothrow
+    /**
+     * Writes a 16 bit value, no reserve check.
+     */
+    @trusted nothrow
+    void write16n(int v)
     {
-        write(string.toDString);
+        auto x = cast(ushort) v;
+        data[offset] = x & 0x00FF;
+        data[offset + 1] = x >> 8u;
+        offset += 2;
     }
 
+    /**
+     * Writes a 16 bit value.
+     */
+    void write16(int v) nothrow
+    {
+        auto u = cast(ushort) v;
+        write(&u, u.sizeof);
+    }
+
+    /**
+     * Writes a 32 bit int.
+     */
+    void write32(int v) nothrow @trusted
+    {
+        write(&v, v.sizeof);
+    }
+
+    /**
+     * Writes a 64 bit int.
+     */
+    @trusted void write64(long v) nothrow
+    {
+        write(&v, v.sizeof);
+    }
+
+    /// NOT zero-terminated
+    extern (C++) void writestring(const(char)* s) pure nothrow
+    {
+        if (!s)
+            return;
+        import core.stdc.string : strlen;
+        write(s[0 .. strlen(s)]);
+    }
+
+    /// ditto
     void writestring(const(char)[] s) pure nothrow
     {
         write(s);
     }
 
+    /// ditto
     void writestring(string s) pure nothrow
     {
         write(s);
     }
 
+    /// NOT zero-terminated, followed by newline
     void writestringln(const(char)[] s) pure nothrow
     {
         writestring(s);
         writenl();
     }
 
+    // Zero-terminated
+    void writeString(const(char)* s) pure nothrow @trusted
+    {
+        write(s[0 .. strlen(s)+1]);
+    }
+
+    /// ditto
+    void writeString(const(char)[] s) pure nothrow
+    {
+        write(s);
+        writeByte(0);
+    }
+
+    /// ditto
+    void writeString(string s) pure nothrow
+    {
+        writeString(cast(const(char)[])(s));
+    }
+
     extern (C++) void prependstring(const(char)* string) pure nothrow
     {
         size_t len = strlen(string);
@@ -244,6 +366,38 @@ struct OutBuffer
             notlinehead = false;
     }
 
+    // Write n zeros; return pointer to start of zeros
+    @trusted
+    void *writezeros(size_t n) nothrow
+    {
+        reserve(n);
+        auto result = memset(data.ptr + offset, 0, n);
+        offset += n;
+        return result;
+    }
+
+    // Position buffer to accept the specified number of bytes at offset
+    @trusted
+    void position(size_t where, size_t nbytes) nothrow
+    {
+        if (where + nbytes > data.length)
+        {
+            reserve(where + nbytes - offset);
+        }
+        offset = where;
+
+        debug assert(offset + nbytes <= data.length);
+    }
+
+    /**
+     * Writes an 8 bit byte, no reserve check.
+     */
+    extern (C++) @trusted nothrow
+    void writeByten(int b)
+    {
+        this.data[offset++] = cast(ubyte) b;
+    }
+
     extern (C++) void writeByte(uint b) pure nothrow
     {
         if (doindent && !notlinehead && b != '\n')
@@ -369,14 +523,6 @@ struct OutBuffer
         }
     }
 
-    extern (C++) void write(RootObject obj) /*nothrow*/
-    {
-        if (obj)
-        {
-            writestring(obj.toChars());
-        }
-    }
-
     extern (C++) void fill0(size_t nbytes) pure nothrow
     {
         reserve(nbytes);
@@ -428,8 +574,8 @@ struct OutBuffer
                 break;
         }
         offset += count;
-        if (mem.isGCEnabled)
-            memset(data.ptr + offset, 0xff, psize - count);
+        // if (mem.isGCEnabled)
+             memset(data.ptr + offset, 0xff, psize - count);
     }
 
     static if (__VERSION__ < 2092)
@@ -460,7 +606,6 @@ struct OutBuffer
      */
     extern (C++) void print(ulong u) pure nothrow
     {
-        //import core.internal.string;  // not available
         UnsignedStringBuf buf = void;
         writestring(unsignedToTempString(u, buf));
     }
@@ -558,6 +703,11 @@ struct OutBuffer
         return extractData()[0 .. length];
     }
 
+    extern (D) byte[] extractUbyteSlice(bool nullTerminate = false) pure nothrow
+    {
+        return cast(byte[]) extractSlice(nullTerminate);
+    }
+
     // Append terminating null if necessary and get view of internal buffer
     extern (C++) char* peekChars() pure nothrow
     {
@@ -577,6 +727,36 @@ struct OutBuffer
         return extractData();
     }
 
+    void writesLEB128(int value) pure nothrow
+    {
+        while (1)
+        {
+            ubyte b = value & 0x7F;
+
+            value >>= 7;            // arithmetic right shift
+            if ((value == 0 && !(b & 0x40)) ||
+                (value == -1 && (b & 0x40)))
+            {
+                 writeByte(b);
+                 break;
+            }
+            writeByte(b | 0x80);
+        }
+    }
+
+    void writeuLEB128(uint value) pure nothrow
+    {
+        do
+        {
+            ubyte b = value & 0x7F;
+
+            value >>= 7;
+            if (value)
+                b |= 0x80;
+            writeByte(b);
+        } while (value);
+    }
+
     /**
     Destructively saves the contents of `this` to `filename`. As an
     optimization, if the file already has identical contents with the buffer,
@@ -591,7 +771,6 @@ struct OutBuffer
     */
     extern(D) bool moveToFile(const char* filename)
     {
-        import dmd.root.file;
         bool result = true;
         const bool identical = this[] == FileMapping!(const ubyte)(filename)[];
 
@@ -615,12 +794,12 @@ struct OutBuffer
         else
         {
             if (!identical)
-                File.write(filename, this[]);
+                writeFile(filename, this[]);
             destroy();
         }
 
         return identical
-            ? result && File.touch(filename)
+            ? result && touchFile(filename)
             : result;
     }
 }
@@ -645,7 +824,7 @@ char[] unsignedToTempString(ulong value, char[] buf, uint radix = 10) @safe pure
         else
         {
             ubyte x = cast(ubyte)(value % radix);
-            value = value / radix;
+            value /= radix;
             buf[--i] = cast(char)((x < 10) ? x + '0' : x - 10 + 'a');
         }
     } while (value);
similarity index 90%
rename from gcc/d/dmd/root/outbuffer.h
rename to gcc/d/dmd/common/outbuffer.h
index b635373c1838956dc1349b452047abd5b13eb1f1..a5e3f9c541d7d60a0dbab0583060ea5b346b309c 100644 (file)
@@ -4,14 +4,14 @@
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.h
+ * https://github.com/dlang/dmd/blob/master/src/dmd/common/outbuffer.h
  */
 
 #pragma once
 
-#include "dsystem.h"
-#include "dcompat.h"
-#include "rmem.h"
+#include "../root/dsystem.h"
+#include "../root/dcompat.h"
+#include "../root/rmem.h"
 
 class RootObject;
 
@@ -22,7 +22,7 @@ private:
     DArray<unsigned char> data;
     d_size_t offset;
     bool notlinehead;
-    voidfileMapping;  // pointer to a file mapping object not used on the C++ side
+    void *fileMapping;  // pointer to a file mapping object not used on the C++ side
 public:
     bool doindent;
     bool spaces;
diff --git a/gcc/d/dmd/common/string.d b/gcc/d/dmd/common/string.d
new file mode 100644 (file)
index 0000000..026374a
--- /dev/null
@@ -0,0 +1,209 @@
+/**
+ * Common string functions including filename manipulation.
+ *
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * Authors:   Walter Bright, http://www.digitalmars.com
+ * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d)
+ * Documentation: https://dlang.org/phobos/dmd_common_string.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/string.d
+ */
+module dmd.common.string;
+
+/**
+Defines a temporary array using a fixed-length buffer as back store. If the length
+of the buffer suffices, it is readily used. Otherwise, `malloc` is used to
+allocate memory for the array and `free` is used for deallocation in the
+destructor.
+
+This type is meant to use exclusively as an automatic variable. It is not
+default constructible or copyable.
+*/
+struct SmallBuffer(T)
+{
+    import core.stdc.stdlib : malloc, free;
+
+    private T[] _extent;
+    private bool needsFree;
+
+    @disable this(); // no default ctor
+    @disable this(ref const SmallBuffer!T); // noncopyable, nonassignable
+
+    this(size_t len, T[] buffer)
+    {
+        if (len <= buffer.length)
+        {
+            _extent = buffer[0 .. len];
+        }
+        else
+        {
+            _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
+            _extent.ptr || assert(0, "Out of memory.");
+            needsFree = true;
+        }
+        assert(this.length == len);
+    }
+
+    ~this()
+    {
+        if (needsFree)
+            free(_extent.ptr);
+    }
+
+    void create(size_t len)
+    {
+        if (len <= _extent.length)
+        {
+            _extent = _extent[0 .. len];
+        }
+        else
+        {
+            __dtor();
+            _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
+            _extent.ptr || assert(0, "Out of memory.");
+            needsFree = true;
+        }
+        assert(this.length == len);
+    }
+
+    // Force accesses to extent to be scoped.
+    scope inout extent()
+    {
+        return _extent;
+    }
+
+    alias extent this;
+}
+
+/// ditto
+unittest
+{
+    char[230] buf = void;
+    auto a = SmallBuffer!char(10, buf);
+    assert(a[] is buf[0 .. 10]);
+    auto b = SmallBuffer!char(1000, buf);
+    assert(b[] !is buf[]);
+    b.create(1000);
+    assert(b.length == 1000);
+    assert(b[] !is buf[]);
+}
+
+/**
+Converts a zero-terminated C string to a D slice. Takes linear time and allocates no memory.
+
+Params:
+stringz = the C string to be converted
+
+Returns:
+a slice comprehending the string. The terminating 0 is not part of the slice.
+*/
+auto asDString(C)(C* stringz) pure @nogc nothrow
+{
+    import core.stdc.string : strlen;
+    return stringz[0 .. strlen(stringz)];
+}
+
+///
+unittest
+{
+    const char* p = "123".ptr;
+    assert(p.asDString == "123");
+}
+
+/**
+(Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by
+`buffer` containing the converted string. The terminating zero is not part of the returned slice,
+but is guaranteed to follow it.
+*/
+version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow
+{
+    import core.sys.windows.winnls : CP_ACP, MultiByteToWideChar;
+    // assume filenames encoded in system default Windows ANSI code page
+    enum CodePage = CP_ACP;
+
+    if (narrow is null)
+        return null;
+
+    const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
+    if (requiredLength < cast(int) buffer.length)
+    {
+        buffer[requiredLength] = 0;
+        return buffer[0 .. requiredLength];
+    }
+
+    buffer.create(requiredLength + 1);
+    const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, requiredLength);
+    assert(length == requiredLength);
+    buffer[length] = 0;
+    return buffer[0 .. length];
+}
+
+/**************************************
+* Converts a path to one suitable to be passed to Win32 API
+* functions that can deal with paths longer than 248
+* characters then calls the supplied function on it.
+*
+* Params:
+*  path = The Path to call F on.
+*
+* Returns:
+*  The result of calling F on path.
+*
+* References:
+*  https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+*/
+version(Windows) auto extendedPathThen(alias F)(const(char)[] path)
+{
+    import core.sys.windows.winbase;
+    import core.sys.windows.winnt;
+
+    if (!path.length)
+        return F((wchar[]).init);
+
+    wchar[1024] buf = void;
+    auto store = SmallBuffer!wchar(buf.length, buf);
+    auto wpath = toWStringz(path, store);
+
+    // GetFullPathNameW expects a sized buffer to store the result in. Since we don't
+    // know how large it has to be, we pass in null and get the needed buffer length
+    // as the return code.
+    const pathLength = GetFullPathNameW(&wpath[0],
+                                        0 /*length8*/,
+                                        null /*output buffer*/,
+                                        null /*filePartBuffer*/);
+    if (pathLength == 0)
+    {
+        return F((wchar[]).init);
+    }
+
+    // wpath is the UTF16 version of path, but to be able to use
+    // extended paths, we need to prefix with `\\?\` and the absolute
+    // path.
+    static immutable prefix = `\\?\`w;
+
+    // prefix only needed for long names and non-UNC names
+    const needsPrefix = pathLength >= MAX_PATH && (wpath[0] != '\\' || wpath[1] != '\\');
+    const prefixLength = needsPrefix ? prefix.length : 0;
+
+    // +1 for the null terminator
+    const bufferLength = pathLength + prefixLength + 1;
+
+    wchar[1024] absBuf = void;
+    auto absPath = SmallBuffer!wchar(bufferLength, absBuf);
+
+    absPath[0 .. prefixLength] = prefix[0 .. prefixLength];
+
+    const absPathRet = GetFullPathNameW(&wpath[0],
+        cast(uint)(absPath.length - prefixLength - 1),
+        &absPath[prefixLength],
+        null /*filePartBuffer*/);
+
+    if (absPathRet == 0 || absPathRet > absPath.length - prefixLength)
+    {
+        return F((wchar[]).init);
+    }
+
+    absPath[$ - 1] = '\0';
+    // Strip null terminator from the slice
+    return F(absPath[0 .. $ - 1]);
+}
index d4a8b136d430ad8fc82e0d632ee142234c84cb20..05bd4bd550d1c69ab70d6a75e99d29fa2cbaaba0 100644 (file)
@@ -28,7 +28,7 @@ import dmd.globals;
 import dmd.identifier;
 import dmd.mtype;
 import dmd.typesem;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.tokens;
@@ -452,7 +452,6 @@ extern (C++) final class StaticForeach : RootObject
             sc = sc.startCTFE();
             aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
             sc = sc.endCTFE();
-            aggrfe.aggr = aggrfe.aggr.optimize(WANTvalue);
         }
 
         if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Terror)
index bb40649dc0bfa5d085587c57c3caa08925465713..7d8ab67ee6acd9061e638ee9336dec73e3225a0c 100644 (file)
@@ -23,7 +23,7 @@ import dmd.lexer;
 import dmd.parse;
 import dmd.errors;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.root.string;
@@ -72,6 +72,7 @@ final class CParser(AST) : Parser!AST
     {
         //printf("cparseTranslationUnit()\n");
         symbols = new AST.Dsymbols();
+        addBuiltinDeclarations();
         while (1)
         {
             if (token.value == TOK.endOfFile)
@@ -756,7 +757,6 @@ final class CParser(AST) : Parser!AST
             switch (token.value)
             {
             case TOK.dot:
-            case TOK.arrow:
                 nextToken();
                 if (token.value == TOK.identifier)
                 {
@@ -767,6 +767,19 @@ final class CParser(AST) : Parser!AST
                 error("identifier expected following `.`, not `%s`", token.toChars());
                 break;
 
+            case TOK.arrow:
+                nextToken();
+                if (token.value == TOK.identifier)
+                {
+                    Identifier id = token.ident;
+                    auto die = new AST.DotIdExp(loc, e, id);
+                    die.arrow = true;
+                    e = die;
+                    break;
+                }
+                error("identifier expected following `->`, not `%s`", token.toChars());
+                break;
+
             case TOK.plusPlus:
                 e = new AST.PostExp(TOK.plusPlus, loc, e);
                 break;
@@ -949,6 +962,7 @@ final class CParser(AST) : Parser!AST
                 nextToken();
                 auto t = cparseTypeName();
                 check(TOK.rightParenthesis);
+                pt = &token;
 
                 if (token.value == TOK.leftCurly)
                 {
@@ -957,6 +971,17 @@ final class CParser(AST) : Parser!AST
                     auto ce = new AST.CompoundLiteralExp(loc, t, ci);
                     return cparsePostfixOperators(ce);
                 }
+                else if (t.isTypeIdentifier() &&
+                         token.value == TOK.leftParenthesis &&
+                         !isCastExpression(pt))
+                {
+                    /* this might actually be a function
+                     * call that looks like `(a)(b)` or even `(a)(b,c)`
+                     */
+                    auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
+                    ie.parens = true;    // disambiguate it from being a declaration
+                    return new AST.CallExp(loc, ie, cparseArguments());
+                }
                 else
                 {
                     // ( type-name ) cast-expression
@@ -1451,6 +1476,7 @@ final class CParser(AST) : Parser!AST
 
         auto symbolsSave = symbols;
         Specifier specifier;
+        specifier.packalign = this.packalign;
         auto tspec = cparseDeclarationSpecifiers(level, specifier);
 
         /* If a declarator does not follow, it is unnamed
@@ -1459,7 +1485,8 @@ final class CParser(AST) : Parser!AST
         {
             nextToken();
             auto tt = tspec.isTypeTag();
-            if (!tt || !tt.id)
+            if (!tt ||
+                !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
                 return; // legal but meaningless empty declaration, ignore it
 
             /* `struct tag;` and `struct tag { ... };`
@@ -1493,7 +1520,7 @@ final class CParser(AST) : Parser!AST
         {
             Identifier id;
             AST.Expression asmname;
-            auto dt = cparseDeclarator(DTR.xdirect, tspec, id);
+            auto dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier);
             if (!dt)
             {
                 panic();
@@ -1674,6 +1701,8 @@ final class CParser(AST) : Parser!AST
                     return;
 
                 case TOK.comma:
+                    if (!symbolsSave)
+                        symbolsSave = symbols;
                     nextToken();
                     break;
 
@@ -1720,8 +1749,9 @@ final class CParser(AST) : Parser!AST
              */
             auto pl = ft.parameterList;
             pl.hasIdentifierList = true;        // semantic needs to know to adjust parameter types
-            if (pl.varargs != AST.VarArg.none)
+            if (pl.varargs != AST.VarArg.none && pl.length)
                 error("function identifier-list cannot end with `...`");
+            ft.parameterList.varargs = AST.VarArg.variadic;     // but C11 allows extra arguments
             auto plLength = pl.length;
             if (symbols.length != plLength)
                 error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
@@ -1756,7 +1786,10 @@ final class CParser(AST) : Parser!AST
                     }
                 }
                 if (!p.type)
+                {
                     error("no declaration for identifier `%s`", p.ident.toChars());
+                    p.type = AST.Type.terror;
+                }
             }
         }
 
@@ -2240,14 +2273,14 @@ final class CParser(AST) : Parser!AST
      *  declarator   = declarator kind
      *  t            = base type to start with
      *  pident       = set to Identifier if there is one, null if not
-     *  storageClass = any storage classes seen so far that apply to a function
+     *  specifier    = specifiers in and out
      * Returns:
      *  type declared. If a TypeFunction is returned, this.symbols is the
      *  symbol table for the parameter-type-list, which will contain any
      *  declared struct, union or enum tags.
      */
     private AST.Type cparseDeclarator(DTR declarator, AST.Type t,
-        out Identifier pident, StorageClass storageClass = 0)
+        out Identifier pident, ref Specifier specifier)
     {
         //printf("cparseDeclarator(%d)\n", declarator);
         AST.Types constTypes; // all the Types that will need `const` applied to them
@@ -2285,6 +2318,8 @@ final class CParser(AST) : Parser!AST
                     const mod = cparseTypeQualifierList();
                     if (mod & MOD.xconst)
                         constTypes.push(t);
+                    if (token.value == TOK.__attribute__)
+                        cparseGnuAttributes(specifier);
                     continue;
 
                 default:
@@ -2352,8 +2387,9 @@ final class CParser(AST) : Parser!AST
                         }
                         else
                         {
-                            // An array of unknown size, fake it with a DArray
-                            ta = new AST.TypeDArray(t); // []
+                            /* C11 6.7.6.2-4 An [ ] array is an incomplete array type
+                             */
+                            ta = new AST.TypeSArray(t);
                         }
                         check(TOK.rightBracket);
 
@@ -2388,7 +2424,7 @@ final class CParser(AST) : Parser!AST
                             /* C11 6.7.6.2-1: the element type shall not be an incomplete or
                              * function type.
                              */
-                            if (ta.isTypeDArray() && !isVLA)
+                            if (ta.isTypeSArray() && ta.isTypeSArray().isIncomplete() && !isVLA)
                                 error("array type has incomplete element type `%s`", ta.toChars());
                         }
 
@@ -2489,9 +2525,10 @@ final class CParser(AST) : Parser!AST
     AST.Type cparseTypeName()
     {
         Specifier specifier;
+        specifier.packalign.setDefault();
         auto tspec = cparseSpecifierQualifierList(LVL.global, specifier);
         Identifier id;
-        return cparseDeclarator(DTR.xabstract, tspec, id);
+        return cparseDeclarator(DTR.xabstract, tspec, id, specifier);
     }
 
     /***********************************
@@ -2525,13 +2562,19 @@ final class CParser(AST) : Parser!AST
         StorageClass varargsStc;
 
         check(TOK.leftParenthesis);
-        if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis)
+        if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis) // func(void)
         {
             nextToken();
             nextToken();
             return AST.ParameterList(parameters, varargs, varargsStc);
         }
 
+        if (token.value == TOK.rightParenthesis)        // func()
+        {
+            nextToken();
+            return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
+        }
+
         /* The check for identifier-list comes later,
          * when doing the trailing declaration-list (opt)
          */
@@ -2541,6 +2584,8 @@ final class CParser(AST) : Parser!AST
                 break;
             if (token.value == TOK.dotDotDot)
             {
+                if (parameters.length == 0)     // func(...)
+                    error("named parameter required before `...`");
                 varargs = AST.VarArg.variadic;  // C-style variadics
                 nextToken();
                 check(TOK.rightParenthesis);
@@ -2548,10 +2593,16 @@ final class CParser(AST) : Parser!AST
             }
 
             Specifier specifier;
+            specifier.packalign.setDefault();
             auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier);
+            if (tspec && specifier.mod & MOD.xconst)
+            {
+                tspec = toConst(tspec);
+                specifier.mod = MOD.xnone;      // 'used' it
+            }
 
             Identifier id;
-            auto t = cparseDeclarator(DTR.xparameter, tspec, id);
+            auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
             if (specifier.mod & MOD.xconst)
                 t = toConst(t);
             auto param = new AST.Parameter(STC.parameter, t, id, null, null);
@@ -2920,6 +2971,7 @@ final class CParser(AST) : Parser!AST
          *    enum gnu-attributes (opt) identifier
          */
         Specifier specifier;
+        specifier.packalign.setDefault();
         if (token.value == TOK.__attribute__)
             cparseGnuAttributes(specifier);
 
@@ -2950,6 +3002,16 @@ final class CParser(AST) : Parser!AST
                 nextToken();
                 auto mloc = token.loc;
 
+                if (token.value == TOK.__attribute__)
+                {
+                    /* gnu-attributes can appear here, but just scan and ignore them
+                     * https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html
+                     */
+                    Specifier specifierx;
+                    specifierx.packalign.setDefault();
+                    cparseGnuAttributes(specifierx);
+                }
+
                 AST.Expression value;
                 if (token.value == TOK.assign)
                 {
@@ -2958,6 +3020,16 @@ final class CParser(AST) : Parser!AST
                     // TODO C11 6.7.2.2-2 value must fit into an int
                 }
 
+                if (token.value == TOK.__attribute__)
+                {
+                    /* gnu-attributes can appear here, but just scan and ignore them
+                     * https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html
+                     */
+                    Specifier specifierx;
+                    specifierx.packalign.setDefault();
+                    cparseGnuAttributes(specifierx);
+                }
+
                 auto em = new AST.EnumMember(mloc, ident, value, null, 0, null, null);
                 members.push(em);
 
@@ -3037,14 +3109,12 @@ final class CParser(AST) : Parser!AST
             check(TOK.rightCurly);
 
             if ((*members).length == 0) // C11 6.7.2.1-8
-                /* TODO: not strict enough, should really be contains "no named members",
-                 * not just "no members".
-                 * I.e. an unnamed bit field, _Static_assert, etc, are not named members,
-                 * but will pass this check.
-                 * Be careful to detect named members that come anonymous structs.
-                 * Correctly doing this will likely mean moving it to typesem.d.
+            {
+                /* allow empty structs as an extension
+                 *  struct-declarator-list:
+                 *    struct-declarator (opt)
                  */
-                error("empty struct-declaration-list for `%s %s`", Token.toChars(structOrUnion), tag ? tag.toChars() : "Anonymous".ptr);
+            }
         }
         else if (!tag)
             error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
@@ -3083,7 +3153,13 @@ final class CParser(AST) : Parser!AST
 
         auto symbolsSave = symbols;
         Specifier specifier;
+        specifier.packalign = this.packalign;
         auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
+        if (tspec && specifier.mod & MOD.xconst)
+        {
+            tspec = toConst(tspec);
+            specifier.mod = MOD.xnone;          // 'used' it
+        }
 
         /* If a declarator does not follow, it is unnamed
          */
@@ -3139,12 +3215,14 @@ final class CParser(AST) : Parser!AST
                 dt = tspec;
             }
             else
-                dt = cparseDeclarator(DTR.xdirect, tspec, id);
-            if (!dt)
             {
-                panic();
-                nextToken();
-                break;          // error recovery
+                dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier);
+                if (!dt)
+                {
+                    panic();
+                    nextToken();
+                    break;          // error recovery
+                }
             }
 
             AST.Expression width;
@@ -3155,9 +3233,6 @@ final class CParser(AST) : Parser!AST
                 width = cparseConstantExp();
             }
 
-            if (specifier.mod & MOD.xconst)
-                dt = toConst(dt);
-
             /* GNU Extensions
              * struct-declarator:
              *    declarator gnu-attributes (opt)
@@ -3234,8 +3309,8 @@ final class CParser(AST) : Parser!AST
      */
     private bool isCDeclaration(ref Token* pt)
     {
-        //printf("isCDeclaration()\n");
         auto t = pt;
+        //printf("isCDeclaration() %s\n", t.toChars());
         if (!isDeclarationSpecifiers(t))
             return false;
 
@@ -3360,8 +3435,8 @@ final class CParser(AST) : Parser!AST
      */
     private bool isAssignmentExpression(ref Token* pt)
     {
-        //printf("isAssignmentExpression()\n");
         auto t = pt;
+        //printf("isAssignmentExpression() %s\n", t.toChars());
 
         /* This doesn't actually check for grammar matching an
          * assignment-expression. It just matches ( ) [ ] looking for
@@ -3384,6 +3459,15 @@ final class CParser(AST) : Parser!AST
                 case TOK.leftParenthesis:
                     if (!skipParens(t, &t))
                         return false;
+                    /*
+                        https://issues.dlang.org/show_bug.cgi?id=22267
+                        Fix issue 22267: If the parser encounters the following
+                            `identifier variableName = (expression);`
+                        the initializer is not identified as such since the parentheses
+                        cause the parser to keep walking indefinitely
+                        (whereas `(1) + 1` would not be affected.).
+                    */
+                    any = true;
                     continue;
 
                 case TOK.leftBracket:
@@ -3391,6 +3475,11 @@ final class CParser(AST) : Parser!AST
                         return false;
                     continue;
 
+                case TOK.leftCurly:
+                    if (!skipBraces(t))
+                        return false;
+                    continue;
+
                 default:
                     any = true;   // assume token was part of an a-e
                     t = peek(t);
@@ -3427,6 +3516,7 @@ final class CParser(AST) : Parser!AST
 
         auto t = pt;
 
+        bool seenType;
         bool any;
         while (1)
         {
@@ -3445,9 +3535,19 @@ final class CParser(AST) : Parser!AST
                 case TOK._Bool:
                 //case TOK._Imaginary:
                 case TOK._Complex:
-                case TOK.identifier: // typedef-name
                     t = peek(t);
+                    seenType = true;
                     any = true;
+                    continue;
+
+                case TOK.identifier: // typedef-name
+                    if (!seenType)
+                    {
+                        t = peek(t);
+                        seenType = true;
+                        any = true;
+                        continue;
+                    }
                     break;
 
                 case TOK.struct_:
@@ -3878,6 +3978,10 @@ final class CParser(AST) : Parser!AST
                     t = tk;
                     break;
                 }
+
+                if (tk.value == TOK.leftParenthesis && peek(tk).value == TOK.rightParenthesis)
+                    return false;    // (type-name)() is not a cast (it might be a function call)
+
                 if (!isCastExpression(tk, true))
                 {
                     if (afterParenType) // could be ( type-name ) ( unary-expression )
@@ -4071,6 +4175,7 @@ final class CParser(AST) : Parser!AST
         SCW scw;        /// storage-class specifiers
         MOD mod;        /// type qualifiers
         AST.Expressions*  alignExps;  /// alignment
+        structalign_t packalign;  /// #pragma pack alignment value
     }
 
     /***********************
@@ -4089,19 +4194,19 @@ final class CParser(AST) : Parser!AST
             if (level == LVL.global)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_;
+                    stc = AST.STC.extern_;
             }
             else if (level == LVL.local)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_;
+                    stc = AST.STC.extern_;
                 else if (specifier.scw & SCW.xstatic)
                     stc = AST.STC.static_;
             }
             else if (level == LVL.member)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_;
+                    stc = AST.STC.extern_;
                 else if (specifier.scw & SCW.xstatic)
                     stc = AST.STC.static_;
             }
@@ -4111,21 +4216,23 @@ final class CParser(AST) : Parser!AST
             if (level == LVL.global)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_ | AST.STC.gshared;
+                    stc = AST.STC.extern_ | AST.STC.gshared;
+                else if (specifier.scw & SCW.xstatic)
+                    stc = AST.STC.gshared | AST.STC.static_;
                 else
                     stc = AST.STC.gshared;
             }
             else if (level == LVL.local)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_ | AST.STC.gshared;
+                    stc = AST.STC.extern_ | AST.STC.gshared;
                 else if (specifier.scw & SCW.xstatic)
                     stc = AST.STC.gshared;
             }
             else if (level == LVL.member)
             {
                 if (specifier.scw & SCW.xextern)
-                   stc = AST.STC.extern_ | AST.STC.gshared;
+                    stc = AST.STC.extern_ | AST.STC.gshared;
                 else if (specifier.scw & SCW.xstatic)
                     stc = AST.STC.gshared;
             }
@@ -4235,15 +4342,59 @@ final class CParser(AST) : Parser!AST
      */
     private AST.Dsymbol applySpecifier(AST.Dsymbol s, ref Specifier specifier)
     {
+        //printf("applySpecifier() %s\n", s.toChars());
         if (specifier.alignExps)
         {
+            //printf("  applying _Alignas %s, packalign %d\n", (*specifier.alignExps)[0].toChars(), cast(int)specifier.packalign);
             // Wrap declaration in an AlignDeclaration
             auto decls = new AST.Dsymbols(1);
             (*decls)[0] = s;
             s = new AST.AlignDeclaration(s.loc, specifier.alignExps, decls);
         }
+        else if (!specifier.packalign.isDefault())
+        {
+            //printf("  applying packalign %d\n", cast(int)specifier.packalign);
+            // Wrap #pragma pack in an AlignDeclaration
+            auto decls = new AST.Dsymbols(1);
+            (*decls)[0] = s;
+            s = new AST.AlignDeclaration(s.loc, specifier.packalign, decls);
+        }
         return s;
     }
 
+    /***********************************
+     * Add global target-dependent builtin declarations.
+     */
+    private void addBuiltinDeclarations()
+    {
+        void genBuiltinFunc(Identifier id, AST.VarArg va)
+        {
+            auto tva_list = new AST.TypeIdentifier(Loc.initial, Id.builtin_va_list);
+            auto parameters = new AST.Parameters();
+            parameters.push(new AST.Parameter(STC.parameter | STC.ref_, tva_list, null, null, null));
+            auto pl = AST.ParameterList(parameters, va, 0);
+            auto tf = new AST.TypeFunction(pl, AST.Type.tvoid, LINK.c, 0);
+            auto s = new AST.FuncDeclaration(Loc.initial, Loc.initial, id, AST.STC.static_, tf, false);
+            symbols.push(s);
+        }
+
+        /* void __builtin_va_start(__builtin_va_list, ...);
+         * The second argument is supposed to be of any type, so fake it with the ...
+         */
+        genBuiltinFunc(Id.builtin_va_start, AST.VarArg.variadic);
+
+        /* void __builtin_va_end(__builtin_va_list);
+         */
+        genBuiltinFunc(Id.builtin_va_end, AST.VarArg.none);
+
+        /* struct __va_list_tag
+         * {
+         *    uint, uint, void*, void*
+         * }
+         */
+        auto s = new AST.StructDeclaration(Loc.initial, Id.va_list_tag, false);
+        symbols.push(s);
+    }
+
     //}
 }
index 0381f9ad6a466838b6113feb37f44aab6d3b4589..df742c0bd8f7f814ccc8585463e0a0a0505ef88f 100644 (file)
@@ -41,7 +41,7 @@ import dmd.identifier;
 import dmd.mtype;
 import dmd.nspace;
 import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.target;
@@ -98,21 +98,20 @@ extern(C++) const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
 }
 
 /******************************
- * Determine if sym is the 'primary' destructor, that is,
- * the most-aggregate destructor (the one that is defined as __xdtor)
+ * Determine if sym is a full aggregate destructor.
  * Params:
  *      sym = Dsymbol
  * Returns:
- *      true if sym is the primary destructor for an aggregate
+ *      true if sym is an aggregate destructor
  */
-bool isPrimaryDtor(const Dsymbol sym)
+bool isAggregateDtor(const Dsymbol sym)
 {
     const dtor = sym.isDtorDeclaration();
     if (!dtor)
         return false;
     const ad = dtor.isMember();
     assert(ad);
-    return dtor == ad.primaryDtor;
+    return dtor == ad.aggrDtor;
 }
 
 /// Context used when processing pre-semantic AST
@@ -1069,7 +1068,7 @@ private final class CppMangleVisitor : Visitor
 
             if (auto ctor = d.isCtorDeclaration())
                 buf.writestring(ctor.isCpCtor ? "C2" : "C1");
-            else if (d.isPrimaryDtor())
+            else if (d.isAggregateDtor())
                 buf.writestring("D1");
             else if (d.ident && d.ident == Id.assign)
                 buf.writestring("aS");
@@ -1184,7 +1183,7 @@ private final class CppMangleVisitor : Visitor
             mangleFunctionParameters(tf.parameterList);
             return;
         }
-        else if (d.isPrimaryDtor())
+        else if (d.isAggregateDtor())
         {
             buf.writestring("D1");
             mangleFunctionParameters(tf.parameterList);
index 22633a869d4510234bca515250acae09e87c77fa..7f76d7565e0d0db834b6c208720843017cddab68 100644 (file)
@@ -685,6 +685,11 @@ bool isSafePointerCast(Type srcPointee, Type destPointee)
     // It's OK if both are the same (modulo const)
     if (srcPointee.constConv(destPointee))
         return true;
+
+    // It's ok to cast from/to shared because CTFE is single threaded anyways
+    if (srcPointee.unSharedOf() == destPointee.unSharedOf())
+        return true;
+
     // It's OK if function pointers differ only in safe/pure/nothrow
     if (srcPointee.ty == Tfunction && destPointee.ty == Tfunction)
         return srcPointee.covariant(destPointee) == Covariant.yes ||
index 4c70565e5c2027553fb4cb86894b9569f005e217..87c3adae9e60ef90ceaee4a0038b576b7b2c1b5e 100644 (file)
@@ -31,12 +31,13 @@ import dmd.func;
 import dmd.globals;
 import dmd.impcnvtab;
 import dmd.id;
+import dmd.importc;
 import dmd.init;
 import dmd.intrange;
 import dmd.mtype;
 import dmd.opover;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.tokens;
 import dmd.typesem;
@@ -1445,6 +1446,29 @@ MATCH implicitConvTo(Expression e, Type t)
             if (tb.ty == Tpointer && e.e1.op == TOK.string_)
                 e.e1.accept(this);
         }
+
+        override void visit(TupleExp e)
+        {
+            result = e.type.implicitConvTo(t);
+            if (result != MATCH.nomatch)
+                return;
+
+            /* If target type is a tuple of same length, test conversion of
+             * each expression to the corresponding type in the tuple.
+             */
+            TypeTuple totuple = t.isTypeTuple();
+            if (totuple && e.exps.length == totuple.arguments.length)
+            {
+                result = MATCH.exact;
+                foreach (i, ex; *e.exps)
+                {
+                    auto to = (*totuple.arguments)[i].type;
+                    MATCH mi = ex.implicitConvTo(to);
+                    if (mi < result)
+                        result = mi;
+                }
+            }
+        }
     }
 
     scope ImplicitConvTo v = new ImplicitConvTo(t);
@@ -1476,12 +1500,8 @@ MATCH cimplicitConvTo(Expression e, Type t)
         return MATCH.convert;
     if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
         return MATCH.convert;
-    if (tb.ty == Tpointer && typeb.ty == Tpointer)
-    {
-        if (tb.isTypePointer().next.ty == Tvoid ||
-            typeb.isTypePointer().next.ty == Tvoid)
-            return MATCH.convert;       // convert to/from void* C11 6.3.2.3-1
-    }
+    if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
+        return MATCH.convert;
 
     return implicitConvTo(e, t);
 }
@@ -2189,13 +2209,20 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 return;
             }
 
+            /* If target type is a tuple of same length, cast each expression to
+             * the corresponding type in the tuple.
+             */
+            TypeTuple totuple;
+            if (auto tt = t.isTypeTuple())
+                totuple = e.exps.length == tt.arguments.length ? tt : null;
+
             TupleExp te = e.copy().isTupleExp();
             te.e0 = e.e0 ? e.e0.copy() : null;
             te.exps = e.exps.copy();
             for (size_t i = 0; i < te.exps.dim; i++)
             {
                 Expression ex = (*te.exps)[i];
-                ex = ex.castTo(sc, t);
+                ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
                 (*te.exps)[i] = ex;
             }
             result = te;
@@ -2821,6 +2848,13 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
     Expression e1 = pe1;
     Expression e2 = pe2;
 
+    // ImportC: do array/function conversions
+    if (sc)
+    {
+        e1 = e1.arrayFuncConv(sc);
+        e2 = e2.arrayFuncConv(sc);
+    }
+
     Type Lret(Type result)
     {
         pe1 = e1;
@@ -2838,7 +2872,7 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
         return result;
     }
 
-    /// Converts one of the expression too the other
+    /// Converts one of the expression to the other
     Type convert(ref Expression from, Type to)
     {
         from = from.castTo(sc, to);
@@ -2856,6 +2890,22 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
     Type t1b = e1.type.toBasetype();
     Type t2b = e2.type.toBasetype();
 
+    if (sc && sc.flags & SCOPE.Cfile)
+    {
+        // Integral types can be implicitly converted to pointers
+        if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
+        {
+            if (t1b.isintegral())
+            {
+                return convert(e1, t2b);
+            }
+            else if (t2b.isintegral())
+            {
+                return convert(e2, t1b);
+            }
+        }
+    }
+
     if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
     {
         if (op == TOK.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
@@ -3132,6 +3182,14 @@ Lagain:
     Lcc:
         while (1)
         {
+            MATCH i1woat = MATCH.exact;
+            MATCH i2woat = MATCH.exact;
+
+            if (auto t2c = t2.isTypeClass())
+                i1woat = t2c.implicitConvToWithoutAliasThis(t1);
+            if (auto t1c = t1.isTypeClass())
+                i2woat = t1c.implicitConvToWithoutAliasThis(t2);
+
             MATCH i1 = e2.implicitConvTo(t1);
             MATCH i2 = e1.implicitConvTo(t2);
 
@@ -3144,11 +3202,26 @@ Lagain:
                     i2 = MATCH.nomatch;
             }
 
-            if (i2)
+            // Match but without 'alias this' on classes
+            if (i2 && i2woat)
                 return coerce(t2);
-            if (i1)
+            if (i1 && i1woat)
                 return coerce(t1);
 
+            // Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
+            Type coerceImplicit(Type towards)
+            {
+                e1 = e1.implicitCastTo(sc, towards);
+                e2 = e2.implicitCastTo(sc, towards);
+                return Lret(towards);
+            }
+
+            // Implicit conversion with 'alias this'
+            if (i2)
+                return coerceImplicit(t2);
+            if (i1)
+                return coerceImplicit(t1);
+
             if (t1.ty == Tclass && t2.ty == Tclass)
             {
                 TypeClass tc1 = t1.isTypeClass();
@@ -3257,29 +3330,26 @@ Lagain:
         }
     }
 
-    if (t1.ty == Tstruct || t2.ty == Tstruct)
+    if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
     {
-        if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
-        {
-            if (isRecursiveAliasThis(att1, e1.type))
-                return null;
-            //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
-            e1 = resolveAliasThis(sc, e1);
-            t1 = e1.type;
-            t = t1;
-            goto Lagain;
-        }
-        if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
-        {
-            if (isRecursiveAliasThis(att2, e2.type))
-                return null;
-            //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
-            e2 = resolveAliasThis(sc, e2);
-            t2 = e2.type;
-            t = t2;
-            goto Lagain;
-        }
-        return null;
+        if (isRecursiveAliasThis(att1, e1.type))
+            return null;
+        //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
+        e1 = resolveAliasThis(sc, e1);
+        t1 = e1.type;
+        t = t1;
+        goto Lagain;
+    }
+
+    if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
+    {
+        if (isRecursiveAliasThis(att2, e2.type))
+            return null;
+        //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
+        e2 = resolveAliasThis(sc, e2);
+        t2 = e2.type;
+        t = t2;
+        goto Lagain;
     }
 
     if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
index b065251e6523198154c0636dfd867e27ce308e41..34a236ba26e7a5661d124a005afc69633b3208b2 100644 (file)
@@ -20,6 +20,7 @@ import dmd.aggregate;
 import dmd.apply;
 import dmd.arraytypes;
 import dmd.astenums;
+import dmd.attrib;
 import dmd.gluelayer;
 import dmd.declaration;
 import dmd.dscope;
@@ -367,7 +368,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         baseok = Baseok.none;
     }
 
-    static ClassDeclaration create(Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
+    static ClassDeclaration create(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
     {
         return new ClassDeclaration(loc, id, baseclasses, members, inObject);
     }
@@ -607,7 +608,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
 
                 if (!b.sym.alignsize)
                     b.sym.alignsize = target.ptrsize;
-                alignmember(b.sym.alignsize, b.sym.alignsize, &offset);
+                alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, &offset);
                 assert(bi < vtblInterfaces.dim);
 
                 BaseClass* bv = (*vtblInterfaces)[bi];
@@ -725,6 +726,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
 
         void searchVtbl(ref Dsymbols vtbl)
         {
+            bool seenInterfaceVirtual;
             foreach (s; vtbl)
             {
                 auto fd = s.isFuncDeclaration();
@@ -748,6 +750,23 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
                 if (fd == fdmatch)
                     continue;
 
+                /* Functions overriding interface functions for extern(C++) with VC++
+                 * are not in the normal vtbl, but in vtblFinal. If the implementation
+                 * is again overridden in a child class, both would be found here.
+                 * The function in the child class should override the function
+                 * in the base class, which is done here, because searchVtbl is first
+                 * called for the child class. Checking seenInterfaceVirtual makes
+                 * sure, that the compared functions are not in the same vtbl.
+                 */
+                if (fd.interfaceVirtual &&
+                    fd.interfaceVirtual is fdmatch.interfaceVirtual &&
+                    !seenInterfaceVirtual &&
+                    fdmatch.type.covariant(fd.type) == Covariant.yes)
+                {
+                    seenInterfaceVirtual = true;
+                    continue;
+                }
+
                 {
                 // Function type matching: exact > covariant
                 MATCH m1 = tf.equals(fd.type) ? MATCH.exact : MATCH.nomatch;
index 0f40c1142c73f5c36ea509e50e138e2217a7caeb..e3f135a03d8b8bbc93da86d63a694c0458c1a117 100644 (file)
@@ -16,6 +16,7 @@ import core.stdc.stdio;
 import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
+import dmd.attrib;
 import dmd.ctorflow;
 import dmd.dclass;
 import dmd.delegatize;
@@ -34,7 +35,7 @@ import dmd.init;
 import dmd.initsem;
 import dmd.intrange;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.target;
 import dmd.tokens;
@@ -705,7 +706,7 @@ extern (C++) final class AliasDeclaration : Declaration
         assert(s);
     }
 
-    static AliasDeclaration create(Loc loc, Identifier id, Type type)
+    static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
     {
         return new AliasDeclaration(loc, id, type);
     }
@@ -1192,14 +1193,7 @@ extern (C++) class VarDeclaration : Declaration
         /* If coming after a bit field in progress,
          * advance past the field
          */
-        if (fieldState.inFlight)
-        {
-            fieldState.inFlight = false;
-            if (0 && target.os & Target.OS.Posix)
-                fieldState.offset += (fieldState.bitOffset + 7) / 8;
-            else if (0 &&target.os == Target.OS.Windows)
-                fieldState.offset += fieldState.fieldSize;
-        }
+        fieldState.inFlight = false;
 
         const sz = t.size(loc);
         assert(sz != SIZE_INVALID && sz < uint.max);
@@ -1743,13 +1737,23 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
 
     override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
     {
-        //printf("BitFieldDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
+        //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
+        static void print(const ref FieldState fieldState)
+        {
+            printf("FieldState.offset      = %d bytes\n",   fieldState.offset);
+            printf("          .fieldOffset = %d bytes\n",   fieldState.fieldOffset);
+            printf("          .bitOffset   = %d bits\n",    fieldState.bitOffset);
+            printf("          .fieldSize   = %d bytes\n",   fieldState.fieldSize);
+            printf("          .inFlight    = %d\n\n", fieldState.inFlight);
+        }
+        //print(fieldState);
 
         Type t = type.toBasetype();
+        const bool anon = isAnonymous();
 
         // List in ad.fields. Even if the type is error, it's necessary to avoid
         // pointless error diagnostic "more initializers than fields" on struct literal.
-        if (!isAnonymous())
+        if (!anon)
             ad.fields.push(this);
 
         if (t.ty == Terror)
@@ -1760,17 +1764,36 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
         uint memsize = cast(uint)sz;                // size of member
         uint memalignsize = target.fieldalign(t);   // size of member for alignment purposes
 
-        if (fieldWidth == 0 && !isAnonymous())
+        if (fieldWidth == 0 && !anon)
             error(loc, "named bit fields cannot have 0 width");
         if (fieldWidth > memsize * 8)
             error(loc, "bit field width %d is larger than type", fieldWidth);
 
+        const style = target.c.bitFieldStyle;
+
         void startNewField()
         {
+            uint alignsize;
+            if (style == TargetC.BitFieldStyle.Gcc_Clang)
+            {
+                if (fieldWidth > 32)
+                    alignsize = memalignsize;
+                else if (fieldWidth > 16)
+                    alignsize = 4;
+                else if (fieldWidth > 8)
+                    alignsize = 2;
+                else
+                    alignsize = 1;
+            }
+            else
+                alignsize = memsize; // not memalignsize
+
+            uint dummy;
             offset = AggregateDeclaration.placeField(
                 &fieldState.offset,
-                memsize, memalignsize, alignment,
-                &ad.structsize, &ad.alignsize,
+                memsize, alignsize, alignment,
+                &ad.structsize,
+                (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
                 isunion);
 
             fieldState.inFlight = true;
@@ -1779,19 +1802,92 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
             fieldState.fieldSize = memsize;
         }
 
-        if (!fieldState.inFlight || fieldWidth == 0)
+        if (style == TargetC.BitFieldStyle.Gcc_Clang)
         {
-            startNewField();
+            if (fieldWidth == 0)
+            {
+                if (!isunion)
+                {
+                    // Use type of zero width field to align to next field
+                    fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
+                    ad.structsize = fieldState.offset;
+                }
+
+                fieldState.inFlight = false;
+                return;
+            }
+
+            if (ad.alignsize == 0)
+                ad.alignsize = 1;
+            if (!anon &&
+                  ad.alignsize < memalignsize)
+                ad.alignsize = memalignsize;
+        }
+        else if (style == TargetC.BitFieldStyle.MS)
+        {
+            if (ad.alignsize == 0)
+                ad.alignsize = 1;
+            if (fieldWidth == 0)
+            {
+                if (fieldState.inFlight && !isunion)
+                {
+                    // documentation says align to next int
+                    //const alsz = cast(uint)Type.tint32.size();
+                    const alsz = memsize; // but it really does this
+                    fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
+                    ad.structsize = fieldState.offset;
+                }
+
+                fieldState.inFlight = false;
+                return;
+            }
+        }
+        else if (style == TargetC.BitFieldStyle.DM)
+        {
+            if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
+                return;  // this probably should be a bug in DMC
+            if (ad.alignsize == 0)
+                ad.alignsize = 1;
+            if (fieldWidth == 0)
+            {
+                if (fieldState.inFlight && !isunion)
+                {
+                    const alsz = memsize;
+                    fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
+                    ad.structsize = fieldState.offset;
+                }
+
+                fieldState.inFlight = false;
+                return;
+            }
         }
 
-        if (0 && target.os & Target.OS.Posix)
+        if (!fieldState.inFlight)
+        {
+            startNewField();
+        }
+        else if (style == TargetC.BitFieldStyle.Gcc_Clang)
         {
-            if ((fieldState.offset%4 * 8) + fieldState.bitOffset + fieldWidth > int.sizeof * 8)
+            if (fieldState.bitOffset + fieldWidth > memsize * 8)
             {
+                //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
                 startNewField();
             }
+            else
+            {
+                // if alignment boundary is crossed
+                uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
+                uint end   = start + fieldWidth;
+                //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
+                if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
+                {
+                    //printf("alignment is crossed\n");
+                    startNewField();
+                }
+            }
         }
-        else if (1 || target.os == Target.OS.Windows)
+        else if (style == TargetC.BitFieldStyle.DM ||
+                 style == TargetC.BitFieldStyle.MS)
         {
             if (memsize != fieldState.fieldSize ||
                 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
@@ -1799,22 +1895,29 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
                 startNewField();
             }
         }
+        else
+            assert(0);
 
         offset = fieldState.fieldOffset;
         bitOffset = fieldState.bitOffset;
-        if (0 && target.os & Target.OS.Posix)
+
+        const pastField = bitOffset + fieldWidth;
+        if (style == TargetC.BitFieldStyle.Gcc_Clang)
         {
-            while (bitOffset > memsize * 8)
-            {
-                bitOffset -= 8;
-                offset += 1;
-            }
+            auto size = (pastField + 7) / 8;
+            fieldState.fieldSize = size;
+            //printf(" offset: %d, size: %d\n", offset, size);
+            ad.structsize = offset + size;
         }
+        else
+            fieldState.fieldSize = memsize;
+        //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
+        //print(fieldState);
 
-        //fieldState.fieldSize = memsize;
         if (!isunion)
         {
-            fieldState.bitOffset += fieldWidth;
+            fieldState.offset = offset + fieldState.fieldSize;
+            fieldState.bitOffset = pastField;
         }
 
         //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
@@ -1861,7 +1964,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
         storage_class = STC.static_ | STC.gshared;
         visibility = Visibility(Visibility.Kind.public_);
         linkage = LINK.c;
-        alignment = target.ptrsize;
+        alignment.set(target.ptrsize);
     }
 
     static TypeInfoDeclaration create(Type tinfo)
index 1c56defd3ee3a4c7e4825f77931de22e7ca2c106..4a4c35304177c3a62b84f3281ec9353165a86e19 100644 (file)
@@ -188,7 +188,7 @@ public:
     Dsymbol *overnext;          // next in overload list
     Dsymbol *_import;           // !=NULL if unresolved internal alias for selective import
 
-    static AliasDeclaration *create(Loc loc, Identifier *id, Type *type);
+    static AliasDeclaration *create(const Loc &loc, Identifier *id, Type *type);
     AliasDeclaration *syntaxCopy(Dsymbol *);
     bool overloadInsert(Dsymbol *s);
     const char *kind() const;
@@ -511,7 +511,7 @@ enum class BUILTIN : unsigned char
     toPrecReal
 };
 
-Expression *eval_builtin(Loc loc, FuncDeclaration *fd, Expressions *arguments);
+Expression *eval_builtin(const Loc &loc, FuncDeclaration *fd, Expressions *arguments);
 BUILTIN isBuiltin(FuncDeclaration *fd);
 
 class FuncDeclaration : public Declaration
@@ -535,6 +535,8 @@ public:
     VarDeclaration *vresult;            // result variable for out contracts
     LabelDsymbol *returnLabel;          // where the return goes
 
+    void *isTypeIsolatedCache;          // An AA on the D side to cache an expensive check result
+
     // used to prevent symbols in different
     // scopes from having the same name
     DsymbolTable *localsymtab;
@@ -839,9 +841,6 @@ public:
 class NewDeclaration : public FuncDeclaration
 {
 public:
-    Parameters *parameters;
-    VarArg varargs;
-
     NewDeclaration *syntaxCopy(Dsymbol *);
     const char *kind() const;
     bool isVirtual() const;
index 541fac7dfb43389087a88038466e9b692f457436..a1f36c0c48f9259e9f7a8a8bde479d65ec1ec9a1 100644 (file)
@@ -42,6 +42,7 @@ import dmd.mtype;
 import dmd.printast;
 import dmd.root.rmem;
 import dmd.root.array;
+import dmd.root.ctfloat;
 import dmd.root.region;
 import dmd.root.rootobject;
 import dmd.statement;
@@ -75,6 +76,7 @@ public Expression ctfeInterpret(Expression e)
         case TOK.template_:              // non-eponymous template/instance
         case TOK.scope_:                 // ditto
         case TOK.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
+        case TOK.dotTemplateInstance:    // ditto
         case TOK.dot:                    // ditto
              if (e.type.ty == Terror)
                 return ErrorExp.get();
@@ -2167,26 +2169,20 @@ public:
             return;
         }
 
-        // Note: This is a workaround for
-        // https://issues.dlang.org/show_bug.cgi?id=17351
-        // The aforementioned bug triggers when passing manifest constant by `ref`.
-        // If there was not a previous reference to them, they are
-        // not cached and trigger a "cannot be read at compile time".
-        // This fix is a crude solution to get it to work. A more proper
-        // approach would be to resolve the forward reference, but that is
-        // much more involved.
-        if (goal == CTFEGoal.LValue && e.var.type.isMutable())
+        if (goal == CTFEGoal.LValue)
         {
             if (auto v = e.var.isVarDeclaration())
             {
-                if (!v.isDataseg() && !v.isCTFE() && !istate)
-                {
-                    e.error("variable `%s` cannot be read at compile time", v.toChars());
-                    result = CTFEExp.cantexp;
-                    return;
-                }
                 if (!hasValue(v))
                 {
+                    // Compile-time known non-CTFE variable from an outer context
+                    // e.g. global or from a ref argument
+                    if (v.isConst() || v.isImmutable())
+                    {
+                        result = getVarExp(e.loc, istate, v, goal);
+                        return;
+                    }
+
                     if (!v.isCTFE() && v.isDataseg())
                         e.error("static variable `%s` cannot be read at compile time", v.toChars());
                     else // CTFE initiated from inside a function
@@ -2201,7 +2197,7 @@ public:
                     Expression ev = getValue(v);
                     if (ev.op == TOK.variable ||
                         ev.op == TOK.index ||
-                        ev.op == TOK.slice ||
+                        (ev.op == TOK.slice && ev.type.toBasetype().ty == Tsarray) ||
                         ev.op == TOK.dotVariable)
                     {
                         result = interpret(pue, ev, istate, goal);
@@ -2836,8 +2832,7 @@ public:
             auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, cast(StructDeclaration)cd, elems, e.newtype);
             se.origin = se;
             se.ownedByCtfe = OwnedBy.ctfe;
-            emplaceExp!(ClassReferenceExp)(pue, e.loc, se, e.type);
-            Expression eref = pue.exp();
+            Expression eref = ctfeEmplaceExp!ClassReferenceExp(e.loc, se, e.type);
             if (e.member)
             {
                 // Call constructor
@@ -6024,12 +6019,23 @@ public:
         }
         if (e.to.ty == Tsarray)
             e1 = resolveSlice(e1);
-        if (e.to.toBasetype().ty == Tbool && e1.type.ty == Tpointer)
+
+        auto tobt = e.to.toBasetype();
+        if (tobt.ty == Tbool && e1.type.ty == Tpointer)
         {
             emplaceExp!(IntegerExp)(pue, e.loc, e1.op != TOK.null_, e.to);
             result = pue.exp();
             return;
         }
+        else if (tobt.isTypeBasic() && e1.op == TOK.null_)
+        {
+            if (tobt.isintegral())
+                emplaceExp!(IntegerExp)(pue, e.loc, 0, e.to);
+            else if (tobt.isreal())
+                emplaceExp!(RealExp)(pue, e.loc, CTFloat.zero, e.to);
+            result = pue.exp();
+            return;
+        }
         result = ctfeCast(pue, e.loc, e.type, e.to, e1);
     }
 
@@ -6306,7 +6312,7 @@ public:
             auto tsa = cast(TypeSArray)v.type;
             auto len = cast(size_t)tsa.dim.toInteger();
             UnionExp ue = void;
-            result = createBlockDuplicatedArrayLiteral(&ue, ex.loc, v.type, ex, len);
+            result = createBlockDuplicatedArrayLiteral(&ue, e.loc, v.type, result, len);
             if (result == ue.exp())
                 result = ue.copy();
             (*se.elements)[i] = result;
index ddfee2ccab0516e4eeae2a9e38f268e58ef3c5f9..357f7bdcd9fda4b400093d54997cfd9a7dfbbcdb 100644 (file)
@@ -16,7 +16,7 @@ import core.stdc.string;
 import dmd.doc;
 import dmd.errors;
 import dmd.globals;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 
 extern (C++) struct MacroTable
index 71b8c7a609897c6099ae79da7405fd47485ab8e6..c417f93c353b9dd2c71a658359aff4b6c0dea3bf 100644 (file)
@@ -139,7 +139,7 @@ import dmd.id;
 import dmd.identifier;
 import dmd.mtype;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.aav;
 import dmd.root.string;
 import dmd.root.stringtable;
@@ -1259,14 +1259,49 @@ public:
 
     override void visit(Parameter p)
     {
-        if (p.storageClass & STC.scope_ && !(p.storageClass & STC.scopeinferred))
-            buf.writeByte('M');
+        // https://dlang.org/spec/abi.html#Parameter
+
+        auto stc = p.storageClass;
+
+        // Inferred storage classes don't get mangled in
+        if (stc & STC.scopeinferred)
+            stc &= ~(STC.scope_ | STC.scopeinferred);
+        if (stc & STC.returninferred)
+            stc &= ~(STC.return_ | STC.returninferred);
 
         // 'return inout ref' is the same as 'inout ref'
-        if ((p.storageClass & (STC.return_ | STC.wild)) == STC.return_ &&
-            !(p.storageClass & STC.returninferred))
-            buf.writestring("Nk");
-        switch (p.storageClass & (STC.IOR | STC.lazy_))
+        if ((stc & (STC.return_ | STC.wild)) == (STC.return_ | STC.wild))
+            stc &= ~STC.return_;
+
+        // much like hdrgen.stcToBuffer()
+        string rrs;
+        const isout = (stc & STC.out_) != 0;
+        final switch (buildScopeRef(stc))
+        {
+            case ScopeRef.None:
+            case ScopeRef.Scope:
+            case ScopeRef.Ref:
+            case ScopeRef.Return:
+            case ScopeRef.RefScope:
+                break;
+
+            case ScopeRef.ReturnScope:     rrs = "NkM";                  goto L1;  // return scope
+            case ScopeRef.ReturnRef:       rrs = isout ? "NkJ"  : "NkK"; goto L1;  // return ref
+            case ScopeRef.ReturnRef_Scope: rrs = isout ? "MNkJ" : "MNkK"; goto L1; // scope return ref
+            case ScopeRef.Ref_ReturnScope: rrs = isout ? "NkMJ" : "NkMK"; goto L1; // return scope ref
+            L1:
+                buf.writestring(rrs);
+                stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_);
+                break;
+        }
+
+        if (stc & STC.scope_)
+            buf.writeByte('M');  // scope
+
+        if (stc & STC.return_)
+            buf.writestring("Nk"); // return
+
+        switch (stc & (STC.IOR | STC.lazy_))
         {
         case 0:
             break;
@@ -1288,10 +1323,10 @@ public:
         default:
             debug
             {
-                printf("storageClass = x%llx\n", p.storageClass & (STC.IOR | STC.lazy_));
+                printf("storageClass = x%llx\n", stc & (STC.IOR | STC.lazy_));
             }
             assert(0);
         }
-        visitWithMask(p.type, (p.storageClass & STC.in_) ? MODFlags.const_ : 0);
+        visitWithMask(p.type, (stc & STC.in_) ? MODFlags.const_ : 0);
     }
 }
index 768eaa05a08e2fa0344affdcca15e8726bd940cf..4e0071304e4dd590e76f20733986e0f821355e4c 100644 (file)
@@ -31,6 +31,7 @@ import dmd.dsymbolsem;
 import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
+import dmd.file_manager;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
@@ -39,7 +40,7 @@ import dmd.cparse;
 import dmd.root.array;
 import dmd.root.file;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.port;
 import dmd.root.rmem;
 import dmd.root.rootobject;
@@ -50,113 +51,6 @@ import dmd.target;
 import dmd.utils;
 import dmd.visitor;
 
-enum package_d  = "package." ~ mars_ext;
-enum package_di = "package." ~ hdr_ext;
-
-/********************************************
- * Look for the source file if it's different from filename.
- * Look for .di, .d, directory, and along global.path.
- * Does not open the file.
- * Params:
- *      filename = as supplied by the user
- *      path = path to look for filename
- * Returns:
- *      the found file name or
- *      `null` if it is not different from filename.
- */
-private const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
-{
-    //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
-    /* Search along path[] for .di file, then .d file, then .i file, then .c file.
-     */
-    const sdi = FileName.forceExt(filename, hdr_ext);
-    if (FileName.exists(sdi) == 1)
-        return sdi;
-    scope(exit) FileName.free(sdi.ptr);
-
-    const sd = FileName.forceExt(filename, mars_ext);
-    if (FileName.exists(sd) == 1)
-        return sd;
-    scope(exit) FileName.free(sd.ptr);
-
-    const si = FileName.forceExt(filename, i_ext);
-    if (FileName.exists(si) == 1)
-        return si;
-    scope(exit) FileName.free(si.ptr);
-
-    const sc = FileName.forceExt(filename, c_ext);
-    if (FileName.exists(sc) == 1)
-        return sc;
-    scope(exit) FileName.free(sc.ptr);
-
-    if (FileName.exists(filename) == 2)
-    {
-        /* The filename exists and it's a directory.
-         * Therefore, the result should be: filename/package.d
-         * iff filename/package.d is a file
-         */
-        const ni = FileName.combine(filename, package_di);
-        if (FileName.exists(ni) == 1)
-            return ni;
-        FileName.free(ni.ptr);
-
-        const n = FileName.combine(filename, package_d);
-        if (FileName.exists(n) == 1)
-            return n;
-        FileName.free(n.ptr);
-    }
-    if (FileName.absolute(filename))
-        return null;
-    if (!path.length)
-        return null;
-    foreach (entry; path)
-    {
-        const p = entry.toDString();
-
-        const(char)[] n = FileName.combine(p, sdi);
-        if (FileName.exists(n) == 1) {
-            return n;
-        }
-        FileName.free(n.ptr);
-
-        n = FileName.combine(p, sd);
-        if (FileName.exists(n) == 1) {
-            return n;
-        }
-        FileName.free(n.ptr);
-
-        n = FileName.combine(p, si);
-        if (FileName.exists(n) == 1) {
-            return n;
-        }
-        FileName.free(n.ptr);
-
-        n = FileName.combine(p, sc);
-        if (FileName.exists(n) == 1) {
-            return n;
-        }
-        FileName.free(n.ptr);
-
-        const b = FileName.removeExt(filename);
-        n = FileName.combine(p, b);
-        FileName.free(b.ptr);
-        if (FileName.exists(n) == 2)
-        {
-            const n2i = FileName.combine(n, package_di);
-            if (FileName.exists(n2i) == 1)
-                return n2i;
-            FileName.free(n2i.ptr);
-            const n2 = FileName.combine(n, package_d);
-            if (FileName.exists(n2) == 1) {
-                return n2;
-            }
-            FileName.free(n2.ptr);
-        }
-        FileName.free(n.ptr);
-    }
-    return null;
-}
-
 // function used to call semantic3 on a module's dependencies
 void semantic3OnDependencies(Module m)
 {
@@ -414,8 +308,8 @@ extern (C++) class Package : ScopeDsymbol
             packages ~= s.ident;
         reverse(packages);
 
-        if (lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
-            Module.load(Loc(), packages, this.ident);
+        if (FileManager.lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
+            Module.load(Loc.initial, packages, this.ident);
         else
             isPkgMod = PKG.package_;
     }
@@ -598,12 +492,12 @@ extern (C++) final class Module : Package
         return new Module(Loc.initial, filename, ident, doDocComment, doHdrGen);
     }
 
-    extern (C++) static Module load(Loc loc, Identifiers* packages, Identifier ident)
+    extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
     {
         return load(loc, packages ? (*packages)[] : null, ident);
     }
 
-    extern (D) static Module load(Loc loc, Identifier[] packages, Identifier ident)
+    extern (D) static Module load(const ref Loc loc, Identifier[] packages, Identifier ident)
     {
         //printf("Module::load(ident = '%s')\n", ident.toChars());
         // Build module filename by turning:
@@ -612,7 +506,7 @@ extern (C++) final class Module : Package
         //  foo\bar\baz
         const(char)[] filename = getFilename(packages, ident);
         // Look for the source file
-        if (const result = lookForSourceFile(filename, global.path ? (*global.path)[] : null))
+        if (const result = FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null))
             filename = result; // leaks
 
         auto m = new Module(loc, filename, ident, 0, 0);
@@ -737,7 +631,12 @@ extern (C++) final class Module : Package
             if (isPackageMod)
                 .error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars());
             else
-                error(loc, "is in file '%s' which cannot be read", srcfile.toChars());
+            {
+                .error(loc, "unable to read module `%s`", toChars());
+                const pkgfile = FileName.combine(FileName.removeExt(srcfile.toString()), package_d);
+                .errorSupplemental(loc, "Expected '%s' or '%s' in one of the following import paths:",
+                    srcfile.toChars(), pkgfile.ptr);
+            }
         }
         if (!global.gag)
         {
@@ -776,14 +675,25 @@ extern (C++) final class Module : Package
             return true; // already read
 
         //printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
-        auto readResult = File.read(srcfile.toChars());
 
         if (global.params.emitMakeDeps)
         {
             global.params.makeDeps.push(srcfile.toChars());
         }
 
-        return loadSourceBuffer(loc, readResult);
+        if (auto readResult = FileManager.fileManager.lookup(srcfile))
+        {
+            srcBuffer = readResult;
+            return true;
+        }
+
+        auto readResult = File.read(srcfile.toChars());
+        if (loadSourceBuffer(loc, readResult))
+        {
+            FileManager.fileManager.add(srcfile, srcBuffer);
+            return true;
+        }
+        return false;
     }
 
     /// syntactic parse
index 9b4329b8b0a4afcb9e6c57f21c8d7e8de62a1b1b..f9b765c521cb945169d1efe8581107d9a1ca6cf8 100644 (file)
@@ -45,7 +45,7 @@ import dmd.mtype;
 import dmd.root.array;
 import dmd.root.file;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.port;
 import dmd.root.rmem;
 import dmd.root.string;
@@ -3995,8 +3995,8 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r
     const iDelimiterRowEnd = parseTableDelimiterRow(buf, iEnd + 1, inQuote, columnAlignments);
     if (iDelimiterRowEnd)
     {
-        const delta = replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, true);
-        if (delta)
+        size_t delta;
+        if (replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, true, delta))
         {
             buf.remove(iEnd + delta, iDelimiterRowEnd - iEnd);
             buf.insert(iEnd + delta, "$(TBODY ");
@@ -4023,12 +4023,15 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r
  *  headerRow = if `true` then the number of columns will be enforced to match
  *              `columnAlignments.length` and the row will be surrounded by a
  *              `THEAD` macro
- * Returns: the number of characters added by replacing the row, or `0` if unchanged
+ *  delta     = the number of characters added by replacing the row, or `0` if unchanged
+ * Returns: `true` if a table row was found and replaced
  */
-private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow)
+private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta)
 {
+    delta = 0;
+
     if (!columnAlignments.length || iStart == iEnd)
-        return 0;
+        return false;
 
     iStart = skipChars(buf, iStart, " \t");
     int cellCount = 0;
@@ -4045,7 +4048,7 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
         ++cellCount;
 
     if (headerRow && cellCount != columnAlignments.length)
-        return 0;
+        return false;
 
     if (headerRow && global.params.vmarkdown)
     {
@@ -4053,8 +4056,6 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
         message(loc, "Ddoc: formatting table '%.*s'", cast(int)s.length, s.ptr);
     }
 
-    size_t delta = 0;
-
     void replaceTableCell(size_t iCellStart, size_t iCellEnd, int cellIndex, int di)
     {
         const eDelta = replaceMarkdownEmphasis(buf, loc, inlineDelimiters, di);
@@ -4146,7 +4147,7 @@ private size_t replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, co
         delta += 9;
     }
 
-    return delta;
+    return true;
 }
 
 /****************************************************
@@ -4182,7 +4183,8 @@ private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[]
  */
 private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments)
 {
-    size_t delta = replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false);
+    size_t delta;
+    replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false, delta);
     delta += endTable(buf, iEnd + delta, columnAlignments);
     return delta;
 }
@@ -4263,8 +4265,8 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
                 i += startTable(buf, iLineStart, i, loc, lineQuoted, inlineDelimiters, columnAlignments);
             else if (columnAlignments.length)
             {
-                const delta = replaceTableRow(buf, iLineStart, i, loc, inlineDelimiters, columnAlignments, false);
-                if (delta)
+                size_t delta;
+                if (replaceTableRow(buf, iLineStart, i, loc, inlineDelimiters, columnAlignments, false, delta))
                     i += delta;
                 else
                     i += endTable(buf, i, columnAlignments);
index 638fc7e52957898a1b276554386d953607aed955..42c0d18b2dbe0db06e2c1b08aecc26c0ab52cf9b 100644 (file)
@@ -33,7 +33,7 @@ import dmd.func;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.speller;
 import dmd.statement;
@@ -730,12 +730,21 @@ struct Scope
         }
     }
 
+    /******************************
+     */
     structalign_t alignment()
     {
         if (aligndecl)
-            return aligndecl.getAlignment(&this);
+        {
+            auto ad = aligndecl.getAlignment(&this);
+            return ad.salign;
+        }
         else
-            return STRUCTALIGN_DEFAULT;
+        {
+            structalign_t sa;
+            sa.setDefault();
+            return sa;
+        }
     }
 
     /**********************************
index 80ecd3611358ff3a6efd26ee88b6368e61a0da41..0925e7cd38a2d1510a9d05599e9ee26d1a68f7c0 100644 (file)
@@ -16,6 +16,7 @@ module dmd.dstruct;
 import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
+import dmd.attrib;
 import dmd.declaration;
 import dmd.dmodule;
 import dmd.dscope;
@@ -127,7 +128,7 @@ extern (C++) void semanticTypeInfo(Scope* sc, Type t)
          */
         if (!sd.members)
             return; // opaque struct
-        if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.dtor && !sd.xhash && !search_toString(sd))
+        if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.tidtor && !sd.xhash && !search_toString(sd))
             return; // none of TypeInfo-specific members
 
         // If the struct is in a non-root module, run semantic3 to get
@@ -232,7 +233,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
         }
     }
 
-    static StructDeclaration create(Loc loc, Identifier id, bool inObject)
+    static StructDeclaration create(const ref Loc loc, Identifier id, bool inObject)
     {
         return new StructDeclaration(loc, id, inObject);
     }
@@ -297,22 +298,46 @@ extern (C++) class StructDeclaration : AggregateDeclaration
             return;
         }
 
-        // 0 sized struct's are set to 1 byte
         if (structsize == 0)
         {
             hasNoFields = true;
             alignsize = 1;
-            if (classKind != classKind.c) // C gets a struct size of 0
-                structsize = 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 if (target.c.bitFieldStyle == TargetC.BitFieldStyle.DM)
+                    {
+                        structsize = 0;
+                        alignsize = 0;
+                    }
+                    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 == STRUCTALIGN_DEFAULT)
+        if (alignment.isDefault() || alignment.isPack())
             structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
         else
-            structsize = (structsize + alignment - 1) & ~(alignment - 1);
+            structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1);
 
         sizeok = Sizeok.done;
 
index 3a6dff2d44fb45fafd6416d0302743028893fce3..9aa435d646381eea4c2ad874ebe247d9e107eda2 100644 (file)
@@ -187,7 +187,7 @@ struct Visibility
     }
 }
 
-enum PASS : int
+enum PASS : ubyte
 {
     init,           // initial state
     semantic,       // semantic() started
@@ -225,11 +225,13 @@ enum : int
  */
 struct FieldState
 {
-    uint offset;        /// offset for next field
+    uint offset;        /// byte offset for next field
 
-    uint fieldOffset;   /// offset for the start of the bit field
+    uint fieldOffset;   /// byte offset for the start of the bit field
+    uint fieldSize;     /// byte size of field
+    uint fieldAlign;    /// byte alignment of field
     uint bitOffset;     /// bit offset for field
-    uint fieldSize;     /// size of field in bytes
+
     bool inFlight;      /// bit field is in flight
 }
 
@@ -793,10 +795,18 @@ extern (C++) class Dsymbol : ASTNode
             Dsymbol s2 = sds.symtabLookup(this,ident);
 
             // If using C tag/prototype/forward declaration rules
-            if (sc.flags & SCOPE.Cfile &&
-                handleTagSymbols(*sc, this, s2, sds))
+            if (sc.flags & SCOPE.Cfile)
+            {
+                if (handleTagSymbols(*sc, this, s2, sds))
+                    return;
+                if (handleSymbolRedeclarations(*sc, this, s2, sds))
                     return;
 
+                sds.multiplyDefined(Loc.initial, this, s2);  // ImportC doesn't allow overloading
+                errors = true;
+                return;
+            }
+
             if (!s2.overloadInsert(this))
             {
                 sds.multiplyDefined(Loc.initial, this, s2);
@@ -2384,3 +2394,91 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
 }
 
 
+/**********************************************
+ * ImportC allows redeclarations of C variables, functions and typedefs.
+ *    extern int x;
+ *    int x = 3;
+ * and:
+ *    extern void f();
+ *    void f() { }
+ * Attempt to merge them.
+ * Params:
+ *      sc = context
+ *      s = symbol to add to symbol table
+ *      s2 = existing declaration
+ *      sds = symbol table
+ * Returns:
+ *      if s and s2 are successfully put in symbol table then return the merged symbol,
+ *      null if they conflict
+ */
+Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
+{
+    enum log = false;
+    if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
+
+    static Dsymbol collision()
+    {
+        if (log) printf(" collision\n");
+        return null;
+    }
+
+    auto vd = s.isVarDeclaration(); // new declaration
+    auto vd2 = s2.isVarDeclaration(); // existing declaration
+    if (vd && vd2)
+    {
+        // if one is `static` and the other isn't
+        if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
+            return collision();
+
+        const i1 =  vd._init && ! vd._init.isVoidInitializer();
+        const i2 = vd2._init && !vd2._init.isVoidInitializer();
+
+        if (i1 && i2)
+            return collision();         // can't both have initializers
+
+        if (i1)
+            return vd;
+
+        /* BUG: the types should match, which needs semantic() to be run on it
+         *    extern int x;
+         *    int x;  // match
+         *    typedef int INT;
+         *    INT x;  // match
+         *    long x; // collision
+         * We incorrectly ignore these collisions
+         */
+        return vd2;
+    }
+
+    auto fd = s.isFuncDeclaration(); // new declaration
+    auto fd2 = s2.isFuncDeclaration(); // existing declaration
+    if (fd && fd2)
+    {
+        // if one is `static` and the other isn't
+        if ((fd.storage_class ^ fd2.storage_class) & STC.static_)
+            return collision();
+
+        if (fd.fbody && fd2.fbody)
+            return collision();         // can't both have bodies
+
+        if (fd.fbody)
+            return fd;
+
+        /* BUG: just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
+         * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+         */
+        return fd2;
+    }
+
+    auto td  = s.isAliasDeclaration();  // new declaration
+    auto td2 = s2.isAliasDeclaration(); // existing declaration
+    if (td && td2)
+    {
+        /* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
+         * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+         */
+        return td2;
+    }
+
+    return collision();
+}
index f43bc83799264decd6580602be3a4dece53e1a7e..02252fd13e590eaf7f2ad453604256b1e81b86bb 100644 (file)
@@ -108,7 +108,21 @@ struct Visibility
 
 /* State of symbol in winding its way through the passes of the compiler
  */
-enum PASS
+enum class PASS : uint8_t
+{
+    init,           // initial state
+    semantic,       // semantic() started
+    semanticdone,   // semantic() done
+    semantic2,      // semantic2() started
+    semantic2done,  // semantic2() done
+    semantic3,      // semantic3() started
+    semantic3done,  // semantic3() done
+    inline_,         // inline started
+    inlinedone,     // inline done
+    obj             // toObjFile() run
+};
+
+enum
 {
     PASSinit,           // initial state
     PASSsemantic,       // semantic() started
@@ -145,8 +159,10 @@ struct FieldState
     unsigned offset;
 
     unsigned fieldOffset;
+    unsigned fieldSize;
+    unsigned fieldAlign;
     unsigned bitOffset;
-    unsigned fieldSice;
+
     bool inFlight;
 };
 
index eac20952eb5504ae6b3b63fbe30ab475f55c8170..047c1eb6f69ffdadc54e994915050b58b013948b 100644 (file)
@@ -56,7 +56,7 @@ import dmd.objc;
 import dmd.opover;
 import dmd.parse;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.semantic2;
@@ -109,17 +109,18 @@ extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
  *      ad = AlignmentDeclaration
  *      sc = context
  * Returns:
- *      alignment as numerical value that is never 0.
- *      STRUCTALIGN_DEFAULT is used instead.
- *      STRUCTALIGN_DEFAULT is returned for errors
+ *      ad with alignment value determined
  */
-structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
+AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
 {
-    if (ad.salign != ad.UNKNOWN)   // UNKNOWN is 0
-        return ad.salign;
+    if (!ad.salign.isUnknown())   // UNKNOWN is 0
+        return ad;
 
     if (!ad.exps)
-        return ad.salign = STRUCTALIGN_DEFAULT;
+    {
+        ad.salign.setDefault();
+        return ad;
+    }
 
     dinteger_t strictest = 0;   // strictest alignment
     bool errors;
@@ -140,7 +141,7 @@ structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
             if (sc.flags & SCOPE.Cfile && n == 0)       // C11 6.7.5-6 allows 0 for alignment
                 continue;
 
-            if (n < 1 || n & (n - 1) || structalign_t.max < n || !e.type.isintegral())
+            if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
             {
                 error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
                 errors = true;
@@ -150,10 +151,12 @@ structalign_t getAlignment(AlignDeclaration ad, Scope* sc)
         }
     }
 
-    ad.salign = (errors || strictest == 0)  // C11 6.7.5-6 says alignment of 0 means no effect
-                ? STRUCTALIGN_DEFAULT
-                : cast(structalign_t) strictest;
-    return ad.salign;
+    if (errors || strictest == 0)  // C11 6.7.5-6 says alignment of 0 means no effect
+        ad.salign.setDefault();
+    else
+        ad.salign.set(cast(uint) strictest);
+
+    return ad;
 }
 
 const(char)* getMessage(DeprecatedDeclaration dd)
@@ -365,16 +368,31 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         dsym.semanticRun = PASS.semantic;
 
-        /* Pick up storage classes from context, but except synchronized,
-         * override, abstract, and final.
-         */
-        dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
+        // 'static foreach' variables should not inherit scope properties
+        // https://issues.dlang.org/show_bug.cgi?id=19482
+        if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
+        {
+            dsym.linkage = LINK.d;
+            dsym.visibility = Visibility(Visibility.Kind.public_);
+            dsym.overlapped = false; // unset because it is modified early on this function
+            dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
+        }
+        else
+        {
+            /* Pick up storage classes from context, but except synchronized,
+             * override, abstract, and final.
+             */
+            dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
+            dsym.userAttribDecl = sc.userAttribDecl;
+            dsym.cppnamespace = sc.namespace;
+            dsym.linkage = sc.linkage;
+            dsym.visibility = sc.visibility;
+            dsym.alignment = sc.alignment();
+        }
+
         if (dsym.storage_class & STC.extern_ && dsym._init)
             dsym.error("extern symbols cannot have initializers");
 
-        dsym.userAttribDecl = sc.userAttribDecl;
-        dsym.cppnamespace = sc.namespace;
-
         AggregateDeclaration ad = dsym.isThis();
         if (ad)
             dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
@@ -431,16 +449,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             dsym.errors = true;
 
         dsym.type.checkDeprecated(dsym.loc, sc);
-        dsym.linkage = sc.linkage;
         dsym.parent = sc.parent;
         //printf("this = %p, parent = %p, '%s'\n", dsym, dsym.parent, dsym.parent.toChars());
-        dsym.visibility = sc.visibility;
 
         /* If scope's alignment is the default, use the type's alignment,
          * otherwise the scope overrrides.
          */
-        dsym.alignment = sc.alignment();
-        if (dsym.alignment == STRUCTALIGN_DEFAULT)
+        if (dsym.alignment.isDefault())
             dsym.alignment = dsym.type.alignment(); // use type's alignment
 
         //printf("sc.stc = %x\n", sc.stc);
@@ -935,6 +950,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             sc = sc.push();
             sc.stc &= ~(STC.TYPECTOR | STC.pure_ | STC.nothrow_ | STC.nogc | STC.ref_ | STC.disable);
 
+            if (sc.flags & SCOPE.Cfile &&
+                dsym.type.isTypeSArray() &&
+                dsym.type.isTypeSArray().isIncomplete() &&
+                dsym._init.isVoidInitializer() &&
+                !(dsym.storage_class & STC.field))
+            {
+                dsym.error("incomplete array type must have initializer");
+            }
+
             ExpInitializer ei = dsym._init.isExpInitializer();
 
             if (ei) // https://issues.dlang.org/show_bug.cgi?id=13424
@@ -971,6 +995,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         ei = new ExpInitializer(dsym._init.loc, e);
                         dsym._init = ei;
                     }
+                    else if (sc.flags & SCOPE.Cfile && dsym.type.isTypeSArray() &&
+                             dsym.type.isTypeSArray().isIncomplete())
+                    {
+                        // C11 6.7.9-22 determine the size of the incomplete array,
+                        // or issue an error that the initializer is invalid.
+                        dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
+                    }
 
                     Expression exp = ei.exp;
                     Expression e1 = new VarExp(dsym.loc, dsym);
@@ -1056,18 +1087,29 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     // could crash (inf. recursion) on a mod/pkg referencing itself
                     if (ei && (ei.exp.op != TOK.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
                     {
-                        Expression exp = ei.exp.syntaxCopy();
-
-                        bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
-                        if (needctfe)
-                            sc = sc.startCTFE();
-                        exp = exp.expressionSemantic(sc);
-                        exp = resolveProperties(sc, exp);
-                        if (needctfe)
-                            sc = sc.endCTFE();
+                        if (ei.exp.type)
+                        {
+                            // If exp is already resolved we are done, our original init exp
+                            // could have a type painting that we need to respect
+                            // e.g.  ['a'] typed as string, or [['z'], ""] as string[]
+                            // See https://issues.dlang.org/show_bug.cgi?id=15711
+                        }
+                        else
+                        {
+                            Expression exp = ei.exp.syntaxCopy();
+
+                            bool needctfe = dsym.isDataseg() || (dsym.storage_class & STC.manifest);
+                            if (needctfe)
+                                sc = sc.startCTFE();
+                            exp = exp.expressionSemantic(sc);
+                            exp = resolveProperties(sc, exp);
+                            if (needctfe)
+                                sc = sc.endCTFE();
+                            ei.exp = exp;
+                        }
 
                         Type tb2 = dsym.type.toBasetype();
-                        Type ti = exp.type.toBasetype();
+                        Type ti = ei.exp.type.toBasetype();
 
                         /* The problem is the following code:
                          *  struct CopyTest {
@@ -1091,11 +1133,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             if (sd.postblit && tb2.toDsymbol(null) == sd)
                             {
                                 // The only allowable initializer is a (non-copy) constructor
-                                if (exp.isLvalue())
+                                if (ei.exp.isLvalue())
                                     dsym.error("of type struct `%s` uses `this(this)`, which is not allowed in static initialization", tb2.toChars());
                             }
                         }
-                        ei.exp = exp;
                     }
 
                     dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITinterpret);
@@ -1708,6 +1749,36 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             if (pd.args && pd.args.dim != 0)
                 pd.error("takes no argument");
+            else
+            {
+                immutable isCtor = pd.ident == Id.crt_constructor;
+
+                static uint recurse(Dsymbol s, bool isCtor)
+                {
+                    if (auto ad = s.isAttribDeclaration())
+                    {
+                        uint nestedCount;
+                        auto decls = ad.include(null);
+                        if (decls)
+                        {
+                            for (size_t i = 0; i < decls.dim; ++i)
+                                nestedCount += recurse((*decls)[i], isCtor);
+                        }
+                        return nestedCount;
+                    }
+                    else if (auto f = s.isFuncDeclaration())
+                    {
+                        f.isCrtCtorDtor |= isCtor ? 1 : 2;
+                        return 1;
+                    }
+                    else
+                        return 0;
+                    assert(0);
+                }
+
+                if (recurse(pd, isCtor) > 1)
+                    pd.error("can only apply to a single declaration");
+            }
             return declarations();
         }
         else if (pd.ident == Id.printf || pd.ident == Id.scanf)
@@ -2445,6 +2516,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         tempdecl.parent = sc.parent;
         tempdecl.visibility = sc.visibility;
+        tempdecl.userAttribDecl = sc.userAttribDecl;
         tempdecl.cppnamespace = sc.namespace;
         tempdecl.isstatic = tempdecl.toParent().isModule() || (tempdecl._scope.stc & STC.static_);
         tempdecl.deprecated_ = !!(sc.stc & STC.deprecated_);
@@ -2973,6 +3045,16 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (auto pragmadecl = sc.inlining)
             funcdecl.inlining = pragmadecl.evalPragmaInline(sc);
 
+        // check pragma(crt_constructor)
+        if (funcdecl.isCrtCtorDtor)
+        {
+            if (funcdecl.linkage != LINK.c)
+            {
+                funcdecl.error("must be `extern(C)` for `pragma(%s)`",
+                    funcdecl.isCrtCtorDtor == 1 ? "crt_constructor".ptr : "crt_destructor".ptr);
+            }
+        }
+
         funcdecl.visibility = sc.visibility;
         funcdecl.userAttribDecl = sc.userAttribDecl;
         UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl.linkage);
@@ -3799,6 +3881,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
         }
 
+        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
@@ -3995,7 +4081,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             return;
         }
         if (dd.ident == Id.dtor && dd.semanticRun < PASS.semantic)
-            ad.dtors.push(dd);
+            ad.userDtors.push(dd);
         if (!dd.type)
         {
             dd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, dd.storage_class);
@@ -4417,8 +4503,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         // Look for the constructor
         sd.ctor = sd.searchCtor();
 
-        sd.dtor = buildDtor(sd, sc2);
-        sd.tidtor = buildExternDDtor(sd, sc2);
+        buildDtors(sd, sc2);
+
         sd.hasCopyCtor = buildCopyCtor(sd, sc2);
         sd.postblit = buildPostBlit(sd, sc2);
 
@@ -5057,8 +5143,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
         }
 
-        cldec.dtor = buildDtor(cldec, sc2);
-        cldec.tidtor = buildExternDDtor(cldec, sc2);
+        buildDtors(cldec, sc2);
 
         if (cldec.classKind == ClassKind.cpp && cldec.cppDtorVtblIndex != -1)
         {
index c3503bbf7d6a91a08897bfe867df5ed330ea421a..9d7957a975d3a18a8dbca03dd7371ebfcce6867c 100644 (file)
@@ -67,7 +67,7 @@ import dmd.initsem;
 import dmd.mtype;
 import dmd.opover;
 import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.semantic2;
 import dmd.semantic3;
@@ -985,9 +985,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                 buf.writenl();
                 buf.writestring("       ");
             }
-            buf.write((*parameters)[i]);
+            write(buf, (*parameters)[i]);
             buf.writestring(" = ");
-            buf.write(tiargs[i]);
+            write(buf, tiargs[i]);
         }
         // write remaining variadic arguments on the last line
         if (variadic)
@@ -998,16 +998,16 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                 buf.writenl();
                 buf.writestring("       ");
             }
-            buf.write((*parameters)[end]);
+            write(buf, (*parameters)[end]);
             buf.writestring(" = ");
             buf.writeByte('(');
             if (cast(int)tiargs.length - end > 0)
             {
-                buf.write(tiargs[end]);
+                write(buf, tiargs[end]);
                 foreach (j; parameters.length .. tiargs.length)
                 {
                     buf.writestring(", ");
-                    buf.write(tiargs[j]);
+                    write(buf, tiargs[j]);
                 }
             }
             buf.writeByte(')');
@@ -1919,8 +1919,15 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                             /* If a semantic error occurs while doing alias this,
                              * eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
                              * just regard it as not a match.
-                             */
-                            if (auto e = resolveAliasThis(sc, farg, true))
+                             *
+                             * We also save/restore sc.func.flags to avoid messing up
+                             * attribute inference in the evaluation.
+                            */
+                            const oldflags = sc.func ? sc.func.flags : 0;
+                            auto e = resolveAliasThis(sc, farg, true);
+                            if (sc.func)
+                                sc.func.flags = oldflags;
+                            if (e)
                             {
                                 farg = e;
                                 goto Lretry;
@@ -5340,7 +5347,7 @@ extern (C++) class TemplateParameter : ASTNode
 
     abstract RootObject specialization();
 
-    abstract RootObject defaultArg(Loc instLoc, Scope* sc);
+    abstract RootObject defaultArg(const ref Loc instLoc, Scope* sc);
 
     abstract bool hasDefaultArg();
 
@@ -5422,7 +5429,7 @@ extern (C++) class TemplateTypeParameter : TemplateParameter
         return specType;
     }
 
-    override final RootObject defaultArg(Loc instLoc, Scope* sc)
+    override final RootObject defaultArg(const ref Loc instLoc, Scope* sc)
     {
         Type t = defaultType;
         if (t)
@@ -5541,7 +5548,7 @@ extern (C++) final class TemplateValueParameter : TemplateParameter
         return specValue;
     }
 
-    override RootObject defaultArg(Loc instLoc, Scope* sc)
+    override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
     {
         Expression e = defaultValue;
         if (e)
@@ -5640,7 +5647,7 @@ extern (C++) final class TemplateAliasParameter : TemplateParameter
         return specAlias;
     }
 
-    override RootObject defaultArg(Loc instLoc, Scope* sc)
+    override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
     {
         RootObject da = defaultAlias;
         Type ta = isType(defaultAlias);
@@ -5741,7 +5748,7 @@ extern (C++) final class TemplateTupleParameter : TemplateParameter
         return null;
     }
 
-    override RootObject defaultArg(Loc instLoc, Scope* sc)
+    override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
     {
         return null;
     }
@@ -8413,3 +8420,11 @@ private struct MATCHpair
         this.mfa = mfa;
     }
 }
+
+private void write(ref OutBuffer buf, RootObject obj)
+{
+    if (obj)
+    {
+        buf.writestring(obj.toChars());
+    }
+}
index 28054d02904484834c17982190ecf8d4f016f6f2..e19adfc4b149729bc976b21cf4f042c862d0d27d 100644 (file)
@@ -17,6 +17,7 @@ import core.stdc.ctype;
 
 import dmd.astcodegen;
 import dmd.arraytypes;
+import dmd.attrib;
 import dmd.dsymbol;
 import dmd.errors;
 import dmd.globals;
@@ -25,7 +26,7 @@ import dmd.root.filename;
 import dmd.visitor;
 import dmd.tokens;
 
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.utils;
 
 //debug = Debug_DtoH;
@@ -254,7 +255,7 @@ public:
         Identifier ident;
 
         /// Original type of the currently visited declaration
-        AST.Type* origType;
+        AST.Type origType;
 
         /// Last written visibility level applying to the current scope
         AST.Visibility.Kind currentVisibility;
@@ -706,6 +707,10 @@ public:
         // printf("FuncDeclaration %s %s\n", fd.toPrettyChars(), fd.type.toChars());
         visited[cast(void*)fd] = true;
 
+        // silently ignore non-user-defined destructors
+        if (fd.generated && fd.isDtorDeclaration())
+            return;
+
         // Note that tf might be null for templated (member) functions
         auto tf = cast(AST.TypeFunction)fd.type;
         if ((tf && tf.linkage != LINK.c && tf.linkage != LINK.cpp) || (!tf && fd.isPostBlitDeclaration()))
@@ -841,12 +846,12 @@ public:
             return;
 
         if (vd.originalType && vd.type == AST.Type.tsize_t)
-            origType = &vd.originalType;
+            origType = vd.originalType;
         scope(exit) origType = null;
 
-        if (vd.alignment != STRUCTALIGN_DEFAULT)
+        if (!vd.alignment.isDefault())
         {
-            buf.printf("// Ignoring var %s alignment %u", vd.toChars(), vd.alignment);
+            buf.printf("// Ignoring var %s alignment %d", vd.toChars(), vd.alignment.get());
             buf.writenl();
         }
 
@@ -1008,12 +1013,12 @@ public:
             if (ad.originalType && ad.type.ty == AST.Tpointer &&
                 (cast(AST.TypePointer)t).nextOf.ty == AST.Tfunction)
             {
-                origType = &ad.originalType;
+                origType = ad.originalType;
             }
             scope(exit) origType = null;
 
             buf.writestring("typedef ");
-            typeToBuffer(origType ? *origType : t, ad);
+            typeToBuffer(origType !is null ? origType : t, ad);
             writeDeclEnd();
             return;
         }
@@ -1346,7 +1351,7 @@ public:
 
     /// Starts a custom alignment section using `#pragma pack` if
     /// `alignment` specifies a custom alignment
-    private void pushAlignToBuffer(uint alignment)
+    private void pushAlignToBuffer(structalign_t alignment)
     {
         // DMD ensures alignment is a power of two
         //assert(alignment > 0 && ((alignment & (alignment - 1)) == 0),
@@ -1354,20 +1359,20 @@ public:
 
         // When no alignment is specified, `uint.max` is the default
         // FIXME: alignment is 0 for structs templated members
-        if (alignment == STRUCTALIGN_DEFAULT || (tdparent && alignment == 0))
+        if (alignment.isDefault() || (tdparent && alignment.isUnknown()))
         {
             return;
         }
 
-        buf.printf("#pragma pack(push, %d)", alignment);
+        buf.printf("#pragma pack(push, %d)", alignment.get());
         buf.writenl();
     }
 
     /// Ends a custom alignment section using `#pragma pack` if
     /// `alignment` specifies a custom alignment
-    private void popAlignToBuffer(uint alignment)
+    private void popAlignToBuffer(structalign_t alignment)
     {
-        if (alignment == STRUCTALIGN_DEFAULT || (tdparent && alignment == 0))
+        if (alignment.isDefault() || (tdparent && alignment.isUnknown()))
             return;
 
         buf.writestringln("#pragma pack(pop)");
@@ -1645,7 +1650,7 @@ public:
         }
 
         this.ident = s.ident;
-        auto type = origType ? *origType : t;
+        auto type = origType !is null ? origType : t;
         AST.Dsymbol customLength;
 
         // Check for quirks that are usually resolved during semantic
index 0dff754bee55e1495cb4993d69067709ba9a1600..49ee4b3b3ecc1a8d7011b9e444438fde3326b69d 100644 (file)
@@ -22,7 +22,7 @@ import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.globals;
 import dmd.identifier;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.visitor;
 
 /***********************************************************
index 0d6fa1e88f37c56395a06ee64126c21010e2f240..2a6233244547a5f5a178695e3b0c52ced8992f71 100644 (file)
@@ -59,7 +59,7 @@ import dmd.opover;
 import dmd.optimize;
 import dmd.root.ctfloat;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.root.string;
@@ -1201,20 +1201,14 @@ extern (C++) abstract class Expression : ASTNode
         // DtorDeclaration without parents should fail at an earlier stage
         auto ad = cast(AggregateDeclaration) f.toParent2();
         assert(ad);
-        assert(ad.dtors.length);
 
-        // Search for the user-defined destructor (if any)
-        foreach(dtor; ad.dtors)
+        if (ad.userDtors.dim)
         {
-            if (dtor.generated)
-                continue;
-
-            if (!check(dtor)) // doesn't match check (e.g. is impure as well)
+            if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well)
                 return;
 
             // Sanity check
-            assert(!check(cast(DtorDeclaration) ad.fieldDtor));
-            break;
+            assert(!check(ad.fieldDtor));
         }
 
         dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:",
@@ -1781,13 +1775,13 @@ extern (C++) final class IntegerExp : Expression
         this.value = cast(d_int32)value;
     }
 
-    static IntegerExp create(Loc loc, dinteger_t value, Type type)
+    static IntegerExp create(const ref Loc loc, dinteger_t value, Type type)
     {
         return new IntegerExp(loc, value, type);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, dinteger_t value, Type type)
+    static void emplace(UnionExp* pue, const ref Loc loc, dinteger_t value, Type type)
     {
         emplaceExp!(IntegerExp)(pue, loc, value, type);
     }
@@ -2052,13 +2046,13 @@ extern (C++) final class RealExp : Expression
         this.type = type;
     }
 
-    static RealExp create(Loc loc, real_t value, Type type)
+    static RealExp create(const ref Loc loc, real_t value, Type type)
     {
         return new RealExp(loc, value, type);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, real_t value, Type type)
+    static void emplace(UnionExp* pue, const ref Loc loc, real_t value, Type type)
     {
         emplaceExp!(RealExp)(pue, loc, value, type);
     }
@@ -2127,13 +2121,13 @@ extern (C++) final class ComplexExp : Expression
         //printf("ComplexExp::ComplexExp(%s)\n", toChars());
     }
 
-    static ComplexExp create(Loc loc, complex_t value, Type type)
+    static ComplexExp create(const ref Loc loc, complex_t value, Type type)
     {
         return new ComplexExp(loc, value, type);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, complex_t value, Type type)
+    static void emplace(UnionExp* pue, const ref Loc loc, complex_t value, Type type)
     {
         emplaceExp!(ComplexExp)(pue, loc, value, type);
     }
@@ -2203,7 +2197,7 @@ extern (C++) class IdentifierExp : Expression
         this.ident = ident;
     }
 
-    static IdentifierExp create(Loc loc, Identifier ident)
+    static IdentifierExp create(const ref Loc loc, Identifier ident)
     {
         return new IdentifierExp(loc, ident);
     }
@@ -2421,28 +2415,28 @@ extern (C++) final class StringExp : Expression
         this.postfix = postfix;
     }
 
-    static StringExp create(Loc loc, char* s)
+    static StringExp create(const ref Loc loc, const(char)* s)
     {
         return new StringExp(loc, s.toDString());
     }
 
-    static StringExp create(Loc loc, void* string, size_t len)
+    static StringExp create(const ref Loc loc, const(void)* string, size_t len)
     {
         return new StringExp(loc, string[0 .. len]);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, char* s)
+    static void emplace(UnionExp* pue, const ref Loc loc, const(char)* s)
     {
         emplaceExp!(StringExp)(pue, loc, s.toDString());
     }
 
-    extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string)
+    extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string)
     {
         emplaceExp!(StringExp)(pue, loc, string);
     }
 
-    extern (D) static void emplace(UnionExp* pue, Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
+    extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
     {
         emplaceExp!(StringExp)(pue, loc, string, len, sz, postfix);
     }
@@ -2863,7 +2857,7 @@ extern (C++) final class TupleExp : Expression
         }
     }
 
-    static TupleExp create(Loc loc, Expressions* exps)
+    static TupleExp create(const ref Loc loc, Expressions* exps)
     {
         return new TupleExp(loc, exps);
     }
@@ -2946,13 +2940,13 @@ extern (C++) final class ArrayLiteralExp : Expression
         this.elements = elements;
     }
 
-    static ArrayLiteralExp create(Loc loc, Expressions* elements)
+    static ArrayLiteralExp create(const ref Loc loc, Expressions* elements)
     {
         return new ArrayLiteralExp(loc, null, elements);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, Expressions* elements)
+    static void emplace(UnionExp* pue, const ref Loc loc, Expressions* elements)
     {
         emplaceExp!(ArrayLiteralExp)(pue, loc, null, elements);
     }
@@ -3188,7 +3182,7 @@ extern (C++) final class StructLiteralExp : Expression
         //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
     }
 
-    static StructLiteralExp create(Loc loc, StructDeclaration sd, void* elements, Type stype = null)
+    static StructLiteralExp create(const ref Loc loc, StructDeclaration sd, void* elements, Type stype = null)
     {
         return new StructLiteralExp(loc, sd, cast(Expressions*)elements, stype);
     }
@@ -3532,7 +3526,7 @@ extern (C++) final class NewExp : Expression
         this.arguments = arguments;
     }
 
-    static NewExp create(Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
+    static NewExp create(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
     {
         return new NewExp(loc, thisexp, newargs, newtype, arguments);
     }
@@ -3653,7 +3647,7 @@ extern (C++) final class VarExp : SymbolExp
         this.type = var.type;
     }
 
-    static VarExp create(Loc loc, Declaration var, bool hasOverloads = true)
+    static VarExp create(const ref Loc loc, Declaration var, bool hasOverloads = true)
     {
         return new VarExp(loc, var, hasOverloads);
     }
@@ -3965,6 +3959,7 @@ extern (C++) final class FuncExp : Expression
             auto tfy = new TypeFunction(tfx.parameterList, tof.next,
                         tfx.linkage, STC.undefined_);
             tfy.mod = tfx.mod;
+            tfy.trust = tfx.trust;
             tfy.isnothrow = tfx.isnothrow;
             tfy.isnogc = tfx.isnogc;
             tfy.purity = tfx.purity;
@@ -4688,6 +4683,7 @@ extern (C++) final class DotIdExp : UnaExp
     Identifier ident;
     bool noderef;       // true if the result of the expression will never be dereferenced
     bool wantsym;       // do not replace Symbol with its initializer during semantic()
+    bool arrow;         // ImportC: if -> instead of .
 
     extern (D) this(const ref Loc loc, Expression e, Identifier ident)
     {
@@ -4695,7 +4691,7 @@ extern (C++) final class DotIdExp : UnaExp
         this.ident = ident;
     }
 
-    static DotIdExp create(Loc loc, Expression e, Identifier ident)
+    static DotIdExp create(const ref Loc loc, Expression e, Identifier ident)
     {
         return new DotIdExp(loc, e, ident);
     }
@@ -4889,6 +4885,31 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
         return ti.updateTempDecl(sc, s);
     }
 
+    override bool checkType()
+    {
+        // Same logic as ScopeExp.checkType()
+        if (ti.tempdecl &&
+            ti.semantictiargsdone &&
+            ti.semanticRun == PASS.init)
+        {
+            error("partial %s `%s` has no type", ti.kind(), toChars());
+            return true;
+        }
+        return false;
+    }
+
+    override bool checkValue()
+    {
+        if (ti.tempdecl &&
+            ti.semantictiargsdone &&
+            ti.semanticRun == PASS.init)
+
+            error("partial %s `%s` has no value", ti.kind(), toChars());
+        else
+            error("%s `%s` has no value", ti.kind(), ti.toChars());
+        return true;
+    }
+
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -4987,17 +5008,17 @@ extern (C++) final class CallExp : UnaExp
         this.f = fd;
     }
 
-    static CallExp create(Loc loc, Expression e, Expressions* exps)
+    static CallExp create(const ref Loc loc, Expression e, Expressions* exps)
     {
         return new CallExp(loc, e, exps);
     }
 
-    static CallExp create(Loc loc, Expression e)
+    static CallExp create(const ref Loc loc, Expression e)
     {
         return new CallExp(loc, e);
     }
 
-    static CallExp create(Loc loc, Expression e, Expression earg1)
+    static CallExp create(const ref Loc loc, Expression e, Expression earg1)
     {
         return new CallExp(loc, e, earg1);
     }
@@ -5009,7 +5030,7 @@ extern (C++) final class CallExp : UnaExp
     *       fd    = the declaration of the function to call
     *       earg1 = the function argument
     */
-    static CallExp create(Loc loc, FuncDeclaration fd, Expression earg1)
+    static CallExp create(const ref Loc loc, FuncDeclaration fd, Expression earg1)
     {
         return new CallExp(loc, fd, earg1);
     }
@@ -5167,6 +5188,19 @@ extern (C++) final class PtrExp : UnaExp
     override Expression modifiableLvalue(Scope* sc, Expression e)
     {
         //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type.toChars());
+        Declaration var;
+        if (auto se = e1.isSymOffExp())
+            var = se.var;
+        else if (auto ve = e1.isVarExp())
+            var = ve.var;
+        if (var && var.type.isFunction_Delegate_PtrToFunction())
+        {
+            if (var.type.isTypeFunction())
+                error("function `%s` is not an lvalue and cannot be modified", var.toChars());
+            else
+                error("function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars());
+            return ErrorExp.get();
+        }
         return Expression.modifiableLvalue(sc, e);
     }
 
@@ -5331,13 +5365,13 @@ extern (C++) final class VectorExp : UnaExp
         to = cast(TypeVector)t;
     }
 
-    static VectorExp create(Loc loc, Expression e, Type t)
+    static VectorExp create(const ref Loc loc, Expression e, Type t)
     {
         return new VectorExp(loc, e, t);
     }
 
     // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, Loc loc, Expression e, Type type)
+    static void emplace(UnionExp* pue, const ref Loc loc, Expression e, Type type)
     {
         emplaceExp!(VectorExp)(pue, loc, e, type);
     }
index dec3713b676b4802b443113af59f8d72e252254d..691364cb265de0fc3db6b41304b21b85858cb742 100644 (file)
@@ -57,6 +57,9 @@ enum
     OWNEDcache      // constant value cached for CTFE
 };
 
+#define WANTvalue  0 // default
+#define WANTexpand 1 // expand const/immutable variables if possible
+
 /**
  * Specifies how the checkModify deals with certain situations
  */
@@ -239,8 +242,8 @@ class IntegerExp : public Expression
 public:
     dinteger_t value;
 
-    static IntegerExp *create(Loc loc, dinteger_t value, Type *type);
-    static void emplace(UnionExp *pue, Loc loc, dinteger_t value, Type *type);
+    static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type);
+    static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type);
     bool equals(const RootObject *o) const;
     dinteger_t toInteger();
     real_t toReal();
@@ -269,8 +272,8 @@ class RealExp : public Expression
 public:
     real_t value;
 
-    static RealExp *create(Loc loc, real_t value, Type *type);
-    static void emplace(UnionExp *pue, Loc loc, real_t value, Type *type);
+    static RealExp *create(const Loc &loc, real_t value, Type *type);
+    static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type);
     bool equals(const RootObject *o) const;
     dinteger_t toInteger();
     uinteger_t toUInteger();
@@ -286,8 +289,8 @@ class ComplexExp : public Expression
 public:
     complex_t value;
 
-    static ComplexExp *create(Loc loc, complex_t value, Type *type);
-    static void emplace(UnionExp *pue, Loc loc, complex_t value, Type *type);
+    static ComplexExp *create(const Loc &loc, complex_t value, Type *type);
+    static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type);
     bool equals(const RootObject *o) const;
     dinteger_t toInteger();
     uinteger_t toUInteger();
@@ -303,7 +306,7 @@ class IdentifierExp : public Expression
 public:
     Identifier *ident;
 
-    static IdentifierExp *create(Loc loc, Identifier *ident);
+    static IdentifierExp *create(const Loc &loc, Identifier *ident);
     bool isLvalue();
     Expression *toLvalue(Scope *sc, Expression *e);
     void accept(Visitor *v) { v->visit(this); }
@@ -365,10 +368,9 @@ public:
     utf8_t postfix;      // 'c', 'w', 'd'
     OwnedBy ownedByCtfe;
 
-    static StringExp *create(Loc loc, char *s);
-    static StringExp *create(Loc loc, void *s, size_t len);
-    static void emplace(UnionExp *pue, Loc loc, char *s);
-    static void emplace(UnionExp *pue, Loc loc, void *s, size_t len);
+    static StringExp *create(const Loc &loc, const char *s);
+    static StringExp *create(const Loc &loc, const void *s, size_t len);
+    static void emplace(UnionExp *pue, const Loc &loc, const char *s);
     bool equals(const RootObject *o) const;
     StringExp *toStringExp();
     StringExp *toUTF8(Scope *sc);
@@ -397,7 +399,7 @@ public:
      */
     Expressions *exps;
 
-    static TupleExp *create(Loc loc, Expressions *exps);
+    static TupleExp *create(const Loc &loc, Expressions *exps);
     TupleExp *toTupleExp();
     TupleExp *syntaxCopy();
     bool equals(const RootObject *o) const;
@@ -412,8 +414,8 @@ public:
     Expressions *elements;
     OwnedBy ownedByCtfe;
 
-    static ArrayLiteralExp *create(Loc loc, Expressions *elements);
-    static void emplace(UnionExp *pue, Loc loc, Expressions *elements);
+    static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
+    static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
     ArrayLiteralExp *syntaxCopy();
     bool equals(const RootObject *o) const;
     Expression *getElement(d_size_t i); // use opIndex instead
@@ -468,7 +470,7 @@ public:
     bool isOriginal;            // used when moving instances to indicate `this is this.origin`
     OwnedBy ownedByCtfe;
 
-    static StructLiteralExp *create(Loc loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
+    static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
     bool equals(const RootObject *o) const;
     StructLiteralExp *syntaxCopy();
     Expression *getField(Type *type, unsigned offset);
@@ -528,7 +530,7 @@ public:
     bool onstack;               // allocate on stack
     bool thrownew;              // this NewExp is the expression of a ThrowStatement
 
-    static NewExp *create(Loc loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments);
+    static NewExp *create(const Loc &loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments);
     NewExp *syntaxCopy();
 
     void accept(Visitor *v) { v->visit(this); }
@@ -576,7 +578,7 @@ class VarExp : public SymbolExp
 {
 public:
     bool delegateWasExtracted;
-    static VarExp *create(Loc loc, Declaration *var, bool hasOverloads = true);
+    static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
     bool equals(const RootObject *o) const;
     bool isLvalue();
     Expression *toLvalue(Scope *sc, Expression *e);
@@ -746,8 +748,9 @@ public:
     Identifier *ident;
     bool noderef;       // true if the result of the expression will never be dereferenced
     bool wantsym;       // do not replace Symbol with its initializer during semantic()
+    bool arrow;         // ImportC: if -> instead of .
 
-    static DotIdExp *create(Loc loc, Expression *e, Identifier *ident);
+    static DotIdExp *create(const Loc &loc, Expression *e, Identifier *ident);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -780,6 +783,8 @@ public:
 
     DotTemplateInstanceExp *syntaxCopy();
     bool findTempDecl(Scope *sc);
+    bool checkType();
+    bool checkValue();
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -812,10 +817,10 @@ public:
     bool ignoreAttributes;      // don't enforce attributes (e.g. call @gc function in @nogc code)
     VarDeclaration *vthis2;     // container for multi-context
 
-    static CallExp *create(Loc loc, Expression *e, Expressions *exps);
-    static CallExp *create(Loc loc, Expression *e);
-    static CallExp *create(Loc loc, Expression *e, Expression *earg1);
-    static CallExp *create(Loc loc, FuncDeclaration *fd, Expression *earg1);
+    static CallExp *create(const Loc &loc, Expression *e, Expressions *exps);
+    static CallExp *create(const Loc &loc, Expression *e);
+    static CallExp *create(const Loc &loc, Expression *e, Expression *earg1);
+    static CallExp *create(const Loc &loc, FuncDeclaration *fd, Expression *earg1);
 
     CallExp *syntaxCopy();
     bool isLvalue();
@@ -893,8 +898,8 @@ public:
     unsigned dim;               // number of elements in the vector
     OwnedBy ownedByCtfe;
 
-    static VectorExp *create(Loc loc, Expression *e, Type *t);
-    static void emplace(UnionExp *pue, Loc loc, Expression *e, Type *t);
+    static VectorExp *create(const Loc &loc, Expression *e, Type *t);
+    static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t);
     VectorExp *syntaxCopy();
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -1272,7 +1277,7 @@ public:
 
 class GenericExp : Expression
 {
-    Expression cntlExp;
+    Expression *cntlExp;
     Types *types;
     Expressions *exps;
 
index 3b604af53b98a1c53cbc8c87b03552f287a6ac34..8e152d6a1fcce2a81362f49ddcfcbcbe7f1869a6 100644 (file)
@@ -43,12 +43,14 @@ import dmd.dtemplate;
 import dmd.errors;
 import dmd.escape;
 import dmd.expression;
+import dmd.file_manager;
 import dmd.func;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.imphint;
+import dmd.importc;
 import dmd.init;
 import dmd.initsem;
 import dmd.inline;
@@ -62,7 +64,7 @@ import dmd.printast;
 import dmd.root.ctfloat;
 import dmd.root.file;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.semantic2;
@@ -1239,6 +1241,10 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
         tthis = dve.e1.type;
         goto Lfd;
     }
+    else if (sc && sc.flags & SCOPE.Cfile && e1.op == TOK.variable && !e2)
+    {
+        // ImportC: do not implicitly call function if no ( ) are present
+    }
     else if (e1.op == TOK.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
     {
         s = (cast(VarExp)e1).var;
@@ -1388,7 +1394,6 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
 
     Type t0 = null;
     Expression e0 = null;
-    size_t j0 = ~0;
     bool foundType;
 
     for (size_t i = 0; i < exps.dim; i++)
@@ -1441,17 +1446,16 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
             {
                 // https://issues.dlang.org/show_bug.cgi?id=21285
                 // Functions and delegates don't convert correctly with castTo below
-                exps[j0] = condexp.e1;
+                exps[i] = condexp.e1;
                 e = condexp.e2;
             }
             else
             {
                 // Convert to common type
-                exps[j0] = condexp.e1.castTo(sc, condexp.type);
+                exps[i] = condexp.e1.castTo(sc, condexp.type);
                 e = condexp.e2.castTo(sc, condexp.type);
             }
         }
-        j0 = i;
         e0 = e;
         t0 = e.type;
         if (e.op != TOK.error)
@@ -1599,6 +1603,7 @@ private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool repo
         {
             Expression arg = (*exps)[i];
             arg = resolveProperties(sc, arg);
+            arg = arg.arrayFuncConv(sc);
             if (arg.op == TOK.type)
             {
                 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
@@ -4297,7 +4302,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
          *  expr.foo!(tiargs)(funcargs)
          */
     Ldotti:
-        if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
+        if (exp.e1.op == TOK.dotTemplateInstance)
         {
             DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
             TemplateInstance ti = se.ti;
@@ -4352,7 +4357,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                  * We handle such earlier, so go back.
                  * Note that in the rewrite, we carefully did not run semantic() on e1
                  */
-                if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
+                if (exp.e1.op == TOK.dotTemplateInstance)
                 {
                     goto Ldotti;
                 }
@@ -4419,6 +4424,26 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else if (exp.e1.op == TOK.type && (sc && sc.flags & SCOPE.Cfile))
             {
+                const numArgs = exp.arguments ? exp.arguments.length : 0;
+                if (e1org.parens && numArgs >= 1)
+                {
+                    /* Ambiguous cases arise from CParser where there is not enough
+                     * information to determine if we have a function call or a cast.
+                     *   ( type-name ) ( identifier ) ;
+                     *   ( identifier ) ( identifier ) ;
+                     * If exp.e1 is a type-name, then this is a cast.
+                     */
+                    Expression arg;
+                    foreach (a; (*exp.arguments)[])
+                    {
+                        arg = arg ? new CommaExp(a.loc, arg, a) : a;
+                    }
+                    auto t = exp.e1.isTypeExp().type;
+                    auto e = new CastExp(exp.loc, arg, t);
+                    result = e.expressionSemantic(sc);
+                    return;
+                }
+
                 /* Ambiguous cases arise from CParser where there is not enough
                  * information to determine if we have a function call or declaration.
                  *   type-name ( identifier ) ;
@@ -4426,7 +4451,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                  * If exp.e1 is a type-name, then this is a declaration. C11 does not
                  * have type construction syntax, so don't convert this to a cast().
                  */
-                if (exp.arguments && exp.arguments.dim == 1)
+                if (numArgs == 1)
                 {
                     Expression arg = (*exp.arguments)[0];
                     if (auto ie = (*exp.arguments)[0].isIdentifierExp())
@@ -4638,15 +4663,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             UnaExp ue = cast(UnaExp)exp.e1;
 
-            Expression ue1 = ue.e1;
-            Expression ue1old = ue1; // need for 'right this' check
-            VarDeclaration v;
-            if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
-            {
-                ue.e1 = new TypeExp(ue1.loc, ue1.type);
-                ue1 = null;
-            }
-
+            Expression ue1old = ue.e1; // need for 'right this' check
             DotVarExp dve;
             DotTemplateExp dte;
             Dsymbol s;
@@ -4665,7 +4682,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
 
             // Do overload resolution
-            exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard);
+            exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
                 return setError();
 
@@ -4677,7 +4694,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 auto ad2 = b.sym;
                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
                 ue.e1 = ue.e1.expressionSemantic(sc);
-                ue1 = ue.e1;
                 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
                 assert(vi >= 0);
                 exp.f = ad2.vtbl[vi].isFuncDeclaration();
@@ -6036,17 +6052,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         {
-            auto readResult = File.read(name);
-            if (!readResult.success)
+            auto fileName = FileName(name.toDString);
+            if (auto fmResult = FileManager.fileManager.lookup(fileName))
             {
-                e.error("cannot read file `%s`", name);
-                return setError();
+                se = new StringExp(e.loc, fmResult.data);
             }
             else
             {
-                // take ownership of buffer (probably leaking)
-                auto data = readResult.extractSlice();
-                se = new StringExp(e.loc, data);
+                auto readResult = File.read(name);
+                if (!readResult.success)
+                {
+                    e.error("cannot read file `%s`", name);
+                    return setError();
+                }
+                else
+                {
+                    // take ownership of buffer (probably leaking)
+                    auto data = readResult.extractSlice();
+                    se = new StringExp(e.loc, data);
+
+                    FileBuffer* fileBuffer = FileBuffer.create();
+                    fileBuffer.data = data;
+                    FileManager.fileManager.add(fileName, fileBuffer);
+                }
             }
         }
         result = se.expressionSemantic(sc);
@@ -6357,7 +6385,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 result = e;
                 return;
             }
-            exp.type = Type.tnoreturn;
+
+            // Only override the type when it isn't already some flavour of noreturn,
+            // e.g. when this assert was generated by defaultInitLiteral
+            if (!exp.type || !exp.type.isTypeNoreturn())
+                exp.type = Type.tnoreturn;
         }
         else
             exp.type = Type.tvoid;
@@ -6374,12 +6406,53 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
             //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
         }
+        if (exp.arrow) // ImportC only
+            exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
+
+        if (sc.flags & SCOPE.Cfile)
+        {
+            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)
+                {
+                    exp.e1.error("argument to `_Alignof` must be a type");
+                    return setError();
+                }
+                else if (t)
+                {
+                    result = new IntegerExp(exp.loc, t.alignsize, Type.tsize_t);
+                }
+                else if (s)
+                {
+                    exp.e1.error("argument to `_Alignof` must be a type");
+                    return setError();
+                }
+                else
+                    assert(0);
+                return;
+            }
+        }
+
+        if (sc.flags & SCOPE.Cfile && exp.ident != Id.__sizeof)
+        {
+            result = fieldLookup(exp.e1, sc, exp.ident);
+            return;
+        }
+
         Expression e = exp.semanticY(sc, 1);
+
         if (e && isDotOpDispatch(e))
         {
+            auto ode = e;
             uint errors = global.startGagging();
             e = resolvePropertiesX(sc, e);
-            if (global.endGagging(errors))
+            // Any error or if 'e' is not resolved, go to UFCS
+            if (global.endGagging(errors) || e is ode)
                 e = null; /* fall down to UFCS */
             else
             {
@@ -6580,10 +6653,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
         }
+        if (exp.type)
+        {
+            result = exp;
+            return;
+        }
         // Indicate we need to resolve by UFCS.
         Expression e = exp.semanticY(sc, 1);
         if (!e)
             e = resolveUFCSProperties(sc, exp);
+        if (e is exp)
+            e.type = Type.tvoid; // Unresolved type, because it needs inference
         result = e;
     }
 
@@ -7908,6 +7988,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     dinteger_t length = el.toInteger();
                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
                     exp.upperIsInBounds = bounds.contains(uprRange);
+                    if (exp.lwr.op == TOK.int64 && exp.upr.op == TOK.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
+                    {
+                        exp.error("in slice `%s[%llu .. %llu]`, lower bound is greater than upper bound", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger());
+                        return setError();
+                    }
+                    if (exp.upr.op == TOK.int64 && exp.upr.toInteger() > length)
+                    {
+                        exp.error("in slice `%s[%llu .. %llu]`, upper bound is greater than array length `%llu`", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger(), length);
+                        return setError();
+                    }
                 }
                 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
                 {
@@ -7965,6 +8055,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("ArrayExp::semantic('%s')\n", exp.toChars());
         }
         assert(!exp.type);
+
+        result = exp.carraySemantic(sc);  // C semantics
+        if (result)
+            return;
+
         Expression e = exp.op_overload(sc);
         if (e)
         {
@@ -8019,6 +8114,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(CommaExp e)
     {
+        //printf("Semantic.CommaExp() %s\n", e.toChars());
         if (e.type)
         {
             result = e;
@@ -8042,10 +8138,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (checkNonAssignmentArrayOp(e.e1))
             return setError();
 
+        // Comma expressions trigger this conversion
+        e.e2 = e.e2.arrayFuncConv(sc);
+
         e.type = e.e2.type;
         if (e.type is Type.tvoid)
             discardValue(e.e1);
-        else if (!e.allowCommaExp && !e.isGenerated)
+        else if (!e.allowCommaExp && !e.isGenerated && !(sc.flags & SCOPE.Cfile))
             e.error("Using the result of a comma expression is not allowed");
         result = e;
     }
@@ -8143,7 +8242,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         // operator overloading should be handled in ArrayExp already.
         if (!exp.e1.type)
-            exp.e1 = exp.e1.expressionSemantic(sc);
+            exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
         assert(exp.e1.type); // semantic() should already be run on it
         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
         {
@@ -8191,7 +8290,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         if (t1b.ty == Ttuple)
             sc = sc.startCTFE();
-        exp.e2 = exp.e2.expressionSemantic(sc);
+        exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
         exp.e2 = resolveProperties(sc, exp.e2);
         if (t1b.ty == Ttuple)
             sc = sc.endCTFE();
@@ -8515,7 +8614,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (auto e2comma = exp.e2.isCommaExp())
         {
-            if (!e2comma.isGenerated)
+            if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
                 exp.error("Using the result of a comma expression is not allowed");
 
             /* Rewrite to get rid of the comma from rvalue
@@ -8659,6 +8758,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
                 e1x = e;
             }
+            else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
+            {
+                auto die = e1x.isDotIdExp();
+                e1x = fieldLookup(die.e1, sc, die.ident);
+            }
             else if (auto die = e1x.isDotIdExp())
             {
                 Expression e = die.semanticY(sc, 1);
@@ -8672,10 +8776,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                      * In order to make sure that UFCS is tried with correct parameters, e2
                      * needs to have semantic ran on it.
                      */
+                    auto ode = e;
                     exp.e2 = exp.e2.expressionSemantic(sc);
                     uint errors = global.startGagging();
                     e = resolvePropertiesX(sc, e, exp.e2);
-                    if (global.endGagging(errors))
+                    // Any error or if 'e' is not resolved, go to UFCS
+                    if (global.endGagging(errors) || e is ode)
                         e = null; /* fall down to UFCS */
                     else
                         return setResult(e);
@@ -8717,12 +8823,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             Expression e2x = inferType(exp.e2, t1.baseElemOf());
             e2x = e2x.expressionSemantic(sc);
+            if (!t1.isTypeSArray())
+                e2x = e2x.arrayFuncConv(sc);
             e2x = resolveProperties(sc, e2x);
             if (e2x.op == TOK.type)
                 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
             if (e2x.op == TOK.error)
                 return setResult(e2x);
-            // We skip checking the value for structs/classes as these might have
+            // We delay checking the value for structs/classes as these might have
             // an opAssign defined.
             if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
                 e2x.checkSharedAccess(sc))
@@ -9208,6 +9316,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             else
                 assert(exp.op == TOK.blit);
 
+            if (e2x.checkValue())
+                return setError();
+
             exp.e1 = e1x;
             exp.e2 = e2x;
         }
@@ -9223,6 +9334,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     return;
                 }
             }
+            if (exp.e2.checkValue())
+                return setError();
         }
         else if (t1.ty == Tsarray)
         {
@@ -9672,7 +9785,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         exp.type = exp.e1.type;
         assert(exp.type);
         auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
-        checkAssignEscape(sc, res, false);
+        Expression tmp;
+        /* https://issues.dlang.org/show_bug.cgi?id=22366
+         *
+         * `reorderSettingAAElem` creates a tree of comma expressions, however,
+         * `checkAssignExp` expects only AssignExps.
+         */
+        checkAssignEscape(sc, Expression.extractLast(res, tmp), false);
         return setResult(res);
     }
 
@@ -9944,6 +10063,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        /* ImportC: convert arrays to pointers, functions to pointers to functions
+         */
+        exp.e1 = exp.e1.arrayFuncConv(sc);
+        exp.e2 = exp.e2.arrayFuncConv(sc);
+
         Type tb1 = exp.e1.type.toBasetype();
         Type tb2 = exp.e2.type.toBasetype();
 
@@ -10045,6 +10169,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        /* ImportC: convert arrays to pointers, functions to pointers to functions
+         */
+        exp.e1 = exp.e1.arrayFuncConv(sc);
+        exp.e2 = exp.e2.arrayFuncConv(sc);
+
         Type t1 = exp.e1.type.toBasetype();
         Type t2 = exp.e2.type.toBasetype();
 
@@ -11539,12 +11668,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         ec = ec.toBoolean(sc);
 
         CtorFlow ctorflow_root = sc.ctorflow.clone();
-        Expression e1x = exp.e1.expressionSemantic(sc);
+        Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
         e1x = resolveProperties(sc, e1x);
 
         CtorFlow ctorflow1 = sc.ctorflow;
         sc.ctorflow = ctorflow_root;
-        Expression e2x = exp.e2.expressionSemantic(sc);
+        Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
         e2x = resolveProperties(sc, e2x);
 
         sc.merge(exp.loc, ctorflow1);
@@ -11894,95 +12023,84 @@ Expression semanticX(DotIdExp exp, Scope* sc)
     if (exp.ident == Id._mangleof)
     {
         // symbol.mangleof
-        Dsymbol ds;
-        switch (exp.e1.op)
+
+        // return mangleof as an Expression
+        static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
         {
-        case TOK.scope_:
-            ds = (cast(ScopeExp)exp.e1).sds;
-            goto L1;
-        case TOK.variable:
-            ds = (cast(VarExp)exp.e1).var;
-            goto L1;
-        case TOK.dotVariable:
-            ds = (cast(DotVarExp)exp.e1).var;
-            goto L1;
-        case TOK.overloadSet:
-            ds = (cast(OverExp)exp.e1).vars;
-            goto L1;
-        case TOK.template_:
-            {
-                TemplateExp te = cast(TemplateExp)exp.e1;
-                ds = te.fd ? cast(Dsymbol)te.fd : te.td;
-            }
-        L1:
+            assert(ds);
+            if (auto f = ds.isFuncDeclaration())
             {
-                assert(ds);
-                if (auto f = ds.isFuncDeclaration())
+                if (f.checkForwardRef(loc))
+                    return ErrorExp.get();
+
+                if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
+                               FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
                 {
-                    if (f.checkForwardRef(exp.loc))
-                    {
-                        return ErrorExp.get();
-                    }
-                    if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
-                                   FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
-                    {
-                        f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes");
-                        return ErrorExp.get();
-                    }
+                    f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
+                    return ErrorExp.get();
                 }
-                OutBuffer buf;
-                mangleToBuffer(ds, &buf);
-                Expression e = new StringExp(exp.loc, buf.extractSlice());
-                e = e.expressionSemantic(sc);
-                return e;
             }
-        default:
-            break;
+            OutBuffer buf;
+            mangleToBuffer(ds, &buf);
+            Expression e = new StringExp(loc, buf.extractSlice());
+            return e.expressionSemantic(sc);
+        }
+
+        Dsymbol ds;
+        switch (exp.e1.op)
+        {
+            case TOK.scope_:      return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
+            case TOK.variable:    return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
+            case TOK.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
+            case TOK.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
+            case TOK.template_:
+            {
+                TemplateExp te = exp.e1.isTemplateExp();
+                return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
+            }
+
+            default:
+                break;
         }
     }
 
-    if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length)
+    if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
     {
         // bypass checkPurity
         return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
     }
 
-    if (exp.e1.op == TOK.dot)
-    {
-    }
-    else
+    if (!exp.e1.isDotExp())
     {
         exp.e1 = resolvePropertiesX(sc, exp.e1);
     }
-    if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof)
+
+    if (auto te = exp.e1.isTupleExp())
     {
-        /* 'distribute' the .offsetof to each of the tuple elements.
-         */
-        TupleExp te = cast(TupleExp)exp.e1;
-        auto exps = new Expressions(te.exps.dim);
-        for (size_t i = 0; i < exps.dim; i++)
+        if (exp.ident == Id.offsetof)
         {
-            Expression e = (*te.exps)[i];
+            /* 'distribute' the .offsetof to each of the tuple elements.
+             */
+            auto exps = new Expressions(te.exps.dim);
+            foreach (i, e; (*te.exps)[])
+            {
+                (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
+            }
+            // Don't evaluate te.e0 in runtime
+            Expression e = new TupleExp(exp.loc, null, exps);
             e = e.expressionSemantic(sc);
-            e = new DotIdExp(e.loc, e, Id.offsetof);
-            (*exps)[i] = e;
+            return e;
+        }
+        if (exp.ident == Id.length)
+        {
+            // Don't evaluate te.e0 in runtime
+            return new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
         }
-        // Don't evaluate te.e0 in runtime
-        Expression e = new TupleExp(exp.loc, null, exps);
-        e = e.expressionSemantic(sc);
-        return e;
-    }
-    if (exp.e1.op == TOK.tuple && exp.ident == Id.length)
-    {
-        TupleExp te = cast(TupleExp)exp.e1;
-        // Don't evaluate te.e0 in runtime
-        Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
-        return e;
     }
 
     // https://issues.dlang.org/show_bug.cgi?id=14416
     // Template has no built-in properties except for 'stringof'.
-    if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof)
+    if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
     {
         exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
         return ErrorExp.get();
@@ -11996,8 +12114,15 @@ Expression semanticX(DotIdExp exp, Scope* sc)
     return exp;
 }
 
-// Resolve e1.ident without seeing UFCS.
-// If flag == 1, stop "not a property" error and return NULL.
+/******************************
+ * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
+ * Params:
+ *      exp = expression to resolve
+ *      sc = context
+ *      flag = if 1 then do not emit error messages, just return null
+ * Returns:
+ *      resolved expression, null if error
+ */
 Expression semanticY(DotIdExp exp, Scope* sc, int flag)
 {
     //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
@@ -12008,32 +12133,35 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
      * to be classtype.id and baseclasstype.id
      * if we have no this pointer.
      */
-    if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc))
+    if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
     {
         if (AggregateDeclaration ad = sc.getStructClassScope())
         {
-            if (exp.e1.op == TOK.this_)
+            if (exp.e1.isThisExp())
             {
                 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
             }
             else
             {
-                ClassDeclaration cd = ad.isClassDeclaration();
-                if (cd && cd.baseClass)
-                    exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
+                if (auto cd = ad.isClassDeclaration())
+                {
+                    if (cd.baseClass)
+                        exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
+                }
             }
         }
     }
 
-    Expression e = semanticX(exp, sc);
-    if (e != exp)
-        return e;
+    {
+        Expression e = semanticX(exp, sc);
+        if (e != exp)
+            return e;
+    }
 
     Expression eleft;
     Expression eright;
-    if (exp.e1.op == TOK.dot)
+    if (auto de = exp.e1.isDotExp())
     {
-        DotExp de = cast(DotExp)exp.e1;
         eleft = de.e1;
         eright = de.e2;
     }
@@ -12045,11 +12173,9 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
 
     Type t1b = exp.e1.type.toBasetype();
 
-    if (eright.op == TOK.scope_) // also used for template alias's
+    if (auto ie = eright.isScopeExp()) // also used for template alias's
     {
-        ScopeExp ie = cast(ScopeExp)eright;
-
-        int flags = SearchLocalsOnly;
+        auto flags = SearchLocalsOnly;
         /* Disable access to another module's private imports.
          * The check for 'is sds our current module' is because
          * the current module should have access to its own imports.
@@ -12082,13 +12208,11 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
             exp.checkDeprecated(sc, s);
             exp.checkDisabled(sc, s);
 
-            EnumMember em = s.isEnumMember();
-            if (em)
+            if (auto em = s.isEnumMember())
             {
                 return em.getVarExp(exp.loc, sc);
             }
-            VarDeclaration v = s.isVarDeclaration();
-            if (v)
+            if (auto v = s.isVarDeclaration())
             {
                 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
                 if (!v.type ||
@@ -12100,7 +12224,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                         exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
                     return ErrorExp.get();
                 }
-                if (v.type.ty == Terror)
+                if (v.type.isTypeError())
                     return ErrorExp.get();
 
                 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
@@ -12114,13 +12238,14 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                         error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
                         return ErrorExp.get();
                     }
-                    e = v.expandInitializer(exp.loc);
+                    auto e = v.expandInitializer(exp.loc);
                     v.inuse++;
                     e = e.expressionSemantic(sc);
                     v.inuse--;
                     return e;
                 }
 
+                Expression e;
                 if (v.needThis())
                 {
                     if (!eleft)
@@ -12141,12 +12266,12 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                 return e.expressionSemantic(sc);
             }
 
-            FuncDeclaration f = s.isFuncDeclaration();
-            if (f)
+            if (auto f = s.isFuncDeclaration())
             {
                 //printf("it's a function\n");
                 if (!f.functionSemantic())
                     return ErrorExp.get();
+                Expression e;
                 if (f.needThis())
                 {
                     if (!eleft)
@@ -12167,6 +12292,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
             }
             if (auto td = s.isTemplateDeclaration())
             {
+                Expression e;
                 if (eleft)
                     e = new DotTemplateExp(exp.loc, eleft, td);
                 else
@@ -12176,7 +12302,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
             }
             if (OverDeclaration od = s.isOverDeclaration())
             {
-                e = new VarExp(exp.loc, od, true);
+                Expression e = new VarExp(exp.loc, od, true);
                 if (eleft)
                 {
                     e = new CommaExp(exp.loc, eleft, e);
@@ -12184,8 +12310,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                 }
                 return e;
             }
-            OverloadSet o = s.isOverloadSet();
-            if (o)
+            if (auto o = s.isOverloadSet())
             {
                 //printf("'%s' is an overload set\n", o.toChars());
                 return new OverExp(exp.loc, o);
@@ -12196,36 +12321,33 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
             }
 
-            TupleDeclaration tup = s.isTupleDeclaration();
-            if (tup)
+            if (auto tup = s.isTupleDeclaration())
             {
                 if (eleft)
                 {
-                    e = new DotVarExp(exp.loc, eleft, tup);
+                    Expression e = new DotVarExp(exp.loc, eleft, tup);
                     e = e.expressionSemantic(sc);
                     return e;
                 }
-                e = new TupleExp(exp.loc, tup);
+                Expression e = new TupleExp(exp.loc, tup);
                 e = e.expressionSemantic(sc);
                 return e;
             }
 
-            ScopeDsymbol sds = s.isScopeDsymbol();
-            if (sds)
+            if (auto sds = s.isScopeDsymbol())
             {
                 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
-                e = new ScopeExp(exp.loc, sds);
+                Expression e = new ScopeExp(exp.loc, sds);
                 e = e.expressionSemantic(sc);
                 if (eleft)
                     e = new DotExp(exp.loc, eleft, e);
                 return e;
             }
 
-            Import imp = s.isImport();
-            if (imp)
+            if (auto imp = s.isImport())
             {
-                ie = new ScopeExp(exp.loc, imp.pkg);
-                return ie.expressionSemantic(sc);
+                Expression se = new ScopeExp(exp.loc, imp.pkg);
+                return se.expressionSemantic(sc);
             }
             // BUG: handle other cases like in IdentifierExp::semantic()
             debug
@@ -12236,7 +12358,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
         }
         else if (exp.ident == Id.stringof)
         {
-            e = new StringExp(exp.loc, ie.toString());
+            Expression e = new StringExp(exp.loc, ie.toString());
             e = e.expressionSemantic(sc);
             return e;
         }
@@ -12263,9 +12385,11 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
         Type t1bn = t1b.nextOf();
         if (flag)
         {
-            AggregateDeclaration ad = isAggregate(t1bn);
-            if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
-                return null;
+            if (AggregateDeclaration ad = isAggregate(t1bn))
+            {
+                if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
+                    return null;
+            }
         }
 
         /* Rewrite:
@@ -12275,27 +12399,27 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
          */
         if (flag && t1bn.ty == Tvoid)
             return null;
-        e = new PtrExp(exp.loc, exp.e1);
+        Expression e = new PtrExp(exp.loc, exp.e1);
         e = e.expressionSemantic(sc);
         return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
     }
     else if (exp.ident == Id.__xalignof &&
              exp.e1.isVarExp() &&
              exp.e1.isVarExp().var.isVarDeclaration() &&
-             exp.e1.isVarExp().var.isVarDeclaration().alignment)
+             !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
     {
         // For `x.alignof` get the alignment of the variable, not the alignment of its type
         const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
         const naturalAlignment = exp.e1.type.alignsize();
-        const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
-        e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
+        const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
+        Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
         return e;
     }
     else
     {
-        if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_)
+        if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
             flag = 0;
-        e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
+        Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
         if (e)
             e = e.expressionSemantic(sc);
         return e;
@@ -12875,7 +12999,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
         const hasPointers = tb.hasPointers();
         if (hasPointers)
         {
-            if ((stype.alignment() < target.ptrsize ||
+            if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
                  (v.offset & (target.ptrsize - 1))) &&
                 (sc.func && sc.func.setUnsafe()))
             {
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
new file mode 100644 (file)
index 0000000..05aeb7d
--- /dev/null
@@ -0,0 +1,301 @@
+/**
+ * Read a file from disk and store it in memory.
+ *
+ * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d, _file_manager.d)
+ * Documentation:  https://dlang.org/phobos/dmd_file_manager.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/file_manager.d
+ */
+
+module dmd.file_manager;
+
+import dmd.root.stringtable : StringTable;
+import dmd.root.file : File, FileBuffer;
+import dmd.root.filename : FileName;
+import dmd.root.string : toDString;
+import dmd.globals;
+import dmd.identifier;
+
+enum package_d  = "package." ~ mars_ext;
+enum package_di = "package." ~ hdr_ext;
+
+extern(C++) struct FileManager
+{
+    private StringTable!(FileBuffer*) files;
+    private __gshared bool initialized = false;
+
+nothrow:
+    extern(D) private FileBuffer* readToFileBuffer(const(char)[] filename)
+    {
+        if (!initialized)
+            FileManager._init();
+
+        auto readResult = File.read(filename);
+        if (readResult.success)
+        {
+            FileBuffer* fb;
+            if (auto val = files.lookup(filename))
+                fb = val.value;
+
+            if (!fb)
+                fb = FileBuffer.create();
+
+            fb.data = readResult.extractSlice();
+
+            return files.insert(filename, fb) == null ? null : fb;
+        }
+        else
+        {
+            return null;
+        }
+
+    }
+
+    /********************************************
+    * Look for the source file if it's different from filename.
+    * Look for .di, .d, directory, and along global.path.
+    * Does not open the file.
+    * Params:
+    *      filename = as supplied by the user
+    *      path = path to look for filename
+    * Returns:
+    *      the found file name or
+    *      `null` if it is not different from filename.
+    */
+    extern(D) static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+    {
+        //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
+        /* Search along path[] for .di file, then .d file, then .i file, then .c file.
+        */
+        const sdi = FileName.forceExt(filename, hdr_ext);
+        if (FileName.exists(sdi) == 1)
+            return sdi;
+        scope(exit) FileName.free(sdi.ptr);
+
+        const sd = FileName.forceExt(filename, mars_ext);
+        if (FileName.exists(sd) == 1)
+            return sd;
+        scope(exit) FileName.free(sd.ptr);
+
+        const si = FileName.forceExt(filename, i_ext);
+        if (FileName.exists(si) == 1)
+            return si;
+        scope(exit) FileName.free(si.ptr);
+
+        const sc = FileName.forceExt(filename, c_ext);
+        if (FileName.exists(sc) == 1)
+            return sc;
+        scope(exit) FileName.free(sc.ptr);
+
+        if (FileName.exists(filename) == 2)
+        {
+            /* The filename exists and it's a directory.
+            * Therefore, the result should be: filename/package.d
+            * iff filename/package.d is a file
+            */
+            const ni = FileName.combine(filename, package_di);
+            if (FileName.exists(ni) == 1)
+                return ni;
+            FileName.free(ni.ptr);
+
+            const n = FileName.combine(filename, package_d);
+            if (FileName.exists(n) == 1)
+                return n;
+            FileName.free(n.ptr);
+        }
+        if (FileName.absolute(filename))
+            return null;
+        if (!path.length)
+            return null;
+        foreach (entry; path)
+        {
+            const p = entry.toDString();
+
+            const(char)[] n = FileName.combine(p, sdi);
+            if (FileName.exists(n) == 1) {
+                return n;
+            }
+            FileName.free(n.ptr);
+
+            n = FileName.combine(p, sd);
+            if (FileName.exists(n) == 1) {
+                return n;
+            }
+            FileName.free(n.ptr);
+
+            n = FileName.combine(p, si);
+            if (FileName.exists(n) == 1) {
+                return n;
+            }
+            FileName.free(n.ptr);
+
+            n = FileName.combine(p, sc);
+            if (FileName.exists(n) == 1) {
+                return n;
+            }
+            FileName.free(n.ptr);
+
+            const b = FileName.removeExt(filename);
+            n = FileName.combine(p, b);
+            FileName.free(b.ptr);
+            if (FileName.exists(n) == 2)
+            {
+                const n2i = FileName.combine(n, package_di);
+                if (FileName.exists(n2i) == 1)
+                    return n2i;
+                FileName.free(n2i.ptr);
+                const n2 = FileName.combine(n, package_d);
+                if (FileName.exists(n2) == 1) {
+                    return n2;
+                }
+                FileName.free(n2.ptr);
+            }
+            FileName.free(n.ptr);
+        }
+        return null;
+    }
+
+    /**
+     * Looks up the given filename from the internal file buffer table.
+     * If the file does not already exist within the table, it will be read from the filesystem.
+     * If it has been read before,
+     *
+     * Returns: the loaded source file if it was found in memory,
+     *      otherwise `null`
+     */
+    extern(D) FileBuffer* lookup(FileName filename)
+    {
+        if (!initialized)
+            FileManager._init();
+
+        if (auto val = files.lookup(filename.toString))
+        {
+            // There is a chance that the buffer could've been
+            // stolen by a reader with extractSlice, so we should
+            // try and do our reading logic if that happens.
+            if (val !is null && val.value.data !is null)
+            {
+                return val.value;
+            }
+        }
+
+        const name = filename.toString;
+        auto res = FileName.exists(name);
+        if (res == 1)
+            return readToFileBuffer(name);
+
+        const fullName = lookForSourceFile(name, global.path ? (*global.path)[] : null);
+        if (!fullName)
+            return null;
+
+        return readToFileBuffer(fullName);
+    }
+
+    extern(C++) FileBuffer* lookup(const(char)* filename)
+    {
+        return lookup(FileName(filename.toDString));
+    }
+
+    /**
+     * Looks up the given filename from the internal file buffer table, and returns the lines within the file.
+     * If the file does not already exist within the table, it will be read from the filesystem.
+     * If it has been read before,
+     *
+     * Returns: the loaded source file if it was found in memory,
+     *      otherwise `null`
+     */
+    extern(D) const(char)[][] getLines(FileName file)
+    {
+        if (!initialized)
+            FileManager._init();
+
+        const(char)[][] lines;
+        if (FileBuffer* buffer = lookup(file))
+        {
+            ubyte[] slice = buffer.data[0 .. buffer.data.length];
+            size_t start, end;
+            ubyte c;
+            for (auto i = 0; i < slice.length; i++)
+            {
+                c = slice[i];
+                if (c == '\n' || c == '\r')
+                {
+                    if (i != 0)
+                    {
+                        end = i;
+                        lines ~= cast(const(char)[])slice[start .. end];
+                    }
+                    // Check for Windows-style CRLF newlines
+                    if (c == '\r')
+                    {
+                        if (slice.length > i + 1 && slice[i + 1] == '\n')
+                        {
+                            // This is a CRLF sequence, skip over two characters
+                            start = i + 2;
+                            i++;
+                        }
+                        else
+                        {
+                            // Just a CR sequence
+                            start = i + 1;
+                        }
+                    }
+                    else
+                    {
+                        // The next line should start after the LF sequence
+                        start = i + 1;
+                    }
+                }
+            }
+
+            if (slice[$ - 1] != '\r' && slice[$ - 1] != '\n')
+            {
+                end = slice.length;
+                lines ~= cast(const(char)[])slice[start .. end];
+            }
+        }
+
+        return lines;
+    }
+
+    /**
+     * Adds a FileBuffer to the table.
+     *
+     * Returns: The FileBuffer added, or null
+     */
+    extern(D) FileBuffer* add(FileName filename, FileBuffer* filebuffer)
+    {
+        if (!initialized)
+            FileManager._init();
+
+        auto val = files.insert(filename.toString, filebuffer);
+        return val == null ? null : val.value;
+    }
+
+    extern(C++) FileBuffer* add(const(char)* filename, FileBuffer* filebuffer)
+    {
+        if (!initialized)
+            FileManager._init();
+
+        auto val = files.insert(filename.toDString, filebuffer);
+        return val == null ? null : val.value;
+    }
+
+    __gshared fileManager = FileManager();
+
+    // Initialize the global FileManager singleton
+    extern(C++) static __gshared void _init()
+    {
+        if (!initialized)
+        {
+            fileManager.initialize();
+            initialized = true;
+        }
+    }
+
+    void initialize()
+    {
+        files._init();
+    }
+}
similarity index 50%
rename from gcc/d/dmd/root/root.h
rename to gcc/d/dmd/file_manager.h
index 667ce67fb7c8a8f05aa8e12c0dca1f668cfd5968..7488fab17fc23fefce2c906389bba2a40385d8fa 100644 (file)
@@ -4,17 +4,16 @@
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/root.h
+ * https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.h
  */
 
 #pragma once
 
-#include "object.h"
+#include "root/file.h"
 
-#include "filename.h"
-
-#include "file.h"
-
-#include "outbuffer.h"
-
-#include "array.h"
+struct FileManager
+{
+    static void _init();
+    FileBuffer* lookup(const char* filename);
+    FileBuffer* add(const char* filename, FileBuffer* filebuffer);
+};
index 7f0b0bb9a28d893dfd1728b4c3bc1818d30d0147..2d6a756178e9322c20ae46fc4c24837b7aa68a40 100644 (file)
@@ -45,7 +45,8 @@ import dmd.identifier;
 import dmd.init;
 import dmd.mtype;
 import dmd.objc;
-import dmd.root.outbuffer;
+import dmd.root.aav;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.root.stringtable;
@@ -261,6 +262,8 @@ extern (C++) class FuncDeclaration : Declaration
     VarDeclaration vresult;             /// result variable for out contracts
     LabelDsymbol returnLabel;           /// where the return goes
 
+    bool[size_t] isTypeIsolatedCache;   /// cache for the potentially very expensive isTypeIsolated check
+
     // used to prevent symbols in different
     // scopes from having the same name
     DsymbolTable localsymtab;
@@ -740,7 +743,7 @@ extern (C++) class FuncDeclaration : Declaration
      */
     final BaseClass* overrideInterface()
     {
-        if (ClassDeclaration cd = toParent2().isClassDeclaration())
+        for (ClassDeclaration cd = toParent2().isClassDeclaration(); cd; cd = cd.baseClass)
         {
             foreach (b; cd.interfaces)
             {
@@ -1529,8 +1532,23 @@ extern (C++) class FuncDeclaration : Declaration
     extern (D) final bool isTypeIsolated(Type t)
     {
         StringTable!Type parentTypes;
-        parentTypes._init();
-        return isTypeIsolated(t, parentTypes);
+        const uniqueTypeID = t.getUniqueID();
+        if (uniqueTypeID)
+        {
+            const cacheResultPtr = uniqueTypeID in isTypeIsolatedCache;
+            if (cacheResultPtr !is null)
+                return *cacheResultPtr;
+
+            parentTypes._init();
+            const isIsolated = isTypeIsolated(t, parentTypes);
+            isTypeIsolatedCache[uniqueTypeID] = isIsolated;
+            return isIsolated;
+        }
+        else
+        {
+            parentTypes._init();
+            return isTypeIsolated(t, parentTypes);
+        }
     }
 
     ///ditto
@@ -2593,9 +2611,10 @@ extern (C++) class FuncDeclaration : Declaration
         }
 
         if (!tf.nextOf())
-            error("must return `int` or `void`");
-        else if (tf.nextOf().ty != Tint32 && tf.nextOf().ty != Tvoid)
-            error("must return `int` or `void`, not `%s`", tf.nextOf().toChars());
+            // auto main(), check after semantic
+            assert(this.inferRetType);
+        else if (tf.nextOf().ty != Tint32 && tf.nextOf().ty != Tvoid && tf.nextOf().ty != Tnoreturn)
+            error("must return `int`, `void` or `noreturn`, not `%s`", tf.nextOf().toChars());
         else if (tf.parameterList.varargs || nparams >= 2 || argerr)
             error("parameters must be `main()` or `main(string[] args)`");
     }
@@ -3054,7 +3073,11 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         return null;
 
     bool hasOverloads = fd.overnext !is null;
-    auto tf = fd.type.toTypeFunction();
+    auto tf = fd.type.isTypeFunction();
+    // if type is an error, the original type should be there for better diagnostics
+    if (!tf)
+        tf = fd.originalType.toTypeFunction();
+
     if (tthis && !MODimplicitConv(tthis.mod, tf.mod)) // modifier mismatch
     {
         OutBuffer thisBuf, funcBuf;
@@ -3253,17 +3276,7 @@ private bool traverseIndirections(Type ta, Type tb)
 {
     //printf("traverseIndirections(%s, %s)\n", ta.toChars(), tb.toChars());
 
-    /* Threaded list of aggregate types already examined,
-     * used to break cycles.
-     * Cycles in type graphs can only occur with aggregates.
-     */
-    static struct Ctxt
-    {
-        Ctxt* prev;
-        Type type;      // an aggregate type
-    }
-
-    static bool traverse(Type ta, Type tb, Ctxt* ctxt, bool reversePass)
+    static bool traverse(Type ta, Type tb, ref scope AssocArray!(const(char)*, bool) table, bool reversePass)
     {
         //printf("traverse(%s, %s)\n", ta.toChars(), tb.toChars());
         ta = ta.baseElemOf();
@@ -3293,28 +3306,27 @@ private bool traverseIndirections(Type ta, Type tb)
 
         if (tb.ty == Tclass || tb.ty == Tstruct)
         {
-            for (Ctxt* c = ctxt; c; c = c.prev)
-                if (tb == c.type)
-                    return true;
-            Ctxt c;
-            c.prev = ctxt;
-            c.type = tb;
-
             /* Traverse the type of each field of the aggregate
              */
+            bool* found = table.getLvalue(tb.deco);
+            if (*found == true)
+                return true; // We have already seen this symbol, break the cycle
+            else
+                *found = true;
+
             AggregateDeclaration sym = tb.toDsymbol(null).isAggregateDeclaration();
             foreach (v; sym.fields)
             {
                 Type tprmi = v.type.addMod(tb.mod);
                 //printf("\ttb = %s, tprmi = %s\n", tb.toChars(), tprmi.toChars());
-                if (!traverse(ta, tprmi, &c, reversePass))
+                if (!traverse(ta, tprmi, table, reversePass))
                     return false;
             }
         }
         else if (tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tpointer)
         {
             Type tind = tb.nextOf();
-            if (!traverse(ta, tind, ctxt, reversePass))
+            if (!traverse(ta, tind, table, reversePass))
                 return false;
         }
         else if (tb.hasPointers())
@@ -3325,7 +3337,10 @@ private bool traverseIndirections(Type ta, Type tb)
 
         // Still no match, so try breaking up ta if we have not done so yet.
         if (!reversePass)
-            return traverse(tb, ta, ctxt, true);
+        {
+            scope newTable = AssocArray!(const(char)*, bool)();
+            return traverse(tb, ta, newTable, true);
+        }
 
         return true;
     }
@@ -3333,7 +3348,8 @@ private bool traverseIndirections(Type ta, Type tb)
     // To handle arbitrary levels of indirections in both parameters, we
     // recursively descend into aggregate members/levels of indirection in both
     // `ta` and `tb` while avoiding cycles. Start with the original types.
-    const result = traverse(ta, tb, null, false);
+    scope table = AssocArray!(const(char)*, bool)();
+    const result = traverse(ta, tb, table, false);
     //printf("  returns %d\n", result);
     return result;
 }
index 9b65d024b97de0eae27a331ba64136a6844dcd22..747a1138905aed6c2268b21b85bb69e9dbbfbd61 100644 (file)
@@ -14,7 +14,7 @@ module dmd.globals;
 import core.stdc.stdint;
 import dmd.root.array;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.identifier;
 
 /// Defines a setting for how compiler warnings and deprecations are handled
@@ -118,6 +118,7 @@ extern (C++) struct Param
     bool vgc;               // identify gc usage
     bool vfield;            // identify non-mutable field variables
     bool vcomplex = true;   // identify complex/imaginary type usage
+    bool vin;               // identify 'in' parameters
     ubyte symdebug;         // insert debug symbolic information
     bool symdebugref;       // insert debug information for all referenced types, too
     bool optimize;          // run optimizer
@@ -261,11 +262,29 @@ extern (C++) struct Param
     const(char)[] mapfile;
 }
 
-alias structalign_t = uint;
+extern (C++) struct structalign_t
+{
+  private:
+    ushort value = 0;  // unknown
+    enum STRUCTALIGN_DEFAULT = 1234;   // default = match whatever the corresponding C compiler does
+    bool pack;         // use #pragma pack semantics
+
+  public:
+  pure @safe @nogc nothrow:
+    bool isDefault() const { return value == STRUCTALIGN_DEFAULT; }
+    void setDefault()      { value = STRUCTALIGN_DEFAULT; }
+    bool isUnknown() const { return value == 0; }  // value is not set
+    void setUnknown()      { value = 0; }
+    void set(uint value)   { this.value = cast(ushort)value; }
+    uint get() const       { return value; }
+    bool isPack() const    { return pack; }
+    void setPack(bool pack) { this.pack = pack; }
+}
+//alias structalign_t = uint;
 
 // magic value means "match whatever the underlying C compiler does"
 // other values are all powers of 2
-enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0);
+//enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0);
 
 enum mars_ext = "d";        // for D source files
 enum doc_ext  = "html";     // for Ddoc generated files
@@ -307,6 +326,8 @@ extern (C++) struct Global
     Array!Identifier* versionids; /// command line versions and predefined versions
     Array!Identifier* debugids;   /// command line debug versions and predefined versions
 
+    bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
+
     enum recursionLimit = 500; /// number of recursive template expansions before abort
 
   nothrow:
index 6e794748beeea53b096bcf24bd8e59e6bf9d416f..2275ec517e51c59f6f157bb1d71a38aaa8efef54 100644 (file)
@@ -12,7 +12,7 @@
 
 #include "root/dcompat.h"
 #include "root/ctfloat.h"
-#include "root/outbuffer.h"
+#include "common/outbuffer.h"
 #include "root/filename.h"
 #include "compiler.h"
 
@@ -107,6 +107,7 @@ struct Param
     bool vgc;           // identify gc usage
     bool vfield;        // identify non-mutable field variables
     bool vcomplex;      // identify complex/imaginary type usage
+    bool vin;           // identify 'in' parameters
     unsigned char symdebug;  // insert debug symbolic information
     bool symdebugref;   // insert debug information for all referenced types, too
     bool optimize;      // run optimizer
@@ -238,10 +239,24 @@ struct Param
     DString mapfile;
 };
 
-typedef unsigned structalign_t;
+struct structalign_t
+{
+    unsigned short value;
+    bool pack;
+
+    bool isDefault() const;
+    void setDefault();
+    bool isUnknown() const;
+    void setUnknown();
+    void set(unsigned value);
+    unsigned get() const;
+    bool isPack() const;
+    void setPack(bool pack);
+};
+
 // magic value means "match whatever the underlying C compiler does"
 // other values are all powers of 2
-#define STRUCTALIGN_DEFAULT ((structalign_t) ~0)
+//#define STRUCTALIGN_DEFAULT ((structalign_t) ~0)
 
 const DString mars_ext = "d";
 const DString doc_ext  = "html";     // for Ddoc generated files
@@ -274,6 +289,8 @@ struct Global
     Array<class Identifier*>* versionids; // command line versions and predefined versions
     Array<class Identifier*>* debugids;   // command line debug versions and predefined versions
 
+    bool hasMainFunction;
+
     /* Start gagging. Return the current number of gagged errors
      */
     unsigned startGagging();
index debb9ca62d4f8bfe08d8d93b96d61e60a9991d4a..4018126cb262898212b111e86c6350f9af3dad2c 100644 (file)
@@ -78,6 +78,7 @@ else version (IN_GCC)
     extern (C++)
     {
         Statement asmSemantic(AsmStatement s, Scope* sc);
+        void toObjFile(Dsymbol ds, bool multiobj);
     }
 
     // stubs
index 8c31590a3115af2b1559261d5cb8fe877ff3adaa..4ff07b5de329231275d8889a99974d36c233c272 100644 (file)
@@ -44,7 +44,7 @@ import dmd.mtype;
 import dmd.nspace;
 import dmd.parse;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.statement;
@@ -909,6 +909,12 @@ public:
 
     override void visit(AttribDeclaration d)
     {
+        bool hasSTC;
+        if (auto stcd = d.isStorageClassDeclaration)
+        {
+            hasSTC = stcToBuffer(buf, stcd.stc);
+        }
+
         if (!d.decl)
         {
             buf.writeByte(';');
@@ -918,10 +924,12 @@ public:
         if (d.decl.dim == 0 || (hgs.hdrgen && d.decl.dim == 1 && (*d.decl)[0].isUnitTestDeclaration()))
         {
             // hack for bugzilla 8081
+            if (hasSTC) buf.writeByte(' ');
             buf.writestring("{}");
         }
         else if (d.decl.dim == 1)
         {
+            if (hasSTC) buf.writeByte(' ');
             (*d.decl)[0].accept(this);
             return;
         }
@@ -941,8 +949,6 @@ public:
 
     override void visit(StorageClassDeclaration d)
     {
-        if (stcToBuffer(buf, d.stc))
-            buf.writeByte(' ');
         visit(cast(AttribDeclaration)d);
     }
 
@@ -1324,11 +1330,10 @@ public:
         if (d.ident)
         {
             buf.writestring(d.ident.toString());
-            buf.writeByte(' ');
         }
         if (d.memtype)
         {
-            buf.writestring(": ");
+            buf.writestring(" : ");
             typeToBuffer(d.memtype, null, buf, hgs);
         }
         if (!d.members)
@@ -2362,7 +2367,10 @@ public:
     override void visit(DotIdExp e)
     {
         expToBuffer(e.e1, PREC.primary, buf, hgs);
-        buf.writeByte('.');
+        if (e.arrow)
+            buf.writestring("->");
+        else
+            buf.writeByte('.');
         buf.writestring(e.ident.toString());
     }
 
index e61fb23eb5d4d826dc10621b3986c547dda6e477..3ff0e894e2ac2f04c9b40d9e41ae8eeb3a883373 100644 (file)
@@ -300,7 +300,7 @@ Ldone:
  * Returns:
  *      the completed gcc asm statement, or null if errors occurred
  */
-public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
 {
     //printf("GccAsmStatement.semantic()\n");
     scope p = new Parser!ASTCodegen(sc._module, ";", false);
index 1f04dcfbc11422bc4b65948ce6fba691904c881b..1ee51533b53176e70b307bfbe40e14838f342c90 100644 (file)
@@ -500,6 +500,17 @@ immutable Msgtable[] msgtable =
     { "vector_size" },
     { "__func__" },
     { "noreturn" },
+    { "__pragma", "pragma" },
+    { "builtin_va_list", "__builtin_va_list" },
+    { "builtin_va_start", "__builtin_va_start" },
+    { "builtin_va_arg", "__builtin_va_arg" },
+    { "builtin_va_copy", "__builtin_va_copy" },
+    { "builtin_va_end", "__builtin_va_end" },
+    { "va_list_tag", "__va_list_tag" },
+    { "pack" },
+    { "show" },
+    { "push" },
+    { "pop" },
 ];
 
 
index 43a1435cd107d0f5440354e3e92960458323b1ae..8add74a14277703fb9b9530cbd028bb40f69141b 100644 (file)
@@ -16,7 +16,7 @@ import core.stdc.stdio;
 import core.stdc.string;
 import dmd.globals;
 import dmd.id;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.root.stringtable;
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
new file mode 100644 (file)
index 0000000..0dad1a8
--- /dev/null
@@ -0,0 +1,171 @@
+/**
+ * Contains semantic routines specific to ImportC
+ *
+ * Specification: C11
+ *
+ * Copyright:   Copyright (C) 2021 by The D Language Foundation, All Rights Reserved
+ * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/importc.d, _importc.d)
+ * Documentation:  https://dlang.org/phobos/dmd_importc.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/importc.d
+ */
+
+module dmd.importc;
+
+import core.stdc.stdio;
+
+import dmd.dcast;
+import dmd.dscope;
+import dmd.dsymbol;
+import dmd.expression;
+import dmd.expressionsem;
+import dmd.identifier;
+import dmd.mtype;
+
+/**************************************
+ * C11 does not allow array or function parameters.
+ * Hence, adjust those types per C11 6.7.6.3 rules.
+ * Params:
+ *      t = parameter type to adjust
+ *      sc = context
+ * Returns:
+ *      adjusted type
+ */
+Type cAdjustParamType(Type t, Scope* sc)
+{
+    if (!(sc.flags & SCOPE.Cfile))
+        return t;
+
+    Type tb = t.toBasetype();
+
+    /* C11 6.7.6.3-7 array of T is converted to pointer to T
+     */
+    if (auto ta = tb.isTypeDArray())
+    {
+        t = ta.next.pointerTo();
+    }
+    else if (auto ts = tb.isTypeSArray())
+    {
+        t = ts.next.pointerTo();
+    }
+    /* C11 6.7.6.3-8 function is converted to pointer to function
+     */
+    else if (tb.isTypeFunction())
+    {
+        t = tb.pointerTo();
+    }
+    return t;
+}
+
+/***********************************************
+ * C11 6.3.2.1-3 Convert expression that is an array of type to a pointer to type.
+ * C11 6.3.2.1-4 Convert expression that is a function to a pointer to a function.
+ * Params:
+ *  e = ImportC expression to possibly convert
+ *  sc = context
+ * Returns:
+ *  converted expression
+ */
+Expression arrayFuncConv(Expression e, Scope* sc)
+{
+    //printf("arrayFuncConv() %s\n", e.toChars());
+    if (!(sc.flags & SCOPE.Cfile))
+        return e;
+
+    auto t = e.type.toBasetype();
+    if (auto ta = t.isTypeDArray())
+    {
+        e = e.castTo(sc, ta.next.pointerTo());
+    }
+    else if (auto ts = t.isTypeSArray())
+    {
+        e = e.castTo(sc, ts.next.pointerTo());
+    }
+    else if (t.isTypeFunction())
+    {
+        e = e.addressOf();
+    }
+    else
+        return e;
+    return e.expressionSemantic(sc);
+}
+
+/****************************************
+ * Run semantic on `e`.
+ * Expression `e` evaluates to an instance of a struct.
+ * Look up `ident` as a field of that struct.
+ * Params:
+ *   e = evaluates to an instance of a struct
+ *   sc = context
+ *   id = identifier of a field in that struct
+ * Returns:
+ *   if successful `e.ident`
+ *   if not then `ErrorExp` and message is printed
+ */
+Expression fieldLookup(Expression e, Scope* sc, Identifier id)
+{
+    e = e.expressionSemantic(sc);
+    if (e.isErrorExp())
+        return e;
+
+    Dsymbol s;
+    auto t = e.type;
+    if (t.isTypePointer())
+    {
+        t = t.isTypePointer().next;
+        e = new PtrExp(e.loc, e);
+    }
+    if (auto ts = t.isTypeStruct())
+        s = ts.sym.search(e.loc, id, 0);
+    if (!s)
+    {
+        e.error("`%s` is not a member of `%s`", id.toChars(), t.toChars());
+        return ErrorExp.get();
+    }
+    Expression ef = new DotVarExp(e.loc, e, s.isDeclaration());
+    return ef.expressionSemantic(sc);
+}
+
+/****************************************
+ * C11 6.5.2.1-2
+ * Apply C semantics to `E[I]` expression.
+ * E1[E2] is lowered to *(E1 + E2)
+ * Params:
+ *      ae = ArrayExp to run semantics on
+ *      sc = context
+ * Returns:
+ *      Expression if this was a C expression with completed semantic, null if not
+ */
+Expression carraySemantic(ArrayExp ae, Scope* sc)
+{
+    if (!(sc.flags & SCOPE.Cfile))
+        return null;
+
+    auto e1 = ae.e1.expressionSemantic(sc);
+
+    assert(ae.arguments.length == 1);
+    Expression e2 = (*ae.arguments)[0];
+
+    /* CTFE cannot do pointer arithmetic, but it can index arrays.
+     * So, rewrite as an IndexExp if we can.
+     */
+    auto t1 = e1.type.toBasetype();
+    if (t1.isTypeDArray() || t1.isTypeSArray())
+    {
+        e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
+        return new IndexExp(ae.loc, e1, e2).expressionSemantic(sc);
+    }
+
+    e1 = e1.arrayFuncConv(sc);   // e1 might still be a function call
+    e2 = e2.expressionSemantic(sc);
+    auto t2 = e2.type.toBasetype();
+    if (t2.isTypeDArray() || t2.isTypeSArray())
+    {
+        return new IndexExp(ae.loc, e2, e1).expressionSemantic(sc); // swap operands
+    }
+
+    e2 = e2.arrayFuncConv(sc);
+    auto ep = new PtrExp(ae.loc, new AddExp(ae.loc, e1, e2));
+    return ep.expressionSemantic(sc);
+}
index 45e101b903a4fe93882e8687cc7d1907cacf3dbf..d036ee1635bbcd05080ca58643211e7a1681061a 100644 (file)
@@ -23,7 +23,7 @@ import dmd.globals;
 import dmd.hdrgen;
 import dmd.identifier;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.tokens;
 import dmd.visitor;
index ae8bde2ff57611cf0daac3371e1e37362373b931..5828486c6fe43caa5fe0e288551662db13d033ea 100644 (file)
@@ -31,6 +31,7 @@ import dmd.func;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
+import dmd.importc;
 import dmd.init;
 import dmd.mtype;
 import dmd.opover;
@@ -176,30 +177,35 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                             break;
                     }
                 }
-                else if (fieldi >= nfields)
+                if (j >= nfields)
                 {
-                    error(i.loc, "too many initializers for `%s`", sd.toChars());
+                    error(i.value[j].loc, "too many initializers for `%s`", sd.toChars());
                     return err();
                 }
 
                 VarDeclaration vd = sd.fields[fieldi];
                 if (elems[fieldi])
                 {
-                    error(i.loc, "duplicate initializer for field `%s`", vd.toChars());
+                    error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars());
                     errors = true;
+                    elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+                    ++fieldi;
                     continue;
                 }
 
                 // Check for @safe violations
                 if (vd.type.hasPointers)
                 {
-                    if ((t.alignment() < target.ptrsize ||
+                    if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
                          (vd.offset & (target.ptrsize - 1))) &&
                         sc.func && sc.func.setUnsafe())
                     {
-                        error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
+                        error(i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
                             sd.toChars(), vd.toChars());
                         errors = true;
+                        elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+                        ++fieldi;
+                        continue;
                     }
                 }
 
@@ -208,7 +214,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 {
                     if (vd.isOverlappedWith(v2) && elems[k])
                     {
-                        error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
+                        error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
                         errors = true;
                         continue;
                     }
@@ -222,6 +228,8 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 if (ex.op == TOK.error)
                 {
                     errors = true;
+                    elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
+                    ++fieldi;
                     continue;
                 }
 
@@ -363,10 +371,10 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             if (length > i.dim)
                 i.dim = length;
         }
-        if (t.ty == Tsarray)
+        if (auto tsa = t.isTypeSArray())
         {
-            uinteger_t edim = (cast(TypeSArray)t).dim.toInteger();
-            if (i.dim > edim)
+            uinteger_t edim = tsa.dim.toInteger();
+            if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
             {
                 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
                 return err();
@@ -398,6 +406,13 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         if (i.exp.op == TOK.error)
             return err();
         uint olderrors = global.errors;
+
+        /* ImportC: convert arrays to pointers, functions to pointers to functions
+         */
+        Type tb = t.toBasetype();
+        if (tb.isTypePointer())
+            i.exp = i.exp.arrayFuncConv(sc);
+
         /* Save the expression before ctfe
          * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
          * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
@@ -408,7 +423,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             // If the result will be implicitly cast, move the cast into CTFE
             // to avoid premature truncation of polysemous types.
             // eg real [] x = [1.1, 2.2]; should use real precision.
-            if (i.exp.implicitConvTo(t))
+            if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
             {
                 i.exp = i.exp.implicitCastTo(sc, t);
             }
@@ -416,6 +431,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             {
                 return i;
             }
+            if (sc.flags & SCOPE.Cfile)
+                /* the interpreter turns (char*)"string" into &"string"[0] which then
+                 * it cannot interpret. Resolve that case by doing optimize() first
+                 */
+                i.exp = i.exp.optimize(WANTvalue);
             i.exp = i.exp.ctfeInterpret();
             if (i.exp.op == TOK.voidExpression)
                 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
@@ -424,6 +444,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         {
             i.exp = i.exp.optimize(WANTvalue);
         }
+
         if (!global.gag && olderrors != global.errors)
         {
             return i; // Failed, suppress duplicate error messages
@@ -445,7 +466,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
             return err();
         }
-        Type tb = t.toBasetype();
         Type ti = i.exp.type.toBasetype();
         if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
         {
@@ -470,13 +490,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 goto L1;
             }
         }
-
         /* C11 6.7.9-14..15
          * Initialize an array of unknown size with a string.
-         * ImportC regards Tarray as an array of unknown size.
          * Change to static array of known size
          */
-        if (sc.flags & SCOPE.Cfile && i.exp.op == TOK.string_ && tb.ty == Tarray)
+        if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
+            tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
         {
             StringExp se = i.exp.isStringExp();
             auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
@@ -683,8 +702,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         }
 
         auto tsa = t.isTypeSArray();
-        auto ta = t.isTypeDArray();
-        if (!(tsa || ta))
+        if (!tsa)
         {
             /* Not an array. See if it is `{ exp }` which can be
              * converted to an ExpInitializer
@@ -722,19 +740,32 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         {
             //printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
             auto tn = t.nextOf().toBasetype();
-            if (auto tna = tn.isTypeDArray())
+            auto tnsa = tn.isTypeSArray();
+            if (tnsa && tnsa.isIncomplete())
             {
                 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
-                error(ci.loc, "incomplete element type `%s` not allowed", tna.toChars());
+                error(ci.loc, "incomplete element type `%s` not allowed", tnsa.toChars());
                 errors = true;
                 return 1;
             }
             if (i == dil.length)
                 return 0;
             size_t n;
-            auto tnsa = tn.isTypeSArray();
             const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
 
+            /* Run initializerSemantic on a single element.
+             */
+            Initializer elem(Initializer ie)
+            {
+                ++i;
+                auto tnx = tn; // in case initializerSemantic tries to change it
+                ie = ie.initializerSemantic(sc, tnx, needInterpret);
+                if (ie.isErrorInitializer())
+                    errors = true;
+                assert(tnx == tn); // sub-types should not be modified
+                return ie;
+            }
+
             foreach (j; 0 .. dim)
             {
                 auto di = dil[i];
@@ -751,16 +782,17 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 }
                 else if (auto tns = tn.isTypeStruct())
                 {
-                    dil[n].initializer = structs(tns);
+                    if (di.initializer.isExpInitializer())
+                    {
+                        // no braces enclosing struct initializer
+                        dil[n].initializer = structs(tns);
+                    }
+                    else
+                        dil[n].initializer = elem(di.initializer);
                 }
                 else
                 {
-                    ++i;
-                    auto tnx = tn; // in case initializerSemantic tries to change it
-                    di.initializer = di.initializer.initializerSemantic(sc, tnx, needInterpret);
-                    if (di.initializer.isErrorInitializer())
-                        errors = true;
-                    assert(tnx == tn); // sub-types should not be modified
+                    di.initializer = elem(di.initializer);
                 }
                 ++n;
                 if (i == dil.length)
@@ -770,16 +802,16 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             return n;
         }
 
-        size_t dim = ta ? dil.length : cast(size_t)tsa.dim.toInteger();
-        auto n = array(t, dim);
+        size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
+        auto newdim = array(t, dim);
 
         if (errors)
             return err();
 
-        if (ta) // array of unknown length
+        if (tsa.isIncomplete()) // array of unknown length
         {
             // Change to array of known length
-            tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, n, Type.tsize_t));
+            tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, newdim, Type.tsize_t));
             tx = tsa;       // rewrite caller's type
             ci.type = tsa;  // remember for later passes
         }
@@ -799,6 +831,39 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             return err();
         }
 
+        /* If an array of simple elements, replace with an ArrayInitializer
+         */
+        auto tnb = tn.toBasetype();
+        if (!(tnb.isTypeSArray() || tnb.isTypeStruct()))
+        {
+            auto ai = new ArrayInitializer(ci.loc);
+            ai.dim = cast(uint) dil.length;
+            ai.index.setDim(dil.length);
+            ai.value.setDim(dil.length);
+            foreach (const j; 0 .. dil.length)
+            {
+                ai.index[j] = null;
+                ai.value[j] = dil[j].initializer;
+            }
+            auto ty = tx;
+            return ai.initializerSemantic(sc, ty, needInterpret);
+        }
+
+        if (newdim < ci.initializerList.length && tnb.isTypeStruct())
+        {
+            // https://issues.dlang.org/show_bug.cgi?id=22375
+            // initializerList can be bigger than the number of actual elements
+            // to initialize for array of structs because it is not required
+            // for values to have proper bracing.
+            // i.e: These are all valid initializers for `struct{int a,b;}[3]`:
+            //      {1,2,3,4}, {{1,2},3,4}, {1,2,{3,4}}, {{1,2},{3,4}}
+            // In all examples above, the new length of the initializer list
+            // has been shortened from four elements to two. This is important,
+            // because `dil` is written back to directly, making the lowered
+            // initializer `{{1,2},{3,4}}` and not `{{1,2},{3,4},3,4}`.
+            ci.initializerList.length = newdim;
+        }
+
         return ci;
     }
 
@@ -1263,6 +1328,3 @@ private bool hasNonConstPointers(Expression e)
     }
     return false;
 }
-
-
-
diff --git a/gcc/d/dmd/intrange.h b/gcc/d/dmd/intrange.h
deleted file mode 100644 (file)
index fd61532..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by KennyTM
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/intrange.h
- */
-
-#pragma once
-
-#include "globals.h"   // for uinteger_t
-class Type;
-class Expression;
-
-/**
-This class represents a "sign-extended number", i.e. a 65-bit number, which can
-represent all built-in integer types in D. This class is mainly used for
-performing value-range propagation only, therefore all arithmetic are done with
-saturation, not wrapping as usual.
-*/
-struct SignExtendedNumber
-{
-    /// The lower 64-bit of the number.
-    uinteger_t value;
-    /// The sign (i.e. the most significant bit) of the number.
-    bool negative;
-
-    /// Create an uninitialized sign-extended number.
-    SignExtendedNumber() {}
-
-    /// Create a sign-extended number from an unsigned 64-bit number.
-    SignExtendedNumber(uinteger_t value_)
-        : value(value_), negative(false) {}
-    /// Create a sign-extended number from the lower 64-bit and the sign bit.
-    SignExtendedNumber(uinteger_t value_, bool negative_)
-        : value(value_), negative(negative_) {}
-
-    /// Create a sign-extended number from a signed 64-bit number.
-    static SignExtendedNumber fromInteger(uinteger_t value_);
-
-    /// Get the minimum or maximum value of a sign-extended number.
-    static SignExtendedNumber extreme(bool minimum);
-
-    // These names probably shouldn't be used anyway, as they are common macros
-#undef max
-#undef min
-    static SignExtendedNumber max();
-    static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
-
-    /// Check if the sign-extended number is minimum or zero.
-    bool isMinimum() const { return negative && value == 0; }
-
-    /// Compare two sign-extended number.
-    bool operator==(const SignExtendedNumber&) const;
-    bool operator!=(const SignExtendedNumber& a) const { return !(*this == a); }
-    bool operator<(const SignExtendedNumber&) const;
-    bool operator>(const SignExtendedNumber& a) const { return a < *this; }
-    bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
-    bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
-
-    /// Increase the sign-extended number by 1 (saturated).
-    SignExtendedNumber& operator++();
-    /// Compute the saturated complement of a sign-extended number.
-    SignExtendedNumber operator~() const;
-    /// Compute the saturated negation of a sign-extended number.
-    SignExtendedNumber operator-() const;
-
-    /// Compute the saturated binary and of two sign-extended number.
-    SignExtendedNumber operator&(const SignExtendedNumber&) const;
-    /// Compute the saturated binary or of two sign-extended number.
-    SignExtendedNumber operator|(const SignExtendedNumber&) const;
-    /// Compute the saturated binary xor of two sign-extended number.
-    SignExtendedNumber operator^(const SignExtendedNumber&) const;
-    /// Compute the saturated sum of two sign-extended number.
-    SignExtendedNumber operator+(const SignExtendedNumber&) const;
-    /// Compute the saturated difference of two sign-extended number.
-    SignExtendedNumber operator-(const SignExtendedNumber&) const;
-    /// Compute the saturated product of two sign-extended number.
-    SignExtendedNumber operator*(const SignExtendedNumber&) const;
-    /// Compute the saturated quotient of two sign-extended number.
-    SignExtendedNumber operator/(const SignExtendedNumber&) const;
-    /// Compute the saturated modulus of two sign-extended number.
-    SignExtendedNumber operator%(const SignExtendedNumber&) const;
-
-    /// Compute the saturated shifts of two sign-extended number.
-    SignExtendedNumber operator<<(const SignExtendedNumber&) const;
-    SignExtendedNumber operator>>(const SignExtendedNumber&) const;
-};
-
-/**
-This class represents a range of integers, denoted by its lower and upper bounds
-(inclusive).
-*/
-struct IntRange
-{
-    SignExtendedNumber imin, imax;
-
-    /// Create an uninitialized range.
-    IntRange() {}
-
-    /// Create a range consisting of a single number.
-    IntRange(const SignExtendedNumber& a)
-        : imin(a), imax(a) {}
-    /// Create a range with the lower and upper bounds.
-    IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
-        : imin(lower), imax(upper) {}
-
-    /// Create the tightest range containing all valid integers in the specified
-    /// type.
-    static IntRange fromType(Type *type);
-    /// Create the tightest range containing all valid integers in the type with
-    /// a forced signedness.
-    static IntRange fromType(Type *type, bool isUnsigned);
-
-
-    /// Create the tightest range containing all specified numbers.
-    static IntRange fromNumbers2(const SignExtendedNumber numbers[2]);
-    static IntRange fromNumbers4(const SignExtendedNumber numbers[4]);
-
-    /// Create the widest range possible.
-    static IntRange widest();
-
-    /// Cast the integer range to a signed type with the given size mask.
-    IntRange& castSigned(uinteger_t mask);
-    /// Cast the integer range to an unsigned type with the given size mask.
-    IntRange& castUnsigned(uinteger_t mask);
-    /// Cast the integer range to the dchar type.
-    IntRange& castDchar();
-
-    /// Cast the integer range to a specific type.
-    IntRange& cast(Type *type);
-    /// Cast the integer range to a specific type, forcing it to be unsigned.
-    IntRange& castUnsigned(Type *type);
-
-    /// Check if this range contains another range.
-    bool contains(const IntRange& a) const;
-
-    /// Check if this range contains 0.
-    bool containsZero() const;
-
-    /// Compute the range of the negated absolute values of the original range.
-    IntRange absNeg() const;
-
-    /// Compute the union of two ranges.
-    IntRange unionWith(const IntRange& other) const;
-    void unionOrAssign(const IntRange& other, bool& union_);
-
-    /// Dump the content of the integer range to the console.
-    const IntRange& dump(const char* funcName, Expression *e) const;
-
-    /// Split the range into two nonnegative- and negative-only subintervals.
-    void splitBySign(IntRange& negRange, bool& hasNegRange,
-                     IntRange& nonNegRange, bool& hasNonNegRange) const;
-
-    /// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
-    /// https://github.com/tgehr/d-compiler/blob/master/vrange.d
-    static SignExtendedNumber maxOr(const IntRange&, const IntRange&);
-    static SignExtendedNumber minOr(const IntRange&, const IntRange&);
-    static SignExtendedNumber maxAnd(const IntRange&, const IntRange&);
-    static SignExtendedNumber minAnd(const IntRange&, const IntRange&);
-    static void swap(IntRange&, IntRange&);
-
-    IntRange operator~() const;
-    IntRange operator-() const;
-    IntRange operator&(const IntRange&) const;
-    IntRange operator|(const IntRange&) const;
-    IntRange operator^(const IntRange&) const;
-    IntRange operator+(const IntRange&) const;
-    IntRange operator-(const IntRange&) const;
-    IntRange operator*(const IntRange&) const;
-    IntRange operator/(const IntRange&) const;
-    IntRange operator%(const IntRange&) const;
-    IntRange operator<<(const IntRange&) const;
-    IntRange operator>>(const IntRange&) const;
-};
index bfd31bc1d13697c304c8cc4b57fb4cdf13a1c52c..fef515071f9922a6a76d3669672639ca25d62a6a 100644 (file)
@@ -33,7 +33,7 @@ import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.target;
@@ -794,8 +794,8 @@ public:
             property("init", d._init.toString());
         if (d.isField())
             property("offset", d.offset);
-        if (d.alignment && d.alignment != STRUCTALIGN_DEFAULT)
-            property("align", d.alignment);
+        if (!d.alignment.isUnknown() && !d.alignment.isDefault())
+            property("align", d.alignment.get());
         objectEnd();
     }
 
index d29bdc1380615e83d83d9f0443fbb278235ba261..44a6c0665070fb20a7292ed6040512371f83a06f 100644 (file)
@@ -27,7 +27,7 @@ import dmd.expression;
 import dmd.func;
 import dmd.dmangle;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.stringtable;
 import dmd.dscope;
index afffc2dcf303786a0d22cdc8794f8f6c773d632d..e2b4199b80a23952120bd5c9ff82df8862325580 100644 (file)
@@ -26,8 +26,9 @@ import dmd.errors;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
+import dmd.root.array;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.port;
 import dmd.root.rmem;
 import dmd.root.string;
@@ -229,6 +230,8 @@ class Lexer
     ubyte long_doublesize;      /// size of C long double, 8 or D real.sizeof
     ubyte wchar_tsize;          /// size of C wchar_t, 2 or 4
 
+    structalign_t packalign;    /// current state of #pragma pack alignment (ImportC)
+
     private
     {
         const(char)* base;      // pointer to start of buffer
@@ -242,6 +245,10 @@ class Lexer
         int lastDocLine;        // last line of previous doc comment
 
         Token* tokenFreelist;
+
+        // ImportC #pragma pack stack
+        Array!Identifier* records;      // identifers (or null)
+        Array!structalign_t* packs;     // parallel alignment values
     }
 
   nothrow:
@@ -273,6 +280,7 @@ class Lexer
         this.commentToken = commentToken;
         this.inTokenStringConstant = 0;
         this.lastDocLine = 0;
+        this.packalign.setDefault();
         //initKeywords();
         /* If first line starts with '#!', ignore the line
          */
@@ -1146,6 +1154,11 @@ class Lexer
                             poundLine(n, false);
                             continue;
                         }
+                        else if (n.ident == Id.__pragma && Ccompile)
+                        {
+                            pragmaDirective(scanloc);
+                            continue;
+                        }
                         else
                         {
                             const locx = loc();
@@ -2162,7 +2175,7 @@ class Lexer
             case '.':
                 if (p[1] == '.')
                     goto Ldone; // if ".."
-                if (base == 10 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
+                if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
                     goto Ldone; // if ".identifier" or ".unicode"
                 if (base == 16 && (!ishex(p[1]) || p[1] == '_' || p[1] & 0x80))
                     goto Ldone; // if ".identifier" or ".unicode"
@@ -2911,6 +2924,220 @@ class Lexer
             error(loc, "#line integer [\"filespec\"]\\n expected");
     }
 
+    /*********************************************
+     * C11 6.10.6 Pragma directive
+     * # pragma pp-tokens(opt) new-line
+     * The C preprocessor sometimes leaves pragma directives in
+     * the preprocessed output. Ignore them.
+     * Upon return, p is at start of next line.
+     */
+    private void pragmaDirective(const ref Loc loc)
+    {
+        Token n;
+        scan(&n);
+        if (n.value == TOK.identifier && n.ident == Id.pack)
+            return pragmaPack(loc);
+        skipToNextLine();
+    }
+
+    /*********
+     * ImportC
+     * # pragma pack
+     * https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
+     * https://docs.microsoft.com/en-us/cpp/preprocessor/pack
+     * Scanner is on the `pack`
+     * Params:
+     *  startloc = location to use for error messages
+     */
+    private void pragmaPack(const ref Loc startloc)
+    {
+        const loc = startloc;
+        Token n;
+        scan(&n);
+        if (n.value != TOK.leftParenthesis)
+        {
+            error(loc, "left parenthesis expected to follow `#pragma pack`");
+            skipToNextLine();
+            return;
+        }
+
+        void closingParen()
+        {
+            if (n.value != TOK.rightParenthesis)
+            {
+                error(loc, "right parenthesis expected to close `#pragma pack(`");
+            }
+            skipToNextLine();
+        }
+
+        void setPackAlign(ref const Token t)
+        {
+            const n = t.unsvalue;
+            if (n < 1 || n & (n - 1) || ushort.max < n)
+                error(loc, "pack must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
+            packalign.set(cast(uint)n);
+            packalign.setPack(true);
+        }
+
+        scan(&n);
+
+        if (!records)
+        {
+            records = new Array!Identifier;
+            packs = new Array!structalign_t;
+        }
+
+        /* # pragma pack ( show )
+         */
+        if (n.value == TOK.identifier && n.ident == Id.show)
+        {
+            if (packalign.isDefault())
+                warning(startloc, "current pack attribute is default");
+            else
+                warning(startloc, "current pack attribute is %d", packalign.get());
+            scan(&n);
+            return closingParen();
+        }
+        /* # pragma pack ( push )
+         * # pragma pack ( push , identifier )
+         * # pragma pack ( push , integer )
+         * # pragma pack ( push , identifier , integer )
+         */
+        if (n.value == TOK.identifier && n.ident == Id.push)
+        {
+            scan(&n);
+            Identifier record = null;
+            if (n.value == TOK.comma)
+            {
+                scan(&n);
+                if (n.value == TOK.identifier)
+                {
+                    record = n.ident;
+                    scan(&n);
+                    if (n.value == TOK.comma)
+                    {
+                        scan(&n);
+                        if (n.value == TOK.int32Literal)
+                        {
+                            setPackAlign(n);
+                            scan(&n);
+                        }
+                        else
+                            error(loc, "alignment value expected, not `%s`", n.toChars());
+                    }
+                }
+                else if (n.value == TOK.int32Literal)
+                {
+                    setPackAlign(n);
+                    scan(&n);
+                }
+                else
+                    error(loc, "alignment value expected, not `%s`", n.toChars());
+            }
+            this.records.push(record);
+            this.packs.push(packalign);
+            return closingParen();
+        }
+        /* # pragma pack ( pop )
+         * # pragma pack ( pop PopList )
+         * PopList :
+         *    , IdentifierOrInteger
+         *    , IdentifierOrInteger PopList
+         * IdentifierOrInteger:
+         *      identifier
+         *      integer
+         */
+        if (n.value == TOK.identifier && n.ident == Id.pop)
+        {
+            scan(&n);
+            while (n.value == TOK.comma)
+            {
+                scan(&n);
+                if (n.value == TOK.identifier)
+                {
+                    for (size_t len = this.records.length; len; --len)
+                    {
+                        if ((*this.records)[len - 1] == n.ident)
+                        {
+                            packalign = (*this.packs)[len - 1];
+                            this.records.setDim(len - 1);
+                            this.packs.setDim(len - 1);
+                            break;
+                        }
+                    }
+                    scan(&n);
+                }
+                else if (n.value == TOK.int32Literal)
+                {
+                    setPackAlign(n);
+                    this.records.push(null);
+                    this.packs.push(packalign);
+                    scan(&n);
+                }
+            }
+            return closingParen();
+        }
+        /* # pragma pack ( integer )
+         */
+        if (n.value == TOK.int32Literal)
+        {
+            setPackAlign(n);
+            scan(&n);
+            return closingParen();
+        }
+        /* # pragma pack ( )
+         */
+        if (n.value == TOK.rightParenthesis)
+        {
+            packalign.setDefault();
+            return closingParen();
+        }
+
+        error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
+        skipToNextLine();
+    }
+
+    /***************************************
+     * Scan forward to start of next line.
+     */
+    private void skipToNextLine()
+    {
+        while (1)
+        {
+            switch (*p)
+            {
+            case 0:
+            case 0x1A:
+                return; // do not advance p
+
+            case '\n':
+                ++p;
+                break;
+
+            case '\r':
+                ++p;
+                if (p[0] == '\n')
+                   ++p;
+                break;
+
+            default:
+                if (*p & 0x80)
+                {
+                    const u = decodeUTF();
+                    if (u == PS || u == LS)
+                    {
+                        ++p;
+                        break;
+                    }
+                }
+                ++p;
+                continue;
+            }
+            break;
+        }
+        endOfLine();
+    }
+
     /********************************************
      * Decode UTF character.
      * Issue error messages for invalid sequences.
@@ -3106,8 +3333,10 @@ class Lexer
         return p;
     }
 
-private:
-    void endOfLine() pure @nogc @safe
+    /**************************
+     * `p` should be at start of next line
+     */
+    private void endOfLine() pure @nogc @safe
     {
         scanloc.linnum++;
         line = p;
diff --git a/gcc/d/dmd/lexer.h b/gcc/d/dmd/lexer.h
deleted file mode 100644 (file)
index b36e7f7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/lexer.h
- */
-
-#pragma once
-
-#include "root/root.h"
-#include "globals.h"
-#include "tokens.h"
-
-struct StringTable;
-class Identifier;
-
-class Lexer
-{
-public:
-    static OutBuffer stringbuffer;
-
-    Loc scanloc;                // for error messages
-
-    const utf8_t *base;        // pointer to start of buffer
-    const utf8_t *end;         // past end of buffer
-    const utf8_t *p;           // current character
-    const utf8_t *line;        // start of current line
-    Token token;
-    bool doDocComment;          // collect doc comment information
-    bool anyToken;              // !=0 means seen at least one token
-    bool commentToken;          // !=0 means comments are TOKcomment's
-    bool errors;                // errors occurred during lexing or parsing
-
-    Lexer(const char *filename,
-        const utf8_t *base, size_t begoffset, size_t endoffset,
-        bool doDocComment, bool commentToken);
-
-    TOK nextToken();
-    TOK peekNext();
-    TOK peekNext2();
-    void scan(Token *t);
-    Token *peek(Token *t);
-    Token *peekPastParen(Token *t);
-    unsigned escapeSequence();
-    TOK wysiwygStringConstant(Token *t, int tc);
-    TOK hexStringConstant(Token *t);
-    TOK delimitedStringConstant(Token *t);
-    TOK tokenStringConstant(Token *t);
-    TOK escapeStringConstant(Token *t);
-    TOK charConstant(Token *t);
-    void stringPostfix(Token *t);
-    TOK number(Token *t);
-    TOK inreal(Token *t);
-
-    Loc loc()
-    {
-        scanloc.charnum = (unsigned)(1 + p-line);
-        return scanloc;
-    }
-
-    void error(const char *format, ...);
-    void error(Loc loc, const char *format, ...);
-    void deprecation(const char *format, ...);
-    void poundLine();
-    unsigned decodeUTF();
-    void getDocComment(Token *t, unsigned lineComment);
-
-    static const utf8_t *combineComments(const utf8_t *c1, const utf8_t *c2);
-
-private:
-    void endOfLine();
-};
diff --git a/gcc/d/dmd/macro.h b/gcc/d/dmd/macro.h
deleted file mode 100644 (file)
index 80ec36e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/macro.h
- */
-
-#pragma once
-
-#include "root/dsystem.h"
-#include "root/port.h"
-
-
-struct Macro
-{
-  private:
-    Macro *next;                // next in list
-
-    const utf8_t *name;        // macro name
-    size_t namelen;             // length of macro name
-
-    const utf8_t *text;        // macro replacement text
-    size_t textlen;             // length of replacement text
-
-    int inuse;                  // macro is in use (don't expand)
-
-    Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
-    Macro *search(const utf8_t *name, size_t namelen);
-
-  public:
-    static Macro *define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
-
-    void expand(OutBuffer *buf, size_t start, size_t *pend,
-        const utf8_t *arg, size_t arglen);
-};
diff --git a/gcc/d/dmd/mars.h b/gcc/d/dmd/mars.h
deleted file mode 100644 (file)
index 9b9c278..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/mars.h
- */
-
-#pragma once
-
-/*
-It is very important to use version control macros correctly - the
-idea is that host and target are independent. If these are done
-correctly, cross compilers can be built.
-The host compiler and host operating system are also different,
-and are predefined by the host compiler. The ones used in
-dmd are:
-
-Macros defined by the compiler, not the code:
-
-    Compiler:
-        __DMC__         Digital Mars compiler
-        _MSC_VER        Microsoft compiler
-        __GNUC__        Gnu compiler
-        __clang__       Clang compiler
-
-    Host operating system:
-        _WIN32          Microsoft NT, Windows 95, Windows 98, Win32s,
-                        Windows 2000, Win XP, Vista
-        _WIN64          Windows for AMD64
-        __linux__       Linux
-        __APPLE__       Mac OSX
-        __FreeBSD__     FreeBSD
-        __OpenBSD__     OpenBSD
-        __sun           Solaris, OpenSolaris, SunOS, OpenIndiana, etc
-
-For the target systems, there are the target operating system and
-the target object file format:
-
-    Target operating system:
-        TARGET_WINDOS   Covers 32 bit windows and 64 bit windows
-        TARGET_LINUX    Covers 32 and 64 bit linux
-        TARGET_OSX      Covers 32 and 64 bit Mac OSX
-        TARGET_FREEBSD  Covers 32 and 64 bit FreeBSD
-        TARGET_OPENBSD  Covers 32 and 64 bit OpenBSD
-        TARGET_SOLARIS  Covers 32 and 64 bit Solaris
-
-    It is expected that the compiler for each platform will be able
-    to generate 32 and 64 bit code from the same compiler binary.
-
-    There are currently no macros for byte endianness order.
- */
-
-
-#include "root/dsystem.h"
-
-#ifdef __DMC__
-#ifdef DEBUG
-#undef assert
-#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
-#endif
-#endif
-
-void unittests();
-
-struct OutBuffer;
-
-#include "globals.h"
-
-#include "root/ctfloat.h"
-
-#include "complex_t.h"
-
-#include "errors.h"
-
-class Dsymbol;
-class Library;
-struct File;
-void obj_start(char *srcfile);
-void obj_end(Library *library, File *objfile);
-void obj_append(Dsymbol *s);
-void obj_write_deferred(Library *library);
-
-/// Utility functions used by both main and frontend.
-void readFile(Loc loc, File *f);
-void writeFile(Loc loc, File *f);
-void ensurePathToNameExists(Loc loc, const char *name);
-
-const char *importHint(const char *s);
-/// Little helper function for writing out deps.
-void escapePath(OutBuffer *buf, const char *fname);
index 969290c476ccad03efb91fc38ab152713b21640a..fe4c73a021cd05e10d03849d30cd3191fe72c0ad 100644 (file)
@@ -119,7 +119,7 @@ public:
 
     static Module* create(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
 
-    static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
+    static Module *load(const Loc &loc, Identifiers *packages, Identifier *ident);
 
     const char *kind() const;
     bool read(const Loc &loc); // read file, returns 'true' if succeed, 'false' otherwise.
index 80e47918f2da03bbc6e0f0c047a3d87c16769010..a21924b3aacb5ad77345b42af9b56bb46a4f3bae 100644 (file)
@@ -43,7 +43,7 @@ import dmd.identifier;
 import dmd.init;
 import dmd.opover;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.root.stringtable;
@@ -237,6 +237,7 @@ enum DotExpFlag
 {
     gag     = 1,    // don't report "not a property" error and just return null
     noDeref = 2,    // the use of the expression will not attempt a dereference
+    noAliasThis = 4, // don't do 'alias this' resolution
 }
 
 /// Result of a check whether two types are covariant
@@ -426,6 +427,13 @@ extern (C++) abstract class Type : ASTNode
         return DYNCAST.type;
     }
 
+    /// Returns a non-zero unique ID for this Type, or returns 0 if the Type does not (yet) have a unique ID.
+    /// If `semantic()` has not been run, 0 is returned.
+    final size_t getUniqueID() const
+    {
+        return cast(size_t) deco;
+    }
+
     extern (D)
     final Mcache* getMcache()
     {
@@ -2298,7 +2306,9 @@ extern (C++) abstract class Type : ASTNode
      */
     structalign_t alignment()
     {
-        return STRUCTALIGN_DEFAULT;
+        structalign_t s;
+        s.setDefault();
+        return s;
     }
 
     /***************************************
@@ -3532,6 +3542,13 @@ extern (C++) final class TypeSArray : TypeArray
         this.dim = dim;
     }
 
+    extern (D) this(Type t)  // for incomplete type
+    {
+        super(Tsarray, t);
+        //printf("TypeSArray()\n");
+        this.dim = new IntegerExp(0);
+    }
+
     override const(char)* kind() const
     {
         return "sarray";
@@ -3546,6 +3563,15 @@ extern (C++) final class TypeSArray : TypeArray
         return result;
     }
 
+    /***
+     * C11 6.7.6.2-4 incomplete array type
+     * Returns: true if incomplete type
+     */
+    bool isIncomplete()
+    {
+        return dim.isIntegerExp() && dim.isIntegerExp().getInteger() == 0;
+    }
+
     override d_uns64 size(const ref Loc loc)
     {
         //printf("TypeSArray::size()\n");
@@ -3952,65 +3978,37 @@ extern (C++) final class TypePointer : TypeNext
         if (equals(to))
             return MATCH.exact;
 
-        if (next.ty == Tfunction)
-        {
-            if (auto tp = to.isTypePointer())
-            {
-                if (tp.next.ty == Tfunction)
-                {
-                    if (next.equals(tp.next))
-                        return MATCH.constant;
-
-                    if (next.covariant(tp.next) == Covariant.yes)
-                    {
-                        Type tret = this.next.nextOf();
-                        Type toret = tp.next.nextOf();
-                        if (tret.ty == Tclass && toret.ty == Tclass)
-                        {
-                            /* https://issues.dlang.org/show_bug.cgi?id=10219
-                             * Check covariant interface return with offset tweaking.
-                             * interface I {}
-                             * class C : Object, I {}
-                             * I function() dg = function C() {}    // should be error
-                             */
-                            int offset = 0;
-                            if (toret.isBaseOf(tret, &offset) && offset != 0)
-                                return MATCH.nomatch;
-                        }
-                        return MATCH.convert;
-                    }
-                }
-                else if (tp.next.ty == Tvoid)
-                {
-                    // Allow conversions to void*
-                    return MATCH.convert;
-                }
-            }
+        // Only convert between pointers
+        auto tp = to.isTypePointer();
+        if (!tp)
             return MATCH.nomatch;
-        }
-        else if (auto tp = to.isTypePointer())
+
+        assert(this.next);
+        assert(tp.next);
+
+        // Conversion to void*
+        if (tp.next.ty == Tvoid)
         {
-            assert(tp.next);
+            // Function pointer conversion doesn't check constness?
+            if (this.next.ty == Tfunction)
+                return MATCH.convert;
 
             if (!MODimplicitConv(next.mod, tp.next.mod))
                 return MATCH.nomatch; // not const-compatible
 
-            /* Alloc conversion to void*
-             */
-            if (next.ty != Tvoid && tp.next.ty == Tvoid)
-            {
-                return MATCH.convert;
-            }
-
-            MATCH m = next.constConv(tp.next);
-            if (m > MATCH.nomatch)
-            {
-                if (m == MATCH.exact && mod != to.mod)
-                    m = MATCH.constant;
-                return m;
-            }
+            return this.next.ty == Tvoid ? MATCH.constant : MATCH.convert;
         }
-        return MATCH.nomatch;
+
+        // Conversion between function pointers
+        if (auto thisTf = this.next.isTypeFunction())
+            return thisTf.implicitPointerConv(tp.next);
+
+        // Default, no implicit conversion between the pointer targets
+        MATCH m = next.constConv(tp.next);
+
+        if (m == MATCH.exact && mod != to.mod)
+            m = MATCH.constant;
+        return m;
     }
 
     override MATCH constConv(Type to)
@@ -4760,7 +4758,10 @@ extern (C++) final class TypeFunction : TypeNext
                             }
                         }
                         else
-                            m = arg.implicitConvTo(tprm);
+                        {
+                            import dmd.dcast : cimplicitConvTo;
+                            m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm);
+                        }
                     }
                     //printf("match %d\n", m);
                 }
@@ -4971,6 +4972,47 @@ extern (C++) final class TypeFunction : TypeNext
         return MATCH.nomatch;
     }
 
+    /+
+     + Checks whether this function type is convertible to ` to`
+     + when used in a function pointer / delegate.
+     +
+     + Params:
+     +   to = target type
+     +
+     + Returns:
+     +   MATCH.nomatch: `to` is not a covaraint function
+     +   MATCH.convert: `to` is a covaraint function
+     +   MATCH.exact:   `to` is identical to this function
+     +/
+    private MATCH implicitPointerConv(Type to)
+    {
+        assert(to);
+
+        if (this == to)
+            return MATCH.constant;
+
+        if (this.covariant(to) == Covariant.yes)
+        {
+            Type tret = this.nextOf();
+            Type toret = to.nextOf();
+            if (tret.ty == Tclass && toret.ty == Tclass)
+            {
+                /* https://issues.dlang.org/show_bug.cgi?id=10219
+                 * Check covariant interface return with offset tweaking.
+                 * interface I {}
+                 * class C : Object, I {}
+                 * I function() dg = function C() {}    // should be error
+                 */
+                int offset = 0;
+                if (toret.isBaseOf(tret, &offset) && offset != 0)
+                    return MATCH.nomatch;
+            }
+            return MATCH.convert;
+        }
+
+        return MATCH.nomatch;
+    }
+
     /** Extends TypeNext.constConv by also checking for matching attributes **/
     override MATCH constConv(Type to)
     {
@@ -5262,27 +5304,16 @@ extern (C++) final class TypeDelegate : TypeNext
         if (this == to)
             return MATCH.exact;
 
-        version (all)
+        if (auto toDg = to.isTypeDelegate())
         {
-            // not allowing covariant conversions because it interferes with overriding
-            if (to.ty == Tdelegate && this.nextOf().covariant(to.nextOf()) == Covariant.yes)
-            {
-                Type tret = this.next.nextOf();
-                Type toret = (cast(TypeDelegate)to).next.nextOf();
-                if (tret.ty == Tclass && toret.ty == Tclass)
-                {
-                    /* https://issues.dlang.org/show_bug.cgi?id=10219
-                     * Check covariant interface return with offset tweaking.
-                     * interface I {}
-                     * class C : Object, I {}
-                     * I delegate() dg = delegate C() {}    // should be error
-                     */
-                    int offset = 0;
-                    if (toret.isBaseOf(tret, &offset) && offset != 0)
-                        return MATCH.nomatch;
-                }
-                return MATCH.convert;
-            }
+            MATCH m = this.next.isTypeFunction().implicitPointerConv(toDg.next);
+
+            // Retain the old behaviour for this refactoring
+            // Should probably be changed to constant to match function pointers
+            if (m > MATCH.convert)
+                m = MATCH.convert;
+
+            return m;
         }
 
         return MATCH.nomatch;
@@ -5516,6 +5547,11 @@ extern (C++) final class TypeIdentifier : TypeQualified
         this.ident = ident;
     }
 
+    static TypeIdentifier create(const ref Loc loc, Identifier ident)
+    {
+        return new TypeIdentifier(loc, ident);
+    }
+
     override const(char)* kind() const
     {
         return "identifier";
@@ -5737,7 +5773,7 @@ extern (C++) final class TypeStruct : Type
 
     override structalign_t alignment()
     {
-        if (sym.alignment == 0)
+        if (sym.alignment.isUnknown())
             sym.size(sym.loc);
         return sym.alignment;
     }
@@ -6519,6 +6555,29 @@ extern (C++) final class TypeTuple : Type
         return false;
     }
 
+    override MATCH implicitConvTo(Type to)
+    {
+        if (this == to)
+            return MATCH.exact;
+        if (auto tt = to.isTypeTuple())
+        {
+            if (arguments.dim == tt.arguments.dim)
+            {
+                MATCH m = MATCH.exact;
+                for (size_t i = 0; i < tt.arguments.dim; i++)
+                {
+                    Parameter arg1 = (*arguments)[i];
+                    Parameter arg2 = (*tt.arguments)[i];
+                    MATCH mi = arg1.type.implicitConvTo(arg2.type);
+                    if (mi < m)
+                        m = mi;
+                }
+                return m;
+            }
+        }
+        return MATCH.nomatch;
+    }
+
     override void accept(Visitor v)
     {
         v.visit(this);
index cdf221f55f762ed367650ef23ae09ca700e0a527..430b39b205c94fbf6f12c66548fedaba1a3e7eb9 100644 (file)
@@ -224,6 +224,7 @@ public:
     bool equivalent(Type *t);
     // kludge for template.isType()
     DYNCAST dyncast() const { return DYNCAST_TYPE; }
+    size_t getUniqueID() const;
     Covariant covariant(Type *t, StorageClass *pstc = NULL);
     const char *toChars() const;
     char *toPrettyChars(bool QualifyTypes = false);
@@ -446,6 +447,7 @@ public:
 
     const char *kind();
     TypeSArray *syntaxCopy();
+    bool isIncomplete();
     d_uns64 size(const Loc &loc);
     unsigned alignsize();
     bool isString();
@@ -582,6 +584,7 @@ struct ParameterList
     Parameters* parameters;
     StorageClass stc;
     VarArg varargs;
+    bool hasIdentifierList; // true if C identifier-list style
 
     size_t length();
     Parameter *operator[](size_t i) { return Parameter::getNth(parameters, i); }
@@ -711,6 +714,7 @@ public:
     Identifier *ident;
     Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
 
+    static TypeIdentifier *create(const Loc &loc, Identifier *ident);
     const char *kind();
     TypeIdentifier *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
index 7719ccfe2978ed7b4dc1d858708b2533c0e78f1b..605e9f3bfdd94ba55f7c07aa336b32bc2e47cda8 100644 (file)
@@ -43,7 +43,7 @@ import dmd.tokens;
 import dmd.visitor;
 
 import dmd.root.bitarray;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 
 /**********************************
  * Perform ownership/borrowing checks for funcdecl.
index 85e371e6e63d5465d167003dd0f30191f1b966e1..eb4ba1db20de663d55e35387e8ac54115e1f97e3 100644 (file)
@@ -38,7 +38,7 @@ import dmd.id;
 import dmd.identifier;
 import dmd.mtype;
 import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.stringtable;
 import dmd.target;
 import dmd.tokens;
index 4ef55f3acc9a4fd1c8ec35584dc60e6f71737005..ff03a6e0d3cc0b6ced3a6c51398453d2d4a19e40 100644 (file)
@@ -213,9 +213,13 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE
     if (isRecursiveAliasThis(e.att1, e.e1.type))
         return null;
     //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
-    Expression e1 = new DotIdExp(e.loc, e.e1, ad.aliasthis.ident);
     BinExp be = cast(BinExp)e.copy();
-    be.e1 = e1;
+    // Resolve 'alias this' but in case of assigment don't resolve properties yet
+    // because 'e1 = e2' could mean 'e1(e2)' or 'e1() = e2'
+    bool findOnly = (e.op == TOK.assign);
+    be.e1 = resolveAliasThis(sc, e.e1, true, findOnly);
+    if (!be.e1)
+        return null;
 
     Expression result;
     if (be.op == TOK.concatenateAssign)
@@ -237,9 +241,10 @@ private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinE
     if (isRecursiveAliasThis(e.att2, e.e2.type))
         return null;
     //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
-    Expression e2 = new DotIdExp(e.loc, e.e2, ad.aliasthis.ident);
     BinExp be = cast(BinExp)e.copy();
-    be.e2 = e2;
+    be.e2 = resolveAliasThis(sc, e.e2, true);
+    if (!be.e2)
+        return null;
 
     Expression result;
     if (be.op == TOK.concatenateAssign)
@@ -1744,11 +1749,31 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f
         else if (m == match && m > MATCH.nomatch)
         {
             assert(fd_best);
-            /* Ignore covariant matches, as later on it can be redone
-             * after the opApply delegate has its attributes inferred.
-             */
-            if (tf.covariant(fd_best.type) != Covariant.yes &&
-                fd_best.type.covariant(tf) != Covariant.yes)
+            auto bestTf = fd_best.type.isTypeFunction();
+            assert(bestTf);
+
+            // Found another overload with different attributes?
+            // e.g. @system vs. @safe opApply
+            bool ambig = tf.attributesEqual(bestTf);
+
+            // opApplies with identical attributes could still accept
+            // different function bodies as delegate
+            // => different parameters or attributes
+            if (ambig)
+            {
+                // Fetch the delegates that receive the function body
+                auto tfBody = tf.parameterList[0].type.isTypeDelegate().next;
+                assert(tfBody);
+
+                auto bestBody = bestTf.parameterList[0].type.isTypeDelegate().next;
+                assert(bestBody);
+
+                // Ignore covariant matches, as later on it can be redone
+                // after the opApply delegate has its attributes inferred.
+                ambig = !(tfBody.covariant(bestBody) == Covariant.yes || bestBody.covariant(tfBody) == Covariant.yes);
+            }
+
+            if (ambig)
                 fd_ambig = f;                           // not covariant, so ambiguous
         }
         return 0;               // continue
index 3ae30619a207176c8542fdc7b1c00e9eb4ab824c..9f116fe850968e4767a54931bd7f11628f2308ea 100644 (file)
@@ -697,6 +697,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                 // See if we can remove an unnecessary cast
                 ClassDeclaration cdfrom = e.e1.type.isClassHandle();
                 ClassDeclaration cdto = e.type.isClassHandle();
+                if (cdfrom.errors || cdto.errors)
+                    return error();
                 if (cdto == ClassDeclaration.object && !cdfrom.isInterfaceDeclaration())
                     goto L1;    // can always convert a class to Object
                 // Need to determine correct offset before optimizing away the cast.
index 21042dd80ea0e114e670b92cea2db93873a803ee..f00ceb6cc937f806f4ad87cbdb0d2f92a1190646 100644 (file)
@@ -22,7 +22,7 @@ import dmd.identifier;
 import dmd.lexer;
 import dmd.errors;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.root.string;
@@ -556,6 +556,9 @@ class Parser(AST) : Lexer
                     {
                     case TOK.leftParenthesis:
                         {
+                            // MixinType
+                            if (isDeclaration(&token, NeedDeclaratorId.mustIfDstyle, TOK.reserved, null))
+                                goto Ldeclaration;
                             // mixin(string)
                             nextToken();
                             auto exps = parseArguments();
@@ -2954,6 +2957,8 @@ class Parser(AST) : Lexer
                         // Don't call nextToken again.
                     }
                 case TOK.in_:
+                    if (global.params.vin)
+                        message(scanloc, "Usage of 'in' on parameter");
                     stc = STC.in_;
                     goto L2;
 
@@ -5408,6 +5413,11 @@ class Parser(AST) : Lexer
                     stc = STC.scope_;
                     goto Lagain;
 
+                case TOK.out_:
+                    error("cannot declare `out` loop variable, use `ref` instead");
+                    stc = STC.out_;
+                    goto Lagain;
+
                 case TOK.enum_:
                     stc = STC.manifest;
                     goto Lagain;
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
deleted file mode 100644 (file)
index a2ad478..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/parse.h
- */
-
-#pragma once
-
-#include "arraytypes.h"
-#include "lexer.h"
-#include "enum.h"
-
-class Type;
-class TypeQualified;
-class Expression;
-class Declaration;
-class Statement;
-class Import;
-class Initializer;
-class FuncDeclaration;
-class CtorDeclaration;
-class PostBlitDeclaration;
-class DtorDeclaration;
-class StaticCtorDeclaration;
-class StaticDtorDeclaration;
-class SharedStaticCtorDeclaration;
-class SharedStaticDtorDeclaration;
-class ConditionalDeclaration;
-class InvariantDeclaration;
-class UnitTestDeclaration;
-class NewDeclaration;
-class DeleteDeclaration;
-class Condition;
-class Module;
-struct ModuleDeclaration;
-class TemplateDeclaration;
-class TemplateInstance;
-class StaticAssert;
-struct PrefixAttributes;
-
-/************************************
- * These control how parseStatement() works.
- */
-
-enum ParseStatementFlags
-{
-    PSsemi = 1,         // empty ';' statements are allowed, but deprecated
-    PSscope = 2,        // start a new scope
-    PScurly = 4,        // { } statement is required
-    PScurlyscope = 8,   // { } starts a new scope
-    PSsemi_ok = 0x10    // empty ';' are really ok
-};
-
-
-class Parser : public Lexer
-{
-public:
-    Module *mod;
-    ModuleDeclaration *md;
-    LINK linkage;
-    CPPMANGLE cppmangle;
-    Loc endloc;                 // set to location of last right curly
-    int inBrackets;             // inside [] of array index or slice
-    Loc lookingForElse;         // location of lonely if looking for an else
-
-    Parser(Loc loc, Module *module, const utf8_t *base, size_t length, bool doDocComment);
-    Parser(Module *module, const utf8_t *base, size_t length, bool doDocComment);
-
-    Dsymbols *parseModule();
-    Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL, PrefixAttributes *pAttrs = NULL);
-    Dsymbols *parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment);
-    Dsymbols *parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs = NULL);
-    StorageClass appendStorageClass(StorageClass storageClass, StorageClass stc, bool deprec = false);
-    StorageClass parseAttribute(Expressions **pexps);
-    StorageClass parsePostfix(StorageClass storageClass, Expressions **pudas);
-    StorageClass parseTypeCtor();
-    Expression *parseConstraint();
-    TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false);
-    TemplateParameters *parseTemplateParameterList(int flag = 0);
-    Dsymbol *parseMixin();
-    Objects *parseTemplateArguments();
-    RootObject *parseTypeOrAssignExp(TOK endtoken = TOKreserved);
-    Objects *parseTemplateArgumentList();
-    Objects *parseTemplateSingleArgument();
-    StaticAssert *parseStaticAssert();
-    TypeQualified *parseTypeof();
-    Type *parseVector();
-    LINK parseLinkage(Identifiers **, CPPMANGLE *, bool *);
-    Identifiers *parseQualifiedIdentifier(const char *entity);
-    Condition *parseDebugCondition();
-    Condition *parseVersionCondition();
-    Condition *parseStaticIfCondition();
-    Dsymbol *parseCtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseDtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseStaticCtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseStaticDtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseSharedStaticCtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseSharedStaticDtor(PrefixAttributes *pAttrs);
-    Dsymbol *parseInvariant(PrefixAttributes *pAttrs);
-    Dsymbol *parseUnitTest(PrefixAttributes *pAttrs);
-    Dsymbol *parseNew(PrefixAttributes *pAttrs);
-    Dsymbol *parseDelete(PrefixAttributes *pAttrs);
-    Parameters *parseParameters(VarArg *pvarargs, TemplateParameters **tpl = NULL);
-    EnumDeclaration *parseEnum();
-    Dsymbol *parseAggregate();
-    BaseClasses *parseBaseClasses();
-    Dsymbols *parseImport();
-    Type *parseType(Identifier **pident = NULL, TemplateParameters **ptpl = NULL);
-    Type *parseBasicType(bool dontLookDotIdents = false);
-    Type *parseBasicTypeStartingAt(TypeQualified *tid, bool dontLookDotIdents);
-    Type *parseBasicType2(Type *t);
-    Type *parseDeclarator(Type *t, int *alt, Identifier **pident,
-        TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int *pdisable = NULL, Expressions **pudas = NULL);
-    void parseStorageClasses(StorageClass &storage_class, LINK &link, bool &setAlignment, Expression *&ealign, Expressions *&udas);
-    Dsymbols *parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, const utf8_t *comment);
-    Dsymbol *parseFunctionLiteral();
-    FuncDeclaration *parseContracts(FuncDeclaration *f);
-    void checkDanglingElse(Loc elseloc);
-    void checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident);
-    Statement *parseForeach(Loc loc, bool *isRange, bool isDecl);
-    Dsymbol *parseForeachStaticDecl(Loc loc, Dsymbol **pLastDecl);
-    Statement *parseForeachStatic(Loc loc);
-    /** endPtr used for documented unittests */
-    Statement *parseStatement(int flags, const utf8_t** endPtr = NULL, Loc *pEndloc = NULL);
-    Initializer *parseInitializer();
-    Expression *parseDefaultInitExp();
-    void check(Loc loc, TOK value);
-    void check(TOK value);
-    void check(TOK value, const char *string);
-    void checkParens(TOK value, Expression *e);
-    bool isDeclaration(Token *t, int needId, TOK endtok, Token **pt);
-    bool isBasicType(Token **pt);
-    bool isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, bool allowAltSyntax = true);
-    bool isParameters(Token **pt);
-    bool isExpression(Token **pt);
-    bool skipParens(Token *t, Token **pt);
-    bool skipParensIf(Token *t, Token **pt);
-    bool skipAttributes(Token *t, Token **pt);
-
-    Expression *parseExpression();
-    Expression *parsePrimaryExp();
-    Expression *parseUnaryExp();
-    Expression *parsePostExp(Expression *e);
-    Expression *parseMulExp();
-    Expression *parseAddExp();
-    Expression *parseShiftExp();
-    Expression *parseCmpExp();
-    Expression *parseAndExp();
-    Expression *parseXorExp();
-    Expression *parseOrExp();
-    Expression *parseAndAndExp();
-    Expression *parseOrOrExp();
-    Expression *parseCondExp();
-    Expression *parseAssignExp();
-
-    Expressions *parseArguments();
-
-    Expression *parseNewExp(Expression *thisexp);
-
-    void addComment(Dsymbol *s, const utf8_t *blockComment);
-};
-
-// Operator precedence - greater values are higher precedence
-
-enum PREC
-{
-    PREC_zero,
-    PREC_expr,
-    PREC_assign,
-    PREC_cond,
-    PREC_oror,
-    PREC_andand,
-    PREC_or,
-    PREC_xor,
-    PREC_and,
-    PREC_equal,
-    PREC_rel,
-    PREC_shift,
-    PREC_add,
-    PREC_mul,
-    PREC_pow,
-    PREC_unary,
-    PREC_primary
-};
-
-extern PREC precedence[TOKMAX];
-
-void initPrecedence();
index 3f12b173357f0149a78f816c89f1dd04f052a695..414d6f665f53f8fd8094bb16cfd1865714e14d73 100644 (file)
@@ -59,7 +59,7 @@ extern (C++) final class PrintASTVisitor : Visitor
         printIndent(indent);
 
         import dmd.hdrgen : floatToBuffer;
-        import dmd.root.outbuffer : OutBuffer;
+        import dmd.common.outbuffer : OutBuffer;
         OutBuffer buf;
         floatToBuffer(e.type, e.value, &buf, false);
         printf("Real %s %s\n", buf.peekChars(), e.type ? e.type.toChars() : "");
index 539b940d6fb62a94eee05d857f33648f00ad763a..e062d93da46dde2378066f48a55780b0845d3d31 100644 (file)
@@ -11,7 +11,6 @@
 | [hash.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d)               | Calculate a hash for a byte array                                                          |
 | [longdouble.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/longdouble.d)   | 80-bit floating point number implementation in case they are not natively supported        |
 | [man.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d)                 | Opens an online manual page                                                                |
-| [outbuffer.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.d)     | An expandable buffer in which you can write text or binary data.                           |
 | [port.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d)               | Portable routines for functions that have different implementations on different platforms |
 | [region.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d)           | A region allocator                                                                         |
 | [response.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/response.d)       | Parse command line arguments from response files                                           |
diff --git a/gcc/d/dmd/root/aav.h b/gcc/d/dmd/root/aav.h
deleted file mode 100644 (file)
index c65b674..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/aav.h
- */
-
-#pragma once
-
-#include "dsystem.h"
-
-typedef void* Value;
-typedef void* Key;
-
-struct AA;
-
-size_t dmd_aaLen(AA* aa);
-Value* dmd_aaGet(AA** aa, Key key);
-Value dmd_aaGetRvalue(AA* aa, Key key);
-void dmd_aaRehash(AA** paa);
-
diff --git a/gcc/d/dmd/root/checkedint.h b/gcc/d/dmd/root/checkedint.h
deleted file mode 100644 (file)
index 8a7d9c9..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/checkedint.h
- */
-
-#include "dsystem.h"
-
-
-int adds(int x, int y, bool& overflow);
-int64_t adds(int64_t x, int64_t y, bool& overflow);
-unsigned addu(unsigned x, unsigned y, bool& overflow);
-uint64_t addu(uint64_t x, uint64_t y, bool& overflow);
-
-int subs(int x, int y, bool& overflow);
-int64_t subs(int64_t x, int64_t y, bool& overflow);
-unsigned subu(unsigned x, unsigned y, bool& overflow);
-uint64_t subu(uint64_t x, uint64_t y, bool& overflow);
-
-int negs(int x, bool& overflow);
-int64_t negs(int64_t x, bool& overflow);
-
-int muls(int x, int y, bool& overflow);
-int64_t muls(int64_t x, int64_t y, bool& overflow);
-unsigned mulu(unsigned x, unsigned y, bool& overflow);
-uint64_t mulu(uint64_t x, uint64_t y, bool& overflow);
index ef6056cfed039ac5eadd8b8b214172ec09fa4ed3..64e9571632282a4d502d9d261598960aee251214 100644 (file)
@@ -23,410 +23,8 @@ import dmd.root.filename;
 import dmd.root.rmem;
 import dmd.root.string;
 
-/**
-Encapsulated management of a memory-mapped file.
-
-Params:
-Datum = the mapped data type: Use a POD of size 1 for read/write mapping
-and a `const` version thereof for read-only mapping. Other primitive types
-should work, but have not been yet tested.
-*/
-struct FileMapping(Datum)
-{
-    static assert(__traits(isPOD, Datum) && Datum.sizeof == 1,
-        "Not tested with other data types yet. Add new types with care.");
-
-    version(Posix) enum invalidHandle = -1;
-    else version(Windows) enum invalidHandle = INVALID_HANDLE_VALUE;
-
-    // state {
-    /// Handle of underlying file
-    private auto handle = invalidHandle;
-    /// File mapping object needed on Windows
-    version(Windows) private HANDLE fileMappingObject = invalidHandle;
-    /// Memory-mapped array
-    private Datum[] data;
-    /// Name of underlying file, zero-terminated
-    private const(char)* name;
-    // state }
-
-    /**
-    Open `filename` and map it in memory. If `Datum` is `const`, opens for
-    read-only and maps the content in memory; no error is issued if the file
-    does not exist. This makes it easy to treat a non-existing file as empty.
-
-    If `Datum` is mutable, opens for read/write (creates file if it does not
-    exist) and fails fatally on any error.
-
-    Due to quirks in `mmap`, if the file is empty, `handle` is valid but `data`
-    is `null`. This state is valid and accounted for.
-
-    Params:
-    filename = the name of the file to be mapped in memory
-    */
-    this(const char* filename)
-    {
-        version (Posix)
-        {
-            import core.sys.posix.sys.mman;
-            import core.sys.posix.fcntl;
-
-            handle = .open(filename, is(Datum == const) ? O_RDONLY : (O_CREAT | O_RDWR),
-                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
-            if (handle == invalidHandle)
-            {
-                static if (is(Datum == const))
-                {
-                    // No error, nonexisting file in read mode behaves like an empty file.
-                    return;
-                }
-                else
-                {
-                    fprintf(stderr, "open(\"%s\") failed: %s\n", filename, strerror(errno));
-                    exit(1);
-                }
-            }
-
-            const size = File.size(handle);
-
-            if (size > 0 && size != ulong.max && size <= size_t.max)
-            {
-                auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : PROT_WRITE, MAP_SHARED, handle, 0);
-                if (p == MAP_FAILED)
-                {
-                    fprintf(stderr, "mmap(null, %zu) for \"%s\" failed: %s\n", cast(size_t) size, filename, strerror(errno));
-                    exit(1);
-                }
-                // The cast below will always work because it's gated by the `size <= size_t.max` condition.
-                data = cast(Datum[]) p[0 .. cast(size_t) size];
-            }
-        }
-        else version(Windows)
-        {
-            static if (is(Datum == const))
-            {
-                enum createFileMode = GENERIC_READ;
-                enum openFlags = OPEN_EXISTING;
-            }
-            else
-            {
-                enum createFileMode = GENERIC_READ | GENERIC_WRITE;
-                enum openFlags = CREATE_ALWAYS;
-            }
-
-            handle = CreateFileA(filename, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null);
-            if (handle == invalidHandle)
-            {
-                static if (is(Datum == const))
-                {
-                    return;
-                }
-                else
-                {
-                    fprintf(stderr, "CreateFileA() failed for \"%s\": %d\n", filename, GetLastError());
-                    exit(1);
-                }
-            }
-            createMapping(filename, File.size(handle));
-        }
-        else static assert(0);
-
-        // Save the name for later. Technically there's no need: on Linux one can use readlink on /proc/self/fd/NNN.
-        // On BSD and OSX one can use fcntl with F_GETPATH. On Windows one can use GetFileInformationByHandleEx.
-        // But just saving the name is simplest, fastest, and most portable...
-        import core.stdc.string : strlen;
-        name = filename[0 .. filename.strlen() + 1].idup.ptr;
-    }
-
-    /**
-    Common code factored opportunistically. Windows only. Assumes `handle` is
-    already pointing to an opened file. Initializes the `fileMappingObject`
-    and `data` members.
-
-    Params:
-    filename = the file to be mapped
-    size = the size of the file in bytes
-    */
-    version(Windows) private void createMapping(const char* filename, ulong size)
-    {
-        assert(size <= size_t.max || size == ulong.max);
-        assert(handle != invalidHandle);
-        assert(data is null);
-        assert(fileMappingObject == invalidHandle);
-
-        if (size == 0 || size == ulong.max)
-            return;
-
-        static if (is(Datum == const))
-        {
-            enum fileMappingFlags = PAGE_READONLY;
-            enum mapViewFlags = FILE_MAP_READ;
-        }
-        else
-        {
-            enum fileMappingFlags = PAGE_READWRITE;
-            enum mapViewFlags = FILE_MAP_WRITE;
-        }
-
-        fileMappingObject = CreateFileMappingA(handle, null, fileMappingFlags, 0, 0, null);
-        if (!fileMappingObject)
-        {
-            fprintf(stderr, "CreateFileMappingA(%p) failed for %llu bytes of \"%s\": %d\n",
-                handle, size, filename, GetLastError());
-            fileMappingObject = invalidHandle;  // by convention always use invalidHandle, not null
-            exit(1);
-        }
-        auto p = MapViewOfFile(fileMappingObject, mapViewFlags, 0, 0, 0);
-        if (!p)
-        {
-            fprintf(stderr, "MapViewOfFile() failed for \"%s\": %d\n", filename, GetLastError());
-            exit(1);
-        }
-        data = cast(Datum[]) p[0 .. cast(size_t) size];
-    }
-
-    // Not copyable or assignable (for now).
-    @disable this(const FileMapping!Datum rhs);
-    @disable void opAssign(const ref FileMapping!Datum rhs);
-
-    /**
-    Frees resources associated with this mapping. However, it does not deallocate the name.
-    */
-    ~this() pure nothrow
-    {
-        if (!active)
-            return;
-        fakePure({
-            version (Posix)
-            {
-                import core.sys.posix.sys.mman : munmap;
-
-                // Cannot call fprintf from inside a destructor, so exiting silently.
-
-                if (data.ptr && munmap(cast(void*) data.ptr, data.length) != 0)
-                {
-                    exit(1);
-                }
-                data = null;
-                if (handle != invalidHandle && .close(handle) != 0)
-                {
-                    exit(1);
-                }
-                handle = invalidHandle;
-            }
-            else version(Windows)
-            {
-                if (data.ptr !is null && UnmapViewOfFile(cast(void*) data.ptr) == 0)
-                {
-                    exit(1);
-                }
-                data = null;
-                if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
-                {
-                    exit(1);
-                }
-                fileMappingObject = invalidHandle;
-                if (handle != invalidHandle && CloseHandle(handle) == 0)
-                {
-                    exit(1);
-                }
-                handle = invalidHandle;
-            }
-            else static assert(0);
-        });
-    }
-
-    /**
-    Returns the zero-terminated file name associated with the mapping. Can
-    be saved beyond the lifetime of `this`.
-    */
-    const(char)* filename() const pure @nogc @safe nothrow { return name; }
-
-    /**
-    Frees resources associated with this mapping. However, it does not deallocate the name.
-    Reinitializes `this` as a fresh object that can be reused.
-    */
-    void close()
-    {
-        __dtor();
-        handle = invalidHandle;
-        version(Windows) fileMappingObject = invalidHandle;
-        data = null;
-        name = null;
-    }
-
-    /**
-    Deletes the underlying file and frees all resources associated.
-    Reinitializes `this` as a fresh object that can be reused.
-
-    This function does not abort if the file cannot be deleted, but does print
-    a message on `stderr` and returns `false` to the caller. The underlying
-    rationale is to give the caller the option to continue execution if
-    deleting the file is not important.
-
-    Returns: `true` iff the file was successfully deleted. If the file was not
-    deleted, prints a message to `stderr` and returns `false`.
-    */
-    static if (!is(Datum == const))
-    bool discard()
-    {
-        // Truncate file to zero so unflushed buffers are not flushed unnecessarily.
-        resize(0);
-        auto deleteme = name;
-        close();
-        // In-memory resource freed, now get rid of the underlying temp file.
-        version(Posix)
-        {
-            import core.sys.posix.unistd;
-            if (unlink(deleteme) != 0)
-            {
-                fprintf(stderr, "unlink(\"%s\") failed: %s\n", filename, strerror(errno));
-                return false;
-            }
-        }
-        else version(Windows)
-        {
-            import core.sys.windows.winbase;
-            if (DeleteFileA(deleteme) == 0)
-            {
-                fprintf(stderr, "DeleteFileA error %d\n", GetLastError());
-                return false;
-            }
-        }
-        else static assert(0);
-        return true;
-    }
-
-    /**
-    Queries whether `this` is currently associated with a file.
-
-    Returns: `true` iff there is an active mapping.
-    */
-    bool active() const pure @nogc nothrow
-    {
-        return handle !is invalidHandle;
-    }
-
-    /**
-    Queries the length of the file associated with this mapping.  If not
-    active, returns 0.
-
-    Returns: the length of the file, or 0 if no file associated.
-    */
-    size_t length() const pure @nogc @safe nothrow { return data.length; }
-
-    /**
-    Get a slice to the contents of the entire file.
-
-    Returns: the contents of the file. If not active, returns the `null` slice.
-    */
-    auto opSlice() pure @nogc @safe nothrow { return data; }
-
-    /**
-    Resizes the file and mapping to the specified `size`.
-
-    Params:
-    size = new length requested
-    */
-    static if (!is(Datum == const))
-    void resize(size_t size) pure
-    {
-        assert(handle != invalidHandle);
-        fakePure({
-            version(Posix)
-            {
-                import core.sys.posix.unistd : ftruncate;
-                import core.sys.posix.sys.mman;
-
-                if (data.length)
-                {
-                    assert(data.ptr, "Corrupt memory mapping");
-                    // assert(0) here because it would indicate an internal error
-                    munmap(cast(void*) data.ptr, data.length) == 0 || assert(0);
-                    data = null;
-                }
-                if (ftruncate(handle, size) != 0)
-                {
-                    fprintf(stderr, "ftruncate() failed for \"%s\": %s\n", filename, strerror(errno));
-                    exit(1);
-                }
-                if (size > 0)
-                {
-                    auto p = mmap(null, size, PROT_WRITE, MAP_SHARED, handle, 0);
-                    if (cast(ssize_t) p == -1)
-                    {
-                        fprintf(stderr, "mmap() failed for \"%s\": %s\n", filename, strerror(errno));
-                        exit(1);
-                    }
-                    data = cast(Datum[]) p[0 .. size];
-                }
-            }
-            else version(Windows)
-            {
-                // Per documentation, must unmap first.
-                if (data.length > 0 && UnmapViewOfFile(cast(void*) data.ptr) == 0)
-                {
-                    fprintf(stderr, "UnmapViewOfFile(%p) failed for memory mapping of \"%s\": %d\n",
-                        data.ptr, filename, GetLastError());
-                    exit(1);
-                }
-                data = null;
-                if (fileMappingObject != invalidHandle && CloseHandle(fileMappingObject) == 0)
-                {
-                    fprintf(stderr, "CloseHandle() failed for memory mapping of \"%s\": %d\n", filename, GetLastError());
-                    exit(1);
-                }
-                fileMappingObject = invalidHandle;
-                LARGE_INTEGER biggie;
-                biggie.QuadPart = size;
-                if (SetFilePointerEx(handle, biggie, null, FILE_BEGIN) == 0 || SetEndOfFile(handle) == 0)
-                {
-                    fprintf(stderr, "SetFilePointer() failed for \"%s\": %d\n", filename, GetLastError());
-                    exit(1);
-                }
-                createMapping(name, size);
-            }
-            else static assert(0);
-        });
-    }
-
-    /**
-    Unconditionally and destructively moves the underlying file to `filename`.
-    If the operation succeds, returns true. Upon failure, prints a message to
-    `stderr` and returns `false`.
-
-    Params: filename = zero-terminated name of the file to move to.
-
-    Returns: `true` iff the operation was successful.
-    */
-    bool moveToFile(const char* filename)
-    {
-        auto oldname = name;
-
-        close();
-        // Rename the underlying file to the target, no copy necessary.
-        version(Posix)
-        {
-            if (.rename(oldname, filename) != 0)
-            {
-                fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", oldname, filename, strerror(errno));
-                return false;
-            }
-        }
-        else version(Windows)
-        {
-            import core.sys.windows.winbase;
-            if (MoveFileExA(oldname, filename, MOVEFILE_REPLACE_EXISTING) == 0)
-            {
-                fprintf(stderr, "MoveFileExA(\"%s\", \"%s\") failed: %d\n", oldname, filename, GetLastError());
-                return false;
-            }
-        }
-        else static assert(0);
-        return true;
-    }
-}
+import dmd.common.file;
+import dmd.common.string;
 
 /// Owns a (rmem-managed) file buffer.
 struct FileBuffer
@@ -585,58 +183,8 @@ nothrow:
     /// Write a file, returning `true` on success.
     extern (D) static bool write(const(char)* name, const void[] data)
     {
-        version (Posix)
-        {
-            ssize_t numwritten;
-            int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
-            if (fd == -1)
-                goto err;
-            numwritten = .write(fd, data.ptr, data.length);
-            if (numwritten != data.length)
-                goto err2;
-            if (close(fd) == -1)
-                goto err;
-            return true;
-        err2:
-            close(fd);
-            .remove(name);
-        err:
-            return false;
-        }
-        else version (Windows)
-        {
-            DWORD numwritten; // here because of the gotos
-            const nameStr = name.toDString;
-            // work around Windows file path length limitation
-            // (see documentation for extendedPathThen).
-            HANDLE h = nameStr.extendedPathThen!
-                (p => CreateFileW(p.ptr,
-                                  GENERIC_WRITE,
-                                  0,
-                                  null,
-                                  CREATE_ALWAYS,
-                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
-                                  null));
-            if (h == INVALID_HANDLE_VALUE)
-                goto err;
-
-            if (WriteFile(h, data.ptr, cast(DWORD)data.length, &numwritten, null) != TRUE)
-                goto err2;
-            if (numwritten != data.length)
-                goto err2;
-            if (!CloseHandle(h))
-                goto err;
-            return true;
-        err2:
-            CloseHandle(h);
-            nameStr.extendedPathThen!(p => DeleteFileW(p.ptr));
-        err:
-            return false;
-        }
-        else
-        {
-            static assert(0);
-        }
+        import dmd.common.file : writeFile;
+        return writeFile(name, data);
     }
 
     ///ditto
@@ -717,42 +265,6 @@ nothrow:
         return update(name, data[0 .. size]);
     }
 
-    /// Touch a file to current date
-    static bool touch(const char* namez)
-    {
-        version (Windows)
-        {
-            FILETIME ft = void;
-            SYSTEMTIME st = void;
-            GetSystemTime(&st);
-            SystemTimeToFileTime(&st, &ft);
-
-            import core.stdc.string : strlen;
-
-            // get handle to file
-            HANDLE h = namez[0 .. namez.strlen()].extendedPathThen!(p => CreateFile(p.ptr,
-                FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
-                null, OPEN_EXISTING,
-                FILE_ATTRIBUTE_NORMAL, null));
-            if (h == INVALID_HANDLE_VALUE)
-                return false;
-
-            const f = SetFileTime(h, null, null, &ft); // set last write time
-
-            if (!CloseHandle(h))
-                return false;
-
-            return f != 0;
-        }
-        else version (Posix)
-        {
-            import core.sys.posix.utime;
-            return utime(namez, null) == 0;
-        }
-        else
-            static assert(0);
-    }
-
     /// Size of a file in bytes.
     /// Params: namez = null-terminated filename
     /// Returns: `ulong.max` on any error, the length otherwise.
@@ -777,38 +289,5 @@ nothrow:
         // Error cases go here.
         return ulong.max;
     }
-
-    /// Ditto
-    version (Posix)
-    static ulong size(int fd)
-    {
-        stat_t buf;
-        if (fstat(fd, &buf) == 0)
-            return buf.st_size;
-        return ulong.max;
-    }
-
-    /// Ditto
-    version (Windows)
-    static ulong size(HANDLE fd)
-    {
-        ulong result;
-        if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
-            return result;
-        return ulong.max;
-    }
 }
 
-/**
-Runs a non-pure function or delegate as pure code. Use with caution.
-
-Params:
-fun = the delegate to run, usually inlined: `fakePure({ ... });`
-
-Returns: whatever `fun` returns.
-*/
-private auto ref fakePure(F)(scope F fun) pure
-{
-    mixin("alias PureFun = " ~ F.stringof ~ " pure;");
-    return (cast(PureFun) fun)();
-}
index 1e4ccb5d344f88de0283a7ca3c391799d81539d7..d1500c8953b38f2673ac5f68642c5e410a9fd0d5 100644 (file)
@@ -16,7 +16,8 @@ import core.stdc.errno;
 import core.stdc.string;
 import dmd.root.array;
 import dmd.root.file;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
+import dmd.common.file;
 import dmd.root.port;
 import dmd.root.rmem;
 import dmd.root.rootobject;
@@ -1123,78 +1124,13 @@ version(Windows)
      */
     private int _mkdir(const(char)[] path) nothrow
     {
+        import dmd.common.string : extendedPathThen;
         const createRet = path.extendedPathThen!(
             p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
         // different conventions for CreateDirectory and mkdir
         return createRet == 0 ? 1 : 0;
     }
 
-    /**************************************
-     * Converts a path to one suitable to be passed to Win32 API
-     * functions that can deal with paths longer than 248
-     * characters then calls the supplied function on it.
-     *
-     * Params:
-     *  path = The Path to call F on.
-     *
-     * Returns:
-     *  The result of calling F on path.
-     *
-     * References:
-     *  https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
-     */
-    package auto extendedPathThen(alias F)(const(char)[] path)
-    {
-        if (!path.length)
-            return F((wchar[]).init);
-        return path.toWStringzThen!((wpath)
-        {
-            // GetFullPathNameW expects a sized buffer to store the result in. Since we don't
-            // know how large it has to be, we pass in null and get the needed buffer length
-            // as the return code.
-            const pathLength = GetFullPathNameW(&wpath[0],
-                                                0 /*length8*/,
-                                                null /*output buffer*/,
-                                                null /*filePartBuffer*/);
-            if (pathLength == 0)
-            {
-                return F((wchar[]).init);
-            }
-
-            // wpath is the UTF16 version of path, but to be able to use
-            // extended paths, we need to prefix with `\\?\` and the absolute
-            // path.
-            static immutable prefix = `\\?\`w;
-
-            // prefix only needed for long names and non-UNC names
-            const needsPrefix = pathLength >= MAX_PATH && (wpath[0] != '\\' || wpath[1] != '\\');
-            const prefixLength = needsPrefix ? prefix.length : 0;
-
-            // +1 for the null terminator
-            const bufferLength = pathLength + prefixLength + 1;
-
-            wchar[1024] absBuf = void;
-            wchar[] absPath = bufferLength > absBuf.length
-                ? new wchar[bufferLength] : absBuf[0 .. bufferLength];
-
-            absPath[0 .. prefixLength] = prefix[0 .. prefixLength];
-
-            const absPathRet = GetFullPathNameW(&wpath[0],
-                cast(uint)(absPath.length - prefixLength - 1),
-                &absPath[prefixLength],
-                null /*filePartBuffer*/);
-
-            if (absPathRet == 0 || absPathRet > absPath.length - prefixLength)
-            {
-                return F((wchar[]).init);
-            }
-
-            absPath[$ - 1] = '\0';
-            // Strip null terminator from the slice
-            return F(absPath[0 .. $ - 1]);
-        });
-    }
-
     /**********************************
      * Converts a UTF-16 string to a (null-terminated) narrow string.
      * Returns:
@@ -1222,33 +1158,6 @@ version(Windows)
         return newBuffer[0 .. length];
     }
 
-    /**********************************
-     * Converts a narrow string to a (null-terminated) UTF-16 string.
-     * Returns:
-     *  If `buffer` is specified and the result fits, a slice of that buffer,
-     *  otherwise a new buffer which can be released via `mem.xfree()`.
-     *  Nulls are propagated, i.e., if `narrow` is null, the returned slice is
-     *  null too.
-     */
-    wchar[] toWStringz(const(char)[] narrow, wchar[] buffer = null) nothrow
-    {
-        if (narrow is null)
-            return null;
-
-        const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
-        if (requiredLength < buffer.length)
-        {
-            buffer[requiredLength] = 0;
-            return buffer[0 .. requiredLength];
-        }
-
-        wchar* newBuffer = cast(wchar*) mem.xmalloc_noscan((requiredLength + 1) * wchar.sizeof);
-        const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, newBuffer, requiredLength);
-        assert(length == requiredLength);
-        newBuffer[length] = 0;
-        return newBuffer[0 .. length];
-    }
-
     /**********************************
      * Converts a slice of UTF-8 characters to an array of wchar that's null
      * terminated so it can be passed to Win32 APIs then calls the supplied
@@ -1262,9 +1171,12 @@ version(Windows)
      */
     private auto toWStringzThen(alias F)(const(char)[] str) nothrow
     {
+        import dmd.common.string : SmallBuffer, toWStringz;
+
         if (!str.length) return F(""w.ptr);
 
-        wchar[1024] buf = void;
+        wchar[1024] support = void;
+        auto buf = SmallBuffer!wchar(support.length, support);
         wchar[] wide = toWStringz(str, buf);
         scope(exit) wide.ptr != buf.ptr && mem.xfree(wide.ptr);
 
diff --git a/gcc/d/dmd/root/hash.h b/gcc/d/dmd/root/hash.h
deleted file mode 100644 (file)
index 6a32200..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Compiler implementation of the D programming language
- * http://dlang.org
- *
- * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * Authors:   Martin Nowak, Walter Bright, http://www.digitalmars.com
- * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source:    $(DMDSRC root/_hash.h)
- */
-
-#pragma once
-
-#include "dsystem.h"                    // uint{8|16|32}_t
-
-// MurmurHash2 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-// https://sites.google.com/site/murmurhash/
-static inline uint32_t calcHash(const uint8_t *data, size_t len)
-{
-    // 'm' and 'r' are mixing constants generated offline.
-    // They're not really 'magic', they just happen to work well.
-
-    const uint32_t m = 0x5bd1e995;
-    const int r = 24;
-
-    // Initialize the hash to a 'random' value
-
-    uint32_t h = (uint32_t)len;
-
-    // Mix 4 bytes at a time into the hash
-
-    while(len >= 4)
-    {
-        uint32_t k = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
-
-        k *= m;
-        k ^= k >> r;
-        k *= m;
-
-        h *= m;
-        h ^= k;
-
-        data += 4;
-        len -= 4;
-    }
-
-    // Handle the last few bytes of the input array
-
-    switch(len & 3)
-    {
-    case 3: h ^= data[2] << 16; /* fall through */
-    case 2: h ^= data[1] << 8;  /* fall through */
-    case 1: h ^= data[0];
-        h *= m;
-    }
-
-    // Do a few final mixes of the hash to ensure the last few
-    // bytes are well-incorporated.
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-}
-
-static inline uint32_t calcHash(const char *data, size_t len)
-{
-    return calcHash((const uint8_t *)data, len);
-}
-
-// combine and mix two words (boost::hash_combine)
-static inline size_t mixHash(size_t h, size_t k)
-{
-    return h ^ (k + 0x9e3779b9 + (h << 6) + (h >> 2));
-}
index 854ec1a65bc275d999c22fa457bdc749111c2da6..64104b823d1f0c36a3449c7837304e3f0583c8ec 100644 (file)
@@ -13,7 +13,7 @@ module dmd.root.rootobject;
 
 import core.stdc.stdio;
 
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 
 /***********************************************************
  */
diff --git a/gcc/d/dmd/root/speller.h b/gcc/d/dmd/root/speller.h
deleted file mode 100644 (file)
index bd53fc4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-
-/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- * https://github.com/D-Programming-Language/dmd/blob/master/src/root/speller.h
- */
-
-#pragma once
-
-typedef void *(fp_speller_t)(void *, const char *, int*);
-
-extern const char idchars[];
-
-void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset);
-
diff --git a/gcc/d/dmd/root/stringtable.h b/gcc/d/dmd/root/stringtable.h
deleted file mode 100644 (file)
index 51304d3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.h
- */
-
-#pragma once
-
-#include "root.h"
-
-struct StringEntry;
-
-// StringValue is a variable-length structure. It has neither proper c'tors nor a
-// factory method because the only thing which should be creating these is StringTable.
-struct StringValue
-{
-    void *ptrvalue;
-    size_t length;
-    char *lstring() { return (char *)(this + 1); }
-
-    size_t len() const { return length; }
-    const char *toDchars() const { return (const char *)(this + 1); }
-
-    StringValue();  // not constructible
-};
-
-struct StringTable
-{
-private:
-    StringEntry *table;
-    size_t tabledim;
-
-    uint8_t **pools;
-    size_t npools;
-    size_t nfill;
-
-    size_t count;
-
-public:
-    void _init(size_t size = 0);
-    void reset(size_t size = 0);
-    ~StringTable();
-
-    StringValue *lookup(const char *s, size_t len);
-    StringValue *insert(const char *s, size_t len, void *ptrvalue);
-    StringValue *update(const char *s, size_t len);
-    int apply(int (*fp)(StringValue *));
-
-private:
-    uint32_t allocValue(const char *p, size_t length, void *ptrvalue);
-    StringValue *getValue(uint32_t validx);
-    size_t findSlot(hash_t hash, const char *s, size_t len);
-    void grow();
-};
index 35734b2caa585510a47dcb9de09af1fc7c2545cb..89049599dacdfd1988372c202af2016948c2f639 100644 (file)
@@ -89,7 +89,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
 
         if (hasPointers && v.type.toBasetype().ty != Tstruct)
         {
-            if ((ad.type.alignment() < target.ptrsize ||
+            if ((!ad.type.alignment.isDefault() && ad.type.alignment.get() < target.ptrsize ||
                  (v.offset & (target.ptrsize - 1))) &&
                 sc.func.setUnsafe())
             {
index 7b2fa5e93cdd0db0a529ba1b4009857e6587e493..993db90552343247efb504908ae2e3cbe06fb629 100644 (file)
@@ -53,7 +53,7 @@ import dmd.objc;
 import dmd.opover;
 import dmd.parse;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.sideeffect;
@@ -363,7 +363,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
         assert(fd.semanticRun <= PASS.semantic2);
         fd.semanticRun = PASS.semantic2;
 
-        //printf("FuncDeclaration::semantic2 [%s] fd0 = %s %s\n", loc.toChars(), toChars(), type.toChars());
+        //printf("FuncDeclaration::semantic2 [%s] fd: %s type: %s\n", fd.loc.toChars(), fd.toChars(), fd.type ? fd.type.toChars() : "".ptr);
 
         // Only check valid functions which have a body to avoid errors
         // for multiple declarations, e.g.
index ac2b239efafd1ea75829ecd2e4bdd1356f2d39e2..3852d0b26934e90584475ef6b1b35e011bc9df52 100644 (file)
@@ -55,7 +55,7 @@ import dmd.objc;
 import dmd.opover;
 import dmd.parse;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.sideeffect;
@@ -407,7 +407,8 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     sc2.insert(_arguments);
                     _arguments.parent = funcdecl;
                 }
-                if (f.linkage == LINK.d || f.parameterList.length)
+                if ((f.linkage == LINK.d || f.parameterList.length) &&
+                    !(sc.flags & SCOPE.Cfile))  // don't want to require importing stdarg for C files
                 {
                     // Declare _argptr
                     Type t = target.va_listType(funcdecl.loc, sc);
@@ -598,7 +599,10 @@ private extern(C++) final class Semantic3Visitor : Visitor
                         f.next = Type.tvoid;
                     if (f.checkRetType(funcdecl.loc))
                         funcdecl.fbody = new ErrorStatement();
+                    else if (funcdecl.isMain())
+                        funcdecl.checkDmain();       // Check main() parameters and return type
                 }
+
                 if (global.params.vcomplex && f.next !is null)
                     f.next.checkComplexTransition(funcdecl.loc, sc);
 
@@ -777,8 +781,14 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     }
                     assert(!funcdecl.returnLabel);
                 }
-                else if (f.next.ty == Tnoreturn)
+                else if (f.next.toBasetype().ty == Tnoreturn)
                 {
+                    // Fallthrough despite being declared as noreturn? return is already rejected when evaluating the ReturnStatement
+                    if (blockexit & BE.fallthru)
+                    {
+                        funcdecl.error("is typed as `%s` but does return", f.next.toChars());
+                        funcdecl.loc.errorSupplemental("`noreturn` functions must either throw, abort or loop indefinitely");
+                    }
                 }
                 else
                 {
@@ -1571,7 +1581,7 @@ private struct FuncDeclSem3
     }
 }
 
-private void semanticTypeInfoMembers(StructDeclaration sd)
+extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
 {
     if (sd.xeq &&
         sd.xeq._scope &&
index b49c9035d3f38f8c3344c63d7475570e6df2a726..91e3fe7bfebc8c4b780a0981fb12bf01668aa842 100644 (file)
@@ -39,7 +39,7 @@ import dmd.id;
 import dmd.identifier;
 import dmd.dinterpret;
 import dmd.mtype;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.sapply;
 import dmd.sideeffect;
@@ -463,7 +463,7 @@ extern (C++) class ExpStatement : Statement
         this.exp = new DeclarationExp(loc, declaration);
     }
 
-    static ExpStatement create(Loc loc, Expression exp)
+    static ExpStatement create(const ref Loc loc, Expression exp)
     {
         return new ExpStatement(loc, exp);
     }
@@ -577,7 +577,7 @@ extern (C++) class CompoundStatement : Statement
             statements.push(s);
     }
 
-    static CompoundStatement create(Loc loc, Statement s1, Statement s2)
+    static CompoundStatement create(const ref Loc loc, Statement s1, Statement s2)
     {
         return new CompoundStatement(loc, s1, s2);
     }
@@ -1635,7 +1635,7 @@ extern (C++) final class TryFinallyStatement : Statement
         this.bodyFallsThru = true;      // assume true until statementSemantic()
     }
 
-    static TryFinallyStatement create(Loc loc, Statement _body, Statement finalbody)
+    static TryFinallyStatement create(const ref Loc loc, Statement _body, Statement finalbody)
     {
         return new TryFinallyStatement(loc, _body, finalbody);
     }
index 7825762db9e09e729a0bc76924e3bf70dac40a6a..98b7bd318eb478e4cc19f87da2ffc046b2dab900 100644 (file)
@@ -186,7 +186,7 @@ class ExpStatement : public Statement
 public:
     Expression *exp;
 
-    static ExpStatement *create(Loc loc, Expression *exp);
+    static ExpStatement *create(const Loc &loc, Expression *exp);
     ExpStatement *syntaxCopy();
 
     void accept(Visitor *v) { v->visit(this); }
@@ -218,7 +218,7 @@ class CompoundStatement : public Statement
 public:
     Statements *statements;
 
-    static CompoundStatement *create(Loc loc, Statement *s1, Statement *s2);
+    static CompoundStatement *create(const Loc &loc, Statement *s1, Statement *s2);
     CompoundStatement *syntaxCopy();
     ReturnStatement *endsWithReturnStatement();
     Statement *last();
@@ -615,7 +615,7 @@ public:
     Statement *tryBody;   // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
     bool bodyFallsThru;   // true if _body falls through to finally
 
-    static TryFinallyStatement *create(Loc loc, Statement *body, Statement *finalbody);
+    static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody);
     TryFinallyStatement *syntaxCopy();
     bool hasBreak() const;
     bool hasContinue() const;
diff --git a/gcc/d/dmd/statement_rewrite_walker.h b/gcc/d/dmd/statement_rewrite_walker.h
deleted file mode 100644 (file)
index 28a930a..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- */
-
-#include "statement.h"
-#include "visitor.h"
-
-/* A visitor to walk entire statements and provides ability to replace any sub-statements.
- */
-class StatementRewriteWalker : public Visitor
-{
-    /* Point the currently visited statement.
-     * By using replaceCurrent() method, you can replace AST during walking.
-     */
-    Statement **ps;
-public:
-    void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
-    void replaceCurrent(Statement *s) { *ps = s; }
-
-    void visit(ErrorStatement *) {  }
-    void visit(PeelStatement *s)
-    {
-        if (s->s)
-            visitStmt(s->s);
-    }
-    void visit(ExpStatement *) {  }
-    void visit(DtorExpStatement *) {  }
-    void visit(CompileStatement *) {  }
-    void visit(CompoundStatement *s)
-    {
-        if (s->statements && s->statements->length)
-        {
-            for (size_t i = 0; i < s->statements->length; i++)
-            {
-                if ((*s->statements)[i])
-                    visitStmt((*s->statements)[i]);
-            }
-        }
-    }
-    void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
-    void visit(UnrolledLoopStatement *s)
-    {
-        if (s->statements && s->statements->length)
-        {
-            for (size_t i = 0; i < s->statements->length; i++)
-            {
-                if ((*s->statements)[i])
-                    visitStmt((*s->statements)[i]);
-            }
-        }
-    }
-    void visit(ScopeStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(WhileStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(DoStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForStatement *s)
-    {
-        if (s->_init)
-            visitStmt(s->_init);
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForeachStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForeachRangeStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(IfStatement *s)
-    {
-        if (s->ifbody)
-            visitStmt(s->ifbody);
-        if (s->elsebody)
-            visitStmt(s->elsebody);
-    }
-    void visit(ConditionalStatement *) {  }
-    void visit(PragmaStatement *) {  }
-    void visit(StaticAssertStatement *) {  }
-    void visit(SwitchStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(CaseStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(CaseRangeStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(DefaultStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(GotoDefaultStatement *) {  }
-    void visit(GotoCaseStatement *) {  }
-    void visit(SwitchErrorStatement *) {  }
-    void visit(ReturnStatement *) {  }
-    void visit(BreakStatement *) {  }
-    void visit(ContinueStatement *) {  }
-    void visit(SynchronizedStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(WithStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(TryCatchStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-        if (s->catches && s->catches->length)
-        {
-            for (size_t i = 0; i < s->catches->length; i++)
-            {
-                Catch *c = (*s->catches)[i];
-                if (c && c->handler)
-                    visitStmt(c->handler);
-            }
-        }
-    }
-    void visit(TryFinallyStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-        if (s->finalbody)
-            visitStmt(s->finalbody);
-    }
-    void visit(ScopeGuardStatement *) {  }
-    void visit(ThrowStatement *) {  }
-    void visit(DebugStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(GotoStatement *) {  }
-    void visit(LabelStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(AsmStatement *) {  }
-    void visit(ImportStatement *) {  }
-};
-
index f067c91b3163d6ab4ae15b5efaffe23607f11a69..9eba2ffaed206a32151e90a122440af9303d8f20 100644 (file)
@@ -54,7 +54,7 @@ import dmd.nogc;
 import dmd.opover;
 import dmd.parse;
 import dmd.printast;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.string;
 import dmd.semantic2;
 import dmd.sideeffect;
@@ -659,20 +659,6 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
         result = fs;
     }
 
-    /*******************
-     * Determines the return type of makeTupleForeach.
-     */
-    private static template MakeTupleForeachRet(bool isDecl)
-    {
-        static if(isDecl)
-        {
-            alias MakeTupleForeachRet = Dsymbols*;
-        }
-        else
-        {
-            alias MakeTupleForeachRet = void;
-        }
-    }
 
     /*******************
      * Type check and unroll `foreach` over an expression tuple as well
@@ -696,29 +682,24 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
      * expands the tuples into multiple `STC.local` `static foreach`
      * variables.
      */
-    MakeTupleForeachRet!isDecl makeTupleForeach(bool isStatic, bool isDecl)(ForeachStatement fs, TupleForeachArgs!(isStatic, isDecl) args)
+    auto makeTupleForeach(bool isStatic, bool isDecl)(ForeachStatement fs, Dsymbols* dbody, bool needExpansion)
     {
-        auto returnEarly()
-        {
-            static if (isDecl)
-            {
-                return null;
-            }
-            else
-            {
-                result = new ErrorStatement();
-                return;
-            }
-        }
-        static if(isDecl)
+        // Voldemort return type
+        union U
         {
-            static assert(isStatic);
-            auto dbody = args[0];
+            Statement statement;
+            Dsymbols* decl;
         }
-        static if(isStatic)
+
+        U result;
+
+        auto returnEarly()
         {
-            auto needExpansion = args[$-1];
-            assert(sc);
+            if (isDecl)
+                result.decl = null;
+            else
+                result.statement = new ErrorStatement();
+            return result;
         }
 
         auto loc = fs.loc;
@@ -827,7 +808,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                 }
                 Initializer ie = new ExpInitializer(Loc.initial, new IntegerExp(k));
                 auto var = new VarDeclaration(loc, p.type, p.ident, ie);
-                var.storage_class |= STC.manifest;
+                var.storage_class |= STC.foreach_ | STC.manifest;
                 static if(isStatic) var.storage_class |= STC.local;
                 static if(!isDecl)
                 {
@@ -919,8 +900,9 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                         e = resolveProperties(sc, e);
                         Initializer ie = new ExpInitializer(Loc.initial, e);
                         auto v = new VarDeclaration(loc, type, ident, ie, storageClass);
+                        v.storage_class |= STC.foreach_;
                         if (storageClass & STC.ref_)
-                            v.storage_class |= STC.ref_ | STC.foreach_;
+                            v.storage_class |= STC.ref_;
                         if (isStatic || storageClass&STC.manifest || e.isConst() ||
                             e.op == TOK.string_ ||
                             e.op == TOK.structLiteral ||
@@ -1057,23 +1039,17 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                 ls.gotoTarget = res;
             if (te && te.e0)
                 res = new CompoundStatement(loc, new ExpStatement(te.e0.loc, te.e0), res);
+            result.statement = res;
         }
         else static if (!isDecl)
         {
-            Statement res = new CompoundStatement(loc, statements);
-        }
-        else
-        {
-            auto res = declarations;
-        }
-        static if (!isDecl)
-        {
-            result = res;
+            result.statement = new CompoundStatement(loc, statements);
         }
         else
         {
-            return res;
+            result.decl = declarations;
         }
+        return result;
     }
 
     override void visit(ForeachStatement fs)
@@ -1202,10 +1178,10 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
 
         if (tab.ty == Ttuple) // don't generate new scope for tuple loops
         {
-            makeTupleForeach!(false,false)(fs);
+            Statement s = makeTupleForeach!(false,false)(fs, null, false).statement;
             if (vinit)
-                result = new CompoundStatement(loc, new ExpStatement(loc, vinit), result);
-            result = result.statementSemantic(sc);
+                s = new CompoundStatement(loc, new ExpStatement(loc, vinit), s);
+            result = s.statementSemantic(sc);
             return;
         }
 
@@ -2727,7 +2703,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                 needswitcherror = true;
         }
 
-        if (!sc.sw.sdefault && (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on))
+        if (!sc.sw.sdefault && !(sc.flags & SCOPE.Cfile) &&
+            (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on))
         {
             ss.hasNoDefault = 1;
 
@@ -3061,7 +3038,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
 
         if (lval - fval > 256)
         {
-            crs.error("had %llu cases which is more than 256 cases in case range", lval - fval);
+            crs.error("had %llu cases which is more than 257 cases in case range", 1 + lval - fval);
             errors = true;
             lval = fval + 256;
         }
@@ -3295,12 +3272,14 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
             if (e0)
                 e0 = e0.optimize(WANTvalue);
 
-            /* Void-return function can have void typed expression
+            /* Void-return function can have void / noreturn typed expression
              * on return statement.
              */
-            if (tbret && tbret.ty == Tvoid || rs.exp.type.ty == Tvoid)
+            const convToVoid = rs.exp.type.ty == Tvoid || rs.exp.type.ty == Tnoreturn;
+
+            if (tbret && tbret.ty == Tvoid || convToVoid)
             {
-                if (rs.exp.type.ty != Tvoid)
+                if (!convToVoid)
                 {
                     rs.error("cannot return non-void from `void` function");
                     errors = true;
@@ -3345,7 +3324,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                     }
                     else if (rs.exp.op != TOK.error)
                     {
-                        rs.error("Expected return type of `%s`, not `%s`:",
+                        rs.error("expected return type of `%s`, not `%s`:",
                                  tret.toChars(),
                                  rs.exp.type.toChars());
                         errorSupplemental((fd.returns) ? (*fd.returns)[0].loc : fd.loc,
@@ -3409,10 +3388,20 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
         }
         else
         {
+            // Type of the returned expression (if any), might've been moved to e0
+            auto resType = e0 ? e0.type : Type.tvoid;
+
             // infer return type
             if (fd.inferRetType)
             {
-                if (tf.next && tf.next.ty != Tvoid)
+                // 1. First `return <noreturn exp>?`
+                // 2. Potentially found a returning branch, update accordingly
+                if (!tf.next || tf.next.toBasetype().isTypeNoreturn())
+                {
+                    tf.next = resType; // infer void or noreturn
+                }
+                // Found an actual return value before
+                else if (tf.next.ty != Tvoid && !resType.toBasetype().isTypeNoreturn())
                 {
                     if (tf.next.ty != Terror)
                     {
@@ -3421,20 +3410,23 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                     errors = true;
                     tf.next = Type.terror;
                 }
-                else
-                    tf.next = Type.tvoid;
 
-                    tret = tf.next;
+                tret = tf.next;
                 tbret = tret.toBasetype();
             }
 
             if (inferRef) // deduce 'auto ref'
                 tf.isref = false;
 
-            if (tbret.ty != Tvoid) // if non-void return
+            if (tbret.ty != Tvoid && !resType.isTypeNoreturn()) // if non-void return
             {
                 if (tbret.ty != Terror)
-                    rs.error("`return` expression expected");
+                {
+                    if (e0)
+                        rs.error("expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars());
+                    else
+                        rs.error("`return` expression expected");
+                }
                 errors = true;
             }
             else if (fd.isMain())
@@ -3522,7 +3514,12 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
             }
             else
             {
-                result = new CompoundStatement(rs.loc, new ExpStatement(rs.loc, e0), rs);
+                auto es = new ExpStatement(rs.loc, e0);
+                if (e0.type.isTypeNoreturn())
+                    result = es; // Omit unreachable return;
+                else
+                    result = new CompoundStatement(rs.loc, es, rs);
+
                 return;
             }
         }
@@ -4014,7 +4011,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
                 /* If catch exception type is derived from Exception
                  */
                 if (c.type.toBasetype().implicitConvTo(ClassDeclaration.exception.type) &&
-                    (!c.handler || !c.handler.comeFrom()))
+                    (!c.handler || !c.handler.comeFrom()) && !(sc.flags & SCOPE.debug_))
                 {
                     // Remove c from the array of catches
                     tcs.catches.remove(i);
@@ -4569,45 +4566,14 @@ Statement scopeCode(Statement statement, Scope* sc, out Statement sentry, out St
 }
 
 
-/*******************
- * Determines additional argument types for makeTupleForeach.
- */
-static template TupleForeachArgs(bool isStatic, bool isDecl)
-{
-    alias Seq(T...)=T;
-    static if(isStatic) alias T = Seq!(bool);
-    else alias T = Seq!();
-    static if(!isDecl) alias TupleForeachArgs = T;
-    else alias TupleForeachArgs = Seq!(Dsymbols*,T);
-}
-
-/*******************
- * Determines the return type of makeTupleForeach.
- */
-static template TupleForeachRet(bool isStatic, bool isDecl)
-{
-    alias Seq(T...)=T;
-    static if(!isDecl) alias TupleForeachRet = Statement;
-    else alias TupleForeachRet = Dsymbols*;
-}
-
-
 /*******************
  * See StatementSemanticVisitor.makeTupleForeach.  This is a simple
  * wrapper that returns the generated statements/declarations.
  */
-TupleForeachRet!(isStatic, isDecl) makeTupleForeach(bool isStatic, bool isDecl)(Scope* sc, ForeachStatement fs, TupleForeachArgs!(isStatic, isDecl) args)
+auto makeTupleForeach(bool isStatic, bool isDecl)(Scope* sc, ForeachStatement fs, Dsymbols* dbody, bool needExpansion)
 {
     scope v = new StatementSemanticVisitor(sc);
-    static if(!isDecl)
-    {
-        v.makeTupleForeach!(isStatic, isDecl)(fs, args);
-        return v.result;
-    }
-    else
-    {
-        return v.makeTupleForeach!(isStatic, isDecl)(fs, args);
-    }
+    return v.makeTupleForeach!(isStatic, isDecl)(fs, dbody, needExpansion);
 }
 
 /*********************************
@@ -4731,7 +4697,7 @@ private Statements* flatten(Statement statement, Scope* sc)
             sfs.sfe.prepare(sc);
             if (sfs.sfe.ready())
             {
-                auto s = makeTupleForeach!(true, false)(sc, sfs.sfe.aggrfe, sfs.sfe.needExpansion);
+                Statement s = makeTupleForeach!(true, false)(sc, sfs.sfe.aggrfe, null, sfs.sfe.needExpansion).statement;
                 auto result = s.flatten(sc);
                 if (result)
                 {
index 2f27414a56c7ea9063c3c5ede73179e1e68deb77..d1578ec3a121d67452441d30e313dc57b016e53f 100644 (file)
@@ -22,7 +22,7 @@ import dmd.globals;
 import dmd.identifier;
 import dmd.mtype;
 import dmd.root.array;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.tokens;
 
 
index d5b3de2c522cbb9cee86c50835b2875f2d37043f..16739addf57355b2a5b70f52f2638bd4040bae27 100644 (file)
@@ -316,7 +316,8 @@ struct TargetC
     enum BitFieldStyle : ubyte
     {
         Unspecified,
-        Dm_Ms,                /// Digital Mars and Microsoft C compilers
+        DM,                   /// Digital Mars 32 bit C compiler
+        MS,                   /// Microsoft 32 and 64 bit C compilers
                               /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
                               /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
         Gcc_Clang,            /// gcc and clang
index 83281a6358f58524c4598956e5eecf76e2168f86..6a75ccc5ebd8d60d98c4f4476954f8f8c16d4978 100644 (file)
@@ -63,7 +63,8 @@ struct TargetC
     enum class BitFieldStyle : unsigned char
     {
         Unspecified,
-        Dm_Ms,                // Digital Mars and Microsoft C compilers
+        DM,                   // Digital Mars 32 bit C compiler
+        MS,                   // Microsoft 32 and 64 bit C compilers
                               // https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
                               // https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
         Gcc_Clang,            // gcc and clang
index 08ce9acef99f301b3993ea1c893927d58338aa44..69cc84f6573cf8d7de9118bf2eeb280dacddedd2 100644 (file)
@@ -131,7 +131,7 @@ public:
     virtual bool declareParameter(Scope *sc) = 0;
     virtual void print(RootObject *oarg, RootObject *oded) = 0;
     virtual RootObject *specialization() = 0;
-    virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0;
+    virtual RootObject *defaultArg(const Loc &instLoc, Scope *sc) = 0;
     virtual bool hasDefaultArg() = 0;
 
     /* Create dummy argument based on parameter.
@@ -154,7 +154,7 @@ public:
     bool declareParameter(Scope *sc);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
-    RootObject *defaultArg(Loc instLoc, Scope *sc);
+    RootObject *defaultArg(const Loc &instLoc, Scope *sc);
     bool hasDefaultArg();
     RootObject *dummyArg();
     void accept(Visitor *v) { v->visit(this); }
@@ -186,7 +186,7 @@ public:
     bool declareParameter(Scope *sc);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
-    RootObject *defaultArg(Loc instLoc, Scope *sc);
+    RootObject *defaultArg(const Loc &instLoc, Scope *sc);
     bool hasDefaultArg();
     RootObject *dummyArg();
     void accept(Visitor *v) { v->visit(this); }
@@ -207,7 +207,7 @@ public:
     bool declareParameter(Scope *sc);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
-    RootObject *defaultArg(Loc instLoc, Scope *sc);
+    RootObject *defaultArg(const Loc &instLoc, Scope *sc);
     bool hasDefaultArg();
     RootObject *dummyArg();
     void accept(Visitor *v) { v->visit(this); }
@@ -224,7 +224,7 @@ public:
     bool declareParameter(Scope *sc);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
-    RootObject *defaultArg(Loc instLoc, Scope *sc);
+    RootObject *defaultArg(const Loc &instLoc, Scope *sc);
     bool hasDefaultArg();
     RootObject *dummyArg();
     void accept(Visitor *v) { v->visit(this); }
index 7680fb8500b658d472b7a8742b5d9aea01c7883c..1ea51a89bff7a9634bc49d14390f20a000ffc8fa 100644 (file)
@@ -19,7 +19,7 @@ import core.stdc.string;
 import dmd.globals;
 import dmd.identifier;
 import dmd.root.ctfloat;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rmem;
 import dmd.utf;
 
index 0fd6634f2ce586472e3b940202f77da5b2362208..d14d0aab5939ea46337906b210ad58cca29a8af8 100644 (file)
@@ -187,6 +187,7 @@ enum
         TOKarrow,
         TOKcolonColon,
         TOKwchar_tLiteral,
+        TOKcompoundLiteral,
 
         TOKinline,
         TOKregister,
index 8f968ed0dc2ecb648a00e8200f9cd284da219e43..cc1d2e351e634cfef1b9753aa1d654d658d6d9c9 100644 (file)
@@ -49,7 +49,7 @@ import dmd.tokens;
 import dmd.typesem;
 import dmd.visitor;
 import dmd.root.rootobject;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.string;
 
 enum LOGSEMANTIC = false;
@@ -1410,19 +1410,30 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto o = (*e.args)[0];
         auto o1 = (*e.args)[1];
 
-        FuncDeclaration fd;
-        TypeFunction tf = toTypeFunction(o, fd);
-
         ParameterList fparams;
-        if (tf)
-            fparams = tf.parameterList;
-        else if (fd)
-            fparams = fd.getParameterList();
+
+        CallExp ce;
+        if (auto exp = isExpression(o))
+            ce = exp.isCallExp();
+
+        if (ce)
+        {
+            fparams = ce.f.getParameterList();
+        }
         else
         {
-            e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function",
-                o.toChars(), o1.toChars());
-            return ErrorExp.get();
+            FuncDeclaration fd;
+            auto tf = toTypeFunction(o, fd);
+            if (tf)
+                fparams = tf.parameterList;
+            else if (fd)
+                fparams = fd.getParameterList();
+            else
+            {
+                e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function or a function call",
+                    o.toChars(), o1.toChars());
+                return ErrorExp.get();
+            }
         }
 
         // Avoid further analysis for invalid functions leading to misleading error messages
index ace4e423bccf25ac78fdcadd733e305f6b831fb7..f75ae0e0b5af9ab203f4f8afe0424e1b746c15b1 100644 (file)
@@ -44,6 +44,7 @@ import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.imphint;
+import dmd.importc;
 import dmd.init;
 import dmd.initsem;
 import dmd.visitor;
@@ -53,7 +54,7 @@ import dmd.opover;
 import dmd.parse;
 import dmd.root.ctfloat;
 import dmd.root.rmem;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.root.stringtable;
@@ -1334,6 +1335,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                         continue;
                 }
 
+                fparam.type = fparam.type.cAdjustParamType(sc); // adjust C array and function parameter types
+
                 Type t = fparam.type.toBasetype();
 
                 /* If fparam after semantic() turns out to be a tuple, the number of parameters may
@@ -1378,6 +1381,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                                 stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl);
                         }
                         fparam.type = new TypeTuple(newparams);
+                        fparam.type = fparam.type.typeSemantic(loc, argsc);
                     }
                     fparam.storageClass = STC.parameter;
 
@@ -1627,7 +1631,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             errors = true;
         }
 
-        if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0)
+        if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0 &&
+            !(sc.flags & SCOPE.Cfile))
         {
             .error(loc, "variadic functions with non-D linkage must have at least one parameter");
             errors = true;
@@ -1750,10 +1755,10 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             {
                 // if there was an error evaluating the symbol, it might actually
                 // be a type. Avoid misleading error messages.
-               .error(loc, "`%s` had previous errors", mtype.toChars());
+                .error(loc, "`%s` had previous errors", mtype.toChars());
             }
             else
-               .error(loc, "`%s` is used as a type", mtype.toChars());
+                .error(loc, "`%s` is used as a type", mtype.toChars());
             return error();
         }
         return t;
@@ -2133,6 +2138,15 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                      * struct S { int a; } *s;
                      */
                     sd.members = mtype.members;
+                    if (sd.semanticRun == PASS.semanticdone)
+                    {
+                        /* The first semantic pass marked `sd` as an opaque struct.
+                         * Re-run semantic so that all newly assigned members are
+                         * picked up and added to the symtab.
+                         */
+                        sd.semanticRun = PASS.semantic;
+                        sd.dsymbolSemantic(sc);
+                    }
                 }
                 else
                 {
@@ -2264,7 +2278,7 @@ RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
  * Returns:
  *      the type that was merged
  */
-Type merge(Type type)
+extern (C++) Type merge(Type type)
 {
     switch (type.ty)
     {
@@ -2361,7 +2375,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
         {
             const explicitAlignment = mt.alignment();
             const naturalAlignment = mt.alignsize();
-            const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
+            const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
             e = new IntegerExp(loc, actualAlignment, Type.tsize_t);
         }
         else if (ident == Id._init)
@@ -3734,10 +3748,18 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
     }
 
     /***************************************
-     * Figures out what to do with an undefined member reference
-     * for classes and structs.
-     *
-     * If flag & 1, don't report "not a property" error and just return NULL.
+     * `ident` was not found as a member of `mt`.
+     * Attempt to use overloaded opDot(), overloaded opDispatch(), or `alias this`.
+     * If that fails, forward to visitType().
+     * Params:
+     *  mt = class or struct
+     *  sc = context
+     *  e = `this` for `ident`
+     *  ident = name of member
+     *  flag = flag & 1, don't report "not a property" error and just return NULL.
+     *         flag & DotExpFlag.noAliasThis, don't do 'alias this' resolution.
+     * Returns:
+     *  resolved expression if found, otherwise null
      */
     Expression noMember(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
     {
@@ -3828,7 +3850,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
 
             /* See if we should forward to the alias this.
              */
-            auto alias_e = resolveAliasThis(sc, e, gagError);
+            auto alias_e = flag & DotExpFlag.noAliasThis ? null
+                                                         : resolveAliasThis(sc, e, gagError);
             if (alias_e && alias_e != e)
             {
                 /* Rewrite e.ident as:
@@ -4611,7 +4634,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
  * Returns:
  *  The initialization expression for the type.
  */
-Expression defaultInit(Type mt, const ref Loc loc)
+extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
 {
     Expression visitBasic(TypeBasic mt)
     {
@@ -4744,6 +4767,7 @@ Expression defaultInit(Type mt, const ref Loc loc)
         }
         auto cond = IntegerExp.createBool(false);
         auto msg = new StringExp(loc, "Accessed expression of type `noreturn`");
+        msg.type = Type.tstring;
         auto ae = new AssertExp(loc, cond, msg);
         ae.type = mt;
         return ae;
index d8160f0d633a7fcd399b46cf24c469c5177da690..d05af61ce6fd12153f3a6d3690f38d3275f84076 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Generate `TypeInfo` objects, which are needed for run-time introspection of classes.
+ * Generate `TypeInfo` objects, which are needed for run-time introspection of types.
  *
  * Copyright:   Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
 
 module dmd.typinf;
 
+import dmd.astenums;
+import dmd.declaration;
+import dmd.dmodule;
 import dmd.dscope;
+import dmd.dclass;
+import dmd.dstruct;
+import dmd.errors;
 import dmd.globals;
+import dmd.gluelayer;
 import dmd.mtype;
+import dmd.visitor;
+import core.stdc.stdio;
+
+/****************************************************
+ * Generates the `TypeInfo` object associated with `torig` if it
+ * hasn't already been generated
+ * Params:
+ *      loc   = the location for reporting line numbers in errors
+ *      torig = the type to generate the `TypeInfo` object for
+ *      sc    = the scope
+ */
+extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
+{
+    // printf("genTypeInfo() %s\n", torig.toChars());
+
+    // Even when compiling without `useTypeInfo` (e.g. -betterC) we should
+    // still be able to evaluate `TypeInfo` at compile-time, just not at runtime.
+    // https://issues.dlang.org/show_bug.cgi?id=18472
+    if (!sc || !(sc.flags & SCOPE.ctfe))
+    {
+        if (!global.params.useTypeInfo)
+        {
+            .error(loc, "`TypeInfo` cannot be used with -betterC");
+            fatal();
+        }
+    }
+
+    if (!Type.dtypeinfo)
+    {
+        .error(loc, "`object.TypeInfo` could not be found, but is implicitly used");
+        fatal();
+    }
+
+    Type t = torig.merge2(); // do this since not all Type's are merge'd
+    if (!t.vtinfo)
+    {
+        if (t.isShared()) // does both 'shared' and 'shared const'
+            t.vtinfo = TypeInfoSharedDeclaration.create(t);
+        else if (t.isConst())
+            t.vtinfo = TypeInfoConstDeclaration.create(t);
+        else if (t.isImmutable())
+            t.vtinfo = TypeInfoInvariantDeclaration.create(t);
+        else if (t.isWild())
+            t.vtinfo = TypeInfoWildDeclaration.create(t);
+        else
+            t.vtinfo = getTypeInfoDeclaration(t);
+        assert(t.vtinfo);
+
+        // ClassInfos are generated as part of ClassDeclaration codegen
+        const isUnqualifiedClassInfo = (t.ty == Tclass && !t.mod);
+
+        // generate a COMDAT for other TypeInfos not available as builtins in
+        // druntime
+        if (!isUnqualifiedClassInfo && !builtinTypeInfo(t))
+        {
+            if (sc) // if in semantic() pass
+            {
+                // Find module that will go all the way to an object file
+                Module m = sc._module.importedFrom;
+                m.members.push(t.vtinfo);
+            }
+            else // if in obj generation pass
+            {
+                toObjFile(t.vtinfo, global.params.multiobj);
+            }
+        }
+    }
+    if (!torig.vtinfo)
+        torig.vtinfo = t.vtinfo; // Types aren't merged, but we can share the vtinfo's
+    assert(torig.vtinfo);
+}
 
 /****************************************************
  * Gets the type of the `TypeInfo` object associated with `t`
@@ -24,5 +102,161 @@ import dmd.mtype;
  * Returns:
  *      The type of the `TypeInfo` object associated with `t`
  */
-extern (C++) Type getTypeInfoType(Loc loc, Type t, Scope* sc);
+extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc);
+
+private TypeInfoDeclaration getTypeInfoDeclaration(Type t)
+{
+    //printf("Type::getTypeInfoDeclaration() %s\n", t.toChars());
+    switch (t.ty)
+    {
+    case Tpointer:
+        return TypeInfoPointerDeclaration.create(t);
+    case Tarray:
+        return TypeInfoArrayDeclaration.create(t);
+    case Tsarray:
+        return TypeInfoStaticArrayDeclaration.create(t);
+    case Taarray:
+        return TypeInfoAssociativeArrayDeclaration.create(t);
+    case Tstruct:
+        return TypeInfoStructDeclaration.create(t);
+    case Tvector:
+        return TypeInfoVectorDeclaration.create(t);
+    case Tenum:
+        return TypeInfoEnumDeclaration.create(t);
+    case Tfunction:
+        return TypeInfoFunctionDeclaration.create(t);
+    case Tdelegate:
+        return TypeInfoDelegateDeclaration.create(t);
+    case Ttuple:
+        return TypeInfoTupleDeclaration.create(t);
+    case Tclass:
+        if ((cast(TypeClass)t).sym.isInterfaceDeclaration())
+            return TypeInfoInterfaceDeclaration.create(t);
+        else
+            return TypeInfoClassDeclaration.create(t);
+
+    default:
+        return TypeInfoDeclaration.create(t);
+    }
+}
+
+/**************************************************
+ * Returns:
+ *      true if any part of type t is speculative.
+ *      if t is null, returns false.
+ */
+bool isSpeculativeType(Type t)
+{
+    static bool visitVector(TypeVector t)
+    {
+        return isSpeculativeType(t.basetype);
+    }
+
+    static bool visitAArray(TypeAArray t)
+    {
+        return isSpeculativeType(t.index) ||
+               isSpeculativeType(t.next);
+    }
+
+    static bool visitStruct(TypeStruct t)
+    {
+        StructDeclaration sd = t.sym;
+        if (auto ti = sd.isInstantiated())
+        {
+            if (!ti.needsCodegen())
+            {
+                if (ti.minst || sd.requestTypeInfo)
+                    return false;
+
+                /* https://issues.dlang.org/show_bug.cgi?id=14425
+                 * TypeInfo_Struct would refer the members of
+                 * struct (e.g. opEquals via xopEquals field), so if it's instantiated
+                 * in speculative context, TypeInfo creation should also be
+                 * stopped to avoid 'unresolved symbol' linker errors.
+                 */
+                /* When -debug/-unittest is specified, all of non-root instances are
+                 * automatically changed to speculative, and here is always reached
+                 * from those instantiated non-root structs.
+                 * Therefore, if the TypeInfo is not auctually requested,
+                 * we have to elide its codegen.
+                 */
+                return true;
+            }
+        }
+        else
+        {
+            //assert(!sd.inNonRoot() || sd.requestTypeInfo);    // valid?
+        }
+        return false;
+    }
+
+    static bool visitClass(TypeClass t)
+    {
+        ClassDeclaration sd = t.sym;
+        if (auto ti = sd.isInstantiated())
+        {
+            if (!ti.needsCodegen() && !ti.minst)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
 
+
+    static bool visitTuple(TypeTuple t)
+    {
+        if (t.arguments)
+        {
+            foreach (arg; *t.arguments)
+            {
+                if (isSpeculativeType(arg.type))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    if (!t)
+        return false;
+    Type tb = t.toBasetype();
+    switch (tb.ty)
+    {
+        case Tvector:   return visitVector(tb.isTypeVector());
+        case Taarray:   return visitAArray(tb.isTypeAArray());
+        case Tstruct:   return visitStruct(tb.isTypeStruct());
+        case Tclass:    return visitClass(tb.isTypeClass());
+        case Ttuple:    return visitTuple(tb.isTypeTuple());
+        case Tenum:     return false;
+        default:
+        return isSpeculativeType(tb.nextOf());
+
+        /* For TypeFunction, TypeInfo_Function doesn't store parameter types,
+         * so only the .next (the return type) is checked here.
+         */
+    }
+}
+
+/* ========================================================================= */
+
+/* Indicates whether druntime already contains an appropriate TypeInfo instance
+ * for the specified type (in module rt.util.typeinfo).
+ */
+extern (C++) bool builtinTypeInfo(Type t)
+{
+    if (!t.mod) // unqualified types only
+    {
+        // unqualified basic types + typeof(null)
+        if (t.isTypeBasic() || t.ty == Tnull)
+            return true;
+        // some unqualified arrays
+        if (t.ty == Tarray)
+        {
+            Type next = t.nextOf();
+            return (next.isTypeBasic() && !next.mod)                     // of unqualified basic types
+                || (next.ty == Tchar && next.mod == MODFlags.immutable_) // string
+                || (next.ty == Tchar && next.mod == MODFlags.const_);    // const(char)[]
+        }
+    }
+    return false;
+}
diff --git a/gcc/d/dmd/utf.h b/gcc/d/dmd/utf.h
deleted file mode 100644 (file)
index b3782af..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/utf.h
- */
-
-#pragma once
-
-#include "root/dsystem.h"
-
-/// A UTF-8 code unit
-typedef unsigned char   utf8_t;
-/// A UTF-16 code unit
-typedef unsigned short  utf16_t;
-/// A UTF-32 code unit
-typedef unsigned int    utf32_t;
-typedef utf32_t         dchar_t;
-
-#define ALPHA_TABLE_LENGTH 245
-static utf16_t const ALPHA_TABLE[ALPHA_TABLE_LENGTH][2] =
-{
-    { 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA },
-    { 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 }, { 0x00F8, 0x01F5 }, { 0x01FA, 0x0217 },
-    { 0x0250, 0x02A8 }, { 0x02B0, 0x02B8 }, { 0x02BB, 0x02BB }, { 0x02BD, 0x02C1 },
-    { 0x02D0, 0x02D1 }, { 0x02E0, 0x02E4 }, { 0x037A, 0x037A }, { 0x0386, 0x0386 },
-    { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE },
-    { 0x03D0, 0x03D6 }, { 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
-    { 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C }, { 0x040E, 0x044F },
-    { 0x0451, 0x045C }, { 0x045E, 0x0481 }, { 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 },
-    { 0x04CB, 0x04CC }, { 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
-    { 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0587 }, { 0x05B0, 0x05B9 },
-    { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05D0, 0x05EA },
-    { 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0640, 0x0652 }, { 0x0660, 0x0669 },
-    { 0x0670, 0x06B7 }, { 0x06BA, 0x06BE }, { 0x06C0, 0x06CE }, { 0x06D0, 0x06DC },
-    { 0x06E5, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x06F0, 0x06F9 }, { 0x0901, 0x0903 },
-    { 0x0905, 0x0939 }, { 0x093D, 0x094D }, { 0x0950, 0x0952 }, { 0x0958, 0x0963 },
-    { 0x0966, 0x096F }, { 0x0981, 0x0983 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 },
-    { 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 },
-    { 0x09BE, 0x09C4 }, { 0x09C7, 0x09C8 }, { 0x09CB, 0x09CD }, { 0x09DC, 0x09DD },
-    { 0x09DF, 0x09E3 }, { 0x09E6, 0x09F1 }, { 0x0A02, 0x0A02 }, { 0x0A05, 0x0A0A },
-    { 0x0A0F, 0x0A10 }, { 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 },
-    { 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A3E, 0x0A42 }, { 0x0A47, 0x0A48 },
-    { 0x0A4B, 0x0A4D }, { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A66, 0x0A6F },
-    { 0x0A74, 0x0A74 }, { 0x0A81, 0x0A83 }, { 0x0A85, 0x0A8B }, { 0x0A8D, 0x0A8D },
-    { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 },
-    { 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0AC5 }, { 0x0AC7, 0x0AC9 }, { 0x0ACB, 0x0ACD },
-    { 0x0AD0, 0x0AD0 }, { 0x0AE0, 0x0AE0 }, { 0x0AE6, 0x0AEF }, { 0x0B01, 0x0B03 },
-    { 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
-    { 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B43 }, { 0x0B47, 0x0B48 },
-    { 0x0B4B, 0x0B4D }, { 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B66, 0x0B6F },
-    { 0x0B82, 0x0B83 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 },
-    { 0x0B99, 0x0B9A }, { 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
-    { 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 }, { 0x0BBE, 0x0BC2 },
-    { 0x0BC6, 0x0BC8 }, { 0x0BCA, 0x0BCD }, { 0x0BE7, 0x0BEF }, { 0x0C01, 0x0C03 },
-    { 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 }, { 0x0C2A, 0x0C33 },
-    { 0x0C35, 0x0C39 }, { 0x0C3E, 0x0C44 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D },
-    { 0x0C60, 0x0C61 }, { 0x0C66, 0x0C6F }, { 0x0C82, 0x0C83 }, { 0x0C85, 0x0C8C },
-    { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 }, { 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 },
-    { 0x0CBE, 0x0CC4 }, { 0x0CC6, 0x0CC8 }, { 0x0CCA, 0x0CCD }, { 0x0CDE, 0x0CDE },
-    { 0x0CE0, 0x0CE1 }, { 0x0CE6, 0x0CEF }, { 0x0D02, 0x0D03 }, { 0x0D05, 0x0D0C },
-    { 0x0D0E, 0x0D10 }, { 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D3E, 0x0D43 },
-    { 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D61 }, { 0x0D66, 0x0D6F },
-    { 0x0E01, 0x0E3A }, { 0x0E40, 0x0E5B }, { 0x0E81, 0x0E82 },
-    { 0x0E84, 0x0E84 }, { 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D },
-    { 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 }, { 0x0EA5, 0x0EA5 },
-    { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB }, { 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB9 },
-    { 0x0EBB, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0EC6, 0x0EC6 }, { 0x0EC8, 0x0ECD },
-    { 0x0ED0, 0x0ED9 }, { 0x0EDC, 0x0EDD }, { 0x0F00, 0x0F00 }, { 0x0F18, 0x0F19 },
-    { 0x0F20, 0x0F33 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
-    { 0x0F3E, 0x0F47 }, { 0x0F49, 0x0F69 }, { 0x0F71, 0x0F84 }, { 0x0F86, 0x0F8B },
-    { 0x0F90, 0x0F95 }, { 0x0F97, 0x0F97 }, { 0x0F99, 0x0FAD }, { 0x0FB1, 0x0FB7 },
-    { 0x0FB9, 0x0FB9 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 }, { 0x1E00, 0x1E9B },
-    { 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D }, { 0x1F20, 0x1F45 },
-    { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 }, { 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B },
-    { 0x1F5D, 0x1F5D }, { 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC },
-    { 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC }, { 0x1FD0, 0x1FD3 },
-    { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC }, { 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC },
-    { 0x203F, 0x2040 }, { 0x207F, 0x207F }, { 0x2102, 0x2102 }, { 0x2107, 0x2107 },
-    { 0x210A, 0x2113 }, { 0x2115, 0x2115 }, { 0x2118, 0x211D }, { 0x2124, 0x2124 },
-    { 0x2126, 0x2126 }, { 0x2128, 0x2128 }, { 0x212A, 0x2131 }, { 0x2133, 0x2138 },
-    { 0x2160, 0x2182 }, { 0x3005, 0x3007 }, { 0x3021, 0x3029 }, { 0x3041, 0x3093 },
-    { 0x309B, 0x309C }, { 0x30A1, 0x30F6 }, { 0x30FB, 0x30FC }, { 0x3105, 0x312C },
-    { 0x4E00, 0x9FA5 }, { 0xAC00, 0xD7A3 },
-};
-
-char const *const UTF8_DECODE_OK = NULL;
-extern char const UTF8_DECODE_OUTSIDE_CODE_SPACE[];
-extern char const UTF8_DECODE_TRUNCATED_SEQUENCE[];
-extern char const UTF8_DECODE_OVERLONG[];
-extern char const UTF8_DECODE_INVALID_TRAILER[];
-extern char const UTF8_DECODE_INVALID_CODE_POINT[];
-
-char const *const UTF16_DECODE_OK = NULL;
-extern char const UTF16_DECODE_TRUNCATED_SEQUENCE[];
-extern char const UTF16_DECODE_INVALID_SURROGATE[];
-extern char const UTF16_DECODE_UNPAIRED_SURROGATE[];
-extern char const UTF16_DECODE_INVALID_CODE_POINT[];
-
-/// \return true if \a c is a valid, non-private UTF-32 code point
-bool utf_isValidDchar(dchar_t c);
-
-bool isUniAlpha(dchar_t c);
-
-int utf_codeLengthChar(dchar_t c);
-int utf_codeLengthWchar(dchar_t c);
-int utf_codeLength(int sz, dchar_t c);
-
-void utf_encodeChar(utf8_t *s, dchar_t c);
-void utf_encodeWchar(utf16_t *s, dchar_t c);
-void utf_encode(int sz, void *s, dchar_t c);
-
-const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult);
-const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult);
index 600521fbd495db0e159948a5bc5ab9c549661355..6cd5d20f6f78d8ed6e997d5e85d795c7a5a265c0 100644 (file)
@@ -16,7 +16,7 @@ import dmd.errors;
 import dmd.globals;
 import dmd.root.file;
 import dmd.root.filename;
-import dmd.root.outbuffer;
+import dmd.common.outbuffer;
 import dmd.root.string;
 
 
index 31680564bdd7911927b831f74894951eb391523c..2831eefc4ba6469a368cc89ab3ad238603b1cc3d 100644 (file)
@@ -1757,7 +1757,7 @@ public:
                /* C++ constructors return void, even though front-end semantic
                   treats them as implicitly returning `this'.  Set returnvalue
                   to override the result of this expression.  */
-               if (fd->isCtorDeclaration () && fd->linkage == LINK::cpp)
+               if (fd->isCtorDeclaration ())
                  {
                    thisexp = d_save_expr (thisexp);
                    returnvalue = thisexp;
@@ -1846,6 +1846,11 @@ public:
       {
        tree init = TARGET_EXPR_INITIAL (cleanup);
        TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp);
+
+       /* Keep the return value outside the TARGET_EXPR.  */
+       if (returnvalue != NULL_TREE)
+         cleanup = compound_expr (cleanup, TREE_OPERAND (exp, 1));
+
        exp = cleanup;
       }
 
@@ -1856,7 +1861,7 @@ public:
 
   void visit (DelegateExp *e)
   {
-    if (e->func->semanticRun == PASSsemantic3done)
+    if (e->func->semanticRun == PASS::semantic3done)
       {
        /* Add the function as nested function if it belongs to this module.
           ie: it is a member of this module, or it is a template instance.  */
index c98eb1f45d958c7df11ccbb53c1d9048c0665181..d37d205e870fe123029b4f6b34e6b966ba2cc7b8 100644 (file)
@@ -283,6 +283,13 @@ Sets @code{__traits(getTargetInfo "cppStd")} to @code{202002}.
 @cindex @option{-fno-invariants}
 Turns off code generation for class @code{invariant} contracts.
 
+@item -fmain
+@cindex @option{-fmain}
+Generates a default @code{main()} function when compiling.  This is useful when
+unittesting a library, as it enables running the unittests in a library without
+having to manually define an entry-point function.  This option does nothing
+when @code{main} is already defined in user code.
+
 @item -fno-moduleinfo
 @cindex @option{-fmoduleinfo}
 @cindex @option{-fno-moduleinfo}
@@ -742,6 +749,8 @@ List information on all D language transitions.
 List all usages of complex or imaginary types.
 @item field
 List all non-mutable fields which occupy an object instance.
+@item in
+List all usages of @code{in} on parameter.
 @item nogc
 List all hidden GC allocations.
 @item templates
index f7f90fb08c32fe8f39663145de6cacbd744e64ae..d0a5e2f685966c22981c37fa35b4b40a80372ceb 100644 (file)
@@ -436,6 +436,10 @@ ftransition=field
 D RejectNegative
 List all non-mutable fields which occupy an object instance.
 
+ftransition=in
+D RejectNegative
+List all usages of 'in' on parameter.
+
 ftransition=nogc
 D RejectNegative
 List all hidden GC allocations.
index 06eb5ae3424c38c49fc33dc7973f2b9a609d7f50..cb5c4a7b1e78665fea6eb78a2bf00af2508ad39f 100644 (file)
@@ -145,7 +145,7 @@ get_internal_fn (tree ident, const Visibility &visibility)
   fd->loc = Loc (mod->srcfile.toChars (), 1, 0);
   fd->parent = mod;
   fd->visibility = visibility;
-  fd->semanticRun = PASSsemantic3done;
+  fd->semanticRun = PASS::semantic3done;
 
   return fd;
 }
index db500ee2efedf65783d27acee3b2631c0dd166be..b39b92eb822668ce08657ba1194d58b060dbca22 100644 (file)
@@ -610,7 +610,8 @@ public:
 
   void visit (TypeNoreturn *t)
   {
-    t->ctype = void_type_node;
+    t->ctype = noreturn_type_node;
+    TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
   }
 
   /* Basic Data Types.  */
@@ -770,11 +771,17 @@ public:
        fnparams = chainon (fnparams, build_tree_list (0, type));
       }
 
-    size_t n_args = t->parameterList.length ();
+    const size_t n_args = t->parameterList.length ();
 
     for (size_t i = 0; i < n_args; i++)
       {
        tree type = parameter_type (t->parameterList[i]);
+
+       /* Type `noreturn` is a terminator, as no other arguments can possibly
+          be evaluated after it.  */
+       if (type == noreturn_type_node)
+         break;
+
        fnparams = chainon (fnparams, build_tree_list (0, type));
       }
 
@@ -797,6 +804,10 @@ public:
     TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
     d_keep (t->ctype);
 
+    /* Qualify function types that have the type `noreturn` as volatile.  */
+    if (fntype == noreturn_type_node)
+      t->ctype = build_qualified_type (t->ctype, TYPE_QUAL_VOLATILE);
+
     /* Handle any special support for calling conventions.  */
     switch (t->linkage)
       {
@@ -995,8 +1006,8 @@ public:
           the context or laying out fields as those types may make
           recursive references to this type.  */
        unsigned structsize = t->sym->structsize;
-       unsigned alignsize = (t->sym->alignment != STRUCTALIGN_DEFAULT)
-         ? t->sym->alignment : t->sym->alignsize;
+       unsigned alignsize = t->sym->alignment.isDefault ()
+         ? t->sym->alignsize : t->sym->alignment.get ();
 
        TYPE_SIZE (t->ctype) = bitsize_int (structsize * BITS_PER_UNIT);
        TYPE_SIZE_UNIT (t->ctype) = size_int (structsize);
diff --git a/gcc/testsuite/gdc.test/compilable/b19294.d b/gcc/testsuite/gdc.test/compilable/b19294.d
new file mode 100644 (file)
index 0000000..063a9df
--- /dev/null
@@ -0,0 +1,69 @@
+alias MT = MyStruct!int;
+
+struct MyStruct(T)
+{
+    T x;
+
+    this(T y)
+    {
+        x = y;
+    }
+
+    MyStruct!T opBinary(string op)(MyStruct!T y) const
+    {
+        alias C = typeof(return);
+        auto w = C(this.x);
+        return w.opOpAssign!(op)(y);
+    }
+
+    MyStruct!T opBinaryRight(string op)(MyStruct!T y) const
+    {
+        return opBinary!(op)(y);
+    }
+
+    ref MyStruct opOpAssign(string op, T)(const MyStruct!T z)
+    {
+        mixin ("x "~op~"= z.x;");
+        return this;
+    }
+
+    MyStruct!T opBinary(string op)(T y) const
+    {
+        alias C = typeof(return);
+        auto w = C(this.x);
+        return w.opOpAssign!(op)(y);
+    }
+
+    MyStruct!T opBinaryRight(string op)(T y) const
+    {
+        return opBinary!(op)(y);
+    }
+
+    ref MyStruct opOpAssign(string op, T)(const T z)
+    {
+        mixin ("x "~op~"= z;");
+        return this;
+    }
+}
+
+void test()
+{
+    MT s = MyStruct!int(1);
+    MT[] arr = [s, 2 * s, 3 * s, 4 * s, 5 * s, 6 * s];
+    MT[] result = new MT[arr.length];
+    
+    result[] = arr[] + s;
+    result[] = s + arr[];
+    
+    result[] = arr[] - s;
+    result[] = s - arr[];
+    
+    result[] = arr[] * s;
+    result[] = s * arr[];
+    
+    result[] = arr[] / s;
+    result[] = s / arr[];
+    
+    result[] = arr[] ^^ s;
+    result[] = s ^^ arr[];
+}
index 614bdc8c984ef878ade22df46880a21f1792b31e..424881867172fcce4d071028e47623a18331a5b3 100644 (file)
@@ -2,7 +2,7 @@
 // REQUIRED_ARGS: -O
 // POST_SCRIPT: compilable/extra-files/objdump-postscript.sh
 // only testing on SYSV-ABI, but backend code is identical across platforms
-// DISABLED: win32 win64 osx linux32 freebsd32 freebsd64
+// DISABLED: win32 win64 osx linux32 freebsd32 freebsd64 openbsd32 openbsd64
 
 bool test_ltz(ubyte x) { return x <  0; }
 bool test_lez(ubyte x) { return x <= 0; }
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_22285.d
new file mode 100644 (file)
index 0000000..5e8836d
--- /dev/null
@@ -0,0 +1,15 @@
+// PERMUTE_ARGS:
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_tables_22285.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_tables_22285.html
+
+module test.compilable.ddoc_markdown_tables_22285;
+
+/**
+| A | B | C |
+|---|---|---|
+| a | 0 |   |
+| b | 1 1 1   |              |
+| c | 2 |   |
+*/
+enum _ = 0;
index 54bbc79bf46e7d9c5229e88ee5972b83e01168af..47c0172009dfcb294986fcc57b70ee29e5be3c80 100644 (file)
@@ -144,4 +144,7 @@ __gshared void function(ifloat) onVariableFunctionParam;
 
 __gshared ifloat delegate() onVariableDelegate;
 
-noreturn myExit() {}
+noreturn myExit()
+{
+    assert(false);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
deleted file mode 100644 (file)
index f6aaf3b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// check bugs in importing C files
-
-int squared(int a)
-{
-    return a * a;
-}
index 43803df12cf8b9da5cc1d4787860693cabccae1f..d160bd410ad16511f8b0d5ec7f251210a96786b7 100644 (file)
@@ -66,3 +66,52 @@ static assert(is(T8 == const(ubyte*)));
 alias T8 = mixin(q{immutable(__traits(getMember, S, "T"))})*;
 static assert(is(T8 == immutable(float*)*));
 */
+
+/**************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=22356
+
+mixin("void") func22356(int) { }
+static assert(is(typeof(&func22356) == void function(int)));
+
+static mixin("void") func22356_s(char) { }
+static assert(is(typeof(&func22356_s) == void function(char)));
+
+mixin("int")[2] func22356_2(int) { return [1, 2]; }
+static assert(is(typeof(&func22356_2) == int[2] function(int)));
+
+mixin("int") func22356tp(S, T)(S, T) { return 1; }
+static assert(is(typeof(&func22356tp!(char, float)) == int function(char, float) pure nothrow @nogc @safe));
+
+mixin("int") x22356;
+static assert(is(typeof(x22356) == int));
+
+mixin("int")** xpp22356;
+static assert(is(typeof(xpp22356) == int**));
+
+mixin("int") y22356, z22356;
+static assert(is(typeof(y22356) == int) && is(typeof(z22356) == int));
+
+// Already working but for completeness
+void test_statements_22356()
+{
+    mixin("void") func22356(int) { }
+    static assert(is(typeof(&func22356) == void delegate(int) pure nothrow @nogc @safe));
+
+    static mixin("void") func22356_s(char) { }
+    static assert(is(typeof(&func22356_s) == void function(char) pure nothrow @nogc @safe));
+
+    mixin("int")[2] func22356_2(int) { return [1, 2]; }
+    static assert(is(typeof(&func22356_2) == int[2] delegate(int) pure nothrow @nogc @safe));
+
+    mixin("int") func22356tp(S, T)(S, T) { return 1; }
+    static assert(is(typeof(&func22356tp!(char, float)) == int delegate(char, float) pure nothrow @nogc @safe));
+
+    mixin("int") x22356;
+    static assert(is(typeof(x22356) == int));
+
+    mixin("int")** xpp22356;
+    static assert(is(typeof(xpp22356) == int**));
+
+    mixin("int") y22356, z22356;
+    static assert(is(typeof(y22356) == int) && is(typeof(z22356) == int));
+}
index 7517bb26e0d78adc05e872685c6f65f04460ce4a..b041e072e9c2cb0833f904423768ec00a4fb5410 100644 (file)
@@ -49,8 +49,17 @@ static assert(noreturn.alignof == 0);
 static assert((noreturn*).sizeof == (int*).sizeof);
 static assert((noreturn[]).sizeof == (int[]).sizeof);
 
+static assert(is(typeof(noreturn.init) == noreturn));
+static assert(is(typeof((const noreturn).init) == const noreturn));
+static assert(is(typeof((immutable noreturn).init) == immutable noreturn));
+static assert(is(typeof((shared noreturn).init) == shared noreturn));
+
 version (DigitalMars)
-    noreturn exits(int* p) { *p = 3; }
+    noreturn exits(int* p)
+    {
+        *p = 3;
+        assert(false); // *p could be valid
+    }
 
 noreturn exit();
 
@@ -58,9 +67,47 @@ noreturn pureexits() @nogc nothrow pure @safe { assert(0); }
 
 noreturn callpureexits() { pureexits(); }
 
+noreturn returnExits()
+{
+    return pureexits();
+}
+
+void alsoExits()
+{
+    return assert(0);
+}
+
+int thisAlsoExits()
+{
+    return assert(0);
+}
+
+void cast_()
+{
+    noreturn n;
+    int i = n;
+}
+
 int test1(int i)
 {
     if (exit())
         return i + 1;
     return i - 1;
 }
+
+noreturn tlsNoreturn;
+__gshared noreturn globalNoreturn;
+
+template CreateTLS(A)
+{
+    A a;
+}
+
+void* useTls()
+{
+    alias Tnr = CreateTLS!noreturn;
+    void* a1 = &Tnr.a;
+    void* a2 = &tlsNoreturn;
+    void* a3 = &globalNoreturn;
+    return a1 < a2 ? a2 : a3;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/previewall.d b/gcc/testsuite/gdc.test/compilable/previewall.d
deleted file mode 100644 (file)
index e5ed7a8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// ARG_SETS: -preview=all
-// ARG_SETS: -transition=all
-// ARG_SETS: -revert=all
-import core.stdc.stdio;
-
-void main (string[] args)
-{
-    if (args.length == 42)
-        printf("Hello World\n");
-}
index 1d6fd4f39c7a9d6301d1519b89aba348878fe750..9a4db353e0a20a635c2d7f5c5a0f324977532262 100644 (file)
@@ -1,5 +1,11 @@
 // https://issues.dlang.org/show_bug.cgi?id=21997
 
+struct Strukt
+{
+    int i;
+    string s;
+}
+
 int nonPureFunc(int i)
 {
     return 2 * i;
@@ -28,6 +34,14 @@ int mainCtfe()
     auto baseDel = cast(int delegate(int)) pureDel;
     assert(baseDel(4) == 20);
     */
+
+    {
+        shared Strukt shStr;
+        Strukt str = *cast(Strukt*) &shStr;
+
+        shared(Strukt)* ptr = cast(shared(Strukt)*) &str;
+    }
+
     return 0;
 }
 
diff --git a/gcc/testsuite/gdc.test/compilable/sroa.d b/gcc/testsuite/gdc.test/compilable/sroa.d
new file mode 100644 (file)
index 0000000..8ea515c
--- /dev/null
@@ -0,0 +1,55 @@
+/* REQUIRED_ARGS: -O -release -inline
+This compares two different ways to do a for loop. The range
+version should SROA the VecRange struct into two register variables.
+*/
+
+extern (C):
+
+nothrow:
+@nogc:
+@safe:
+
+alias vec_base_t = size_t;                     // base type of vector
+alias vec_t = vec_base_t*;
+
+@trusted
+pure
+size_t vec_index(size_t b, const vec_t vec);
+
+@trusted
+pure ref inout(vec_base_t) vec_numbits(inout vec_t v) { return v[-1]; }
+@trusted
+pure ref inout(vec_base_t) vec_dim(inout vec_t v) { return v[-2]; }
+
+struct VecRange
+{
+    size_t i;
+    const vec_t v;
+
+  @nogc @safe nothrow pure:
+    this(const vec_t v) { this.v = v; i = vec_index(0, v); }
+    bool empty() const { return i == vec_numbits(v); }
+    size_t front() const { return i; }
+    void popFront() { i = vec_index(i + 1, v); }
+}
+
+@safe
+pure
+uint vec_numBitsSet(const vec_t vec)
+{
+    uint n = 0;
+    size_t length = vec_numbits(vec);
+    for (size_t i = 0; (i = vec_index(i, vec)) < length; ++i)
+        ++n;
+    return n;
+}
+
+@safe
+pure
+uint vec_numBitsSet2(const vec_t vec)
+{
+    uint n = 0;
+    foreach (j; VecRange(vec))
+        ++n;
+    return n;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/stc_traits.d b/gcc/testsuite/gdc.test/compilable/stc_traits.d
new file mode 100644 (file)
index 0000000..c5c4e5f
--- /dev/null
@@ -0,0 +1,172 @@
+// REQUIRED_ARGS: -preview=dip1000 -preview=in
+/*
+TEST_OUTPUT:
+---
+100 tuple()
+101 tuple("return", "ref")
+102 tuple("ref")
+103 tuple()
+104 tuple("ref")
+105 tuple()
+106 tuple()
+107 tuple("ref")
+108 tuple("ref")
+109 tuple("ref")
+110 tuple("ref")
+111 tuple()
+112 tuple("ref")
+113 tuple("ref")
+114 tuple("ref")
+115 tuple("ref")
+116 tuple()
+117 tuple("ref")
+118 tuple("ref")
+119 tuple()
+120 tuple("ref")
+121 tuple()
+122 tuple("ref")
+123 tuple("in")
+124 tuple("in")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("return", "ref")
+m-mixin tuple("return", "ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple()
+m-mixin tuple()
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("ref")
+m-mixin tuple("ref")
+m       tuple("in")
+m-mixin tuple("in")
+---
+*/
+
+void func(int i) {}
+void func(return ref bool i) {}
+void func(ref float a, int b) {}
+void get(T : int)(ref T t) {}
+void get()(float t) {}
+void get(T)(ref T[] t) {}
+void funcautoi()(auto ref int i) {}
+void funcauto(T)(auto ref T a) {}
+void funcin(in int i) {}
+
+struct Foo {
+       void foo(int i) {}
+       void foo(ref bool i) {}
+       static void sfoo(ref int i) {}
+}
+
+struct FooT(T) {
+       void foo(ref T i) {}
+       static void sfoo(ref T i) {}
+}
+
+class Bar {
+       void bar(int i) {}
+       void bar(ref bool i) {}
+       static void sbar(ref int i) {}
+}
+
+class BarT(T) {
+       void bar(ref T i) {}
+       static void sbar(ref T i) {}
+}
+
+int i;
+
+template match(handlers...)
+{
+       static foreach(h; handlers)
+       {
+               // should give the same result
+               pragma(msg, "m       ", __traits(getParameterStorageClasses, h(i), 0));
+               pragma(msg, "m-mixin ", __traits(getParameterStorageClasses, mixin("h(i)"), 0));
+       }
+
+       enum match = (){};
+}
+
+void funcT(T)(ref T t) {}
+
+void main() {
+       int i;
+       bool b;
+       float f;
+       int[] ia;
+       Foo foo;
+       FooT!int foot;
+       Bar bar = new Bar;
+       BarT!int bart = new BarT!int;
+
+       ref int _foo(return ref const int* p, scope int* a, out int b, lazy int c);
+
+       // From SPEC_RUNNABLE_EXAMPLE_COMPILE:
+       int* p, a;
+       int _b, c;
+
+       static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 1)[0] == "scope");
+       static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 2)[0] == "out");
+       static assert(__traits(getParameterStorageClasses, _foo(p, a, _b, c), 3)[0] == "lazy");
+
+#line 100
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(0), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(b), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(f, i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, func(f, i), 1));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(0.0), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(f), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, get(ia), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, mixin("get(i)"), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, Foo.sfoo(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, FooT!int.sfoo(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foo.foo(0), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foo.foo(b), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, foot.foo(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, Bar.sbar(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, BarT!int.sbar(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bar.bar(0), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bar.bar(b), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, bart.bar(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcautoi(10), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcautoi(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcauto(10), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcauto(i), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcin(1), 0));
+       pragma(msg, __LINE__, " ", __traits(getParameterStorageClasses, funcin(i), 0));
+
+       cast(void) match!(
+               function(ref int i) => true,
+               delegate(ref int i) => true,
+               (ref int i) => true,
+               (return ref int i) => &i,
+               get,
+               funcT,
+               (int i) => true,
+               FooT!int.sfoo,
+               Foo.sfoo,
+               BarT!int.sbar,
+               Bar.sbar,
+               funcautoi,
+               funcauto,
+               funcin,
+       );
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test15711.d b/gcc/testsuite/gdc.test/compilable/test15711.d
new file mode 100644 (file)
index 0000000..ba7a93d
--- /dev/null
@@ -0,0 +1,31 @@
+// https://issues.dlang.org/show_bug.cgi?id=15711
+
+struct Quu {
+    string val;
+}
+
+string[] result = foo!(0, [Quu(['z']), Quu("")]);
+
+template foo(size_t i, Quu[] data, string[] results = []) {
+    static if (i < data.length) {
+        enum def = data[i];
+        enum foo = foo!(i+1, data, results ~ def.val);
+    }
+    else {
+        enum foo = results;
+    }
+}
+
+// Run-time version already works
+
+string[] result_rt = foo_rt(0, [Quu(['z']), Quu("")]);
+
+string[] foo_rt(size_t i, Quu[] data, string[] results = []) {
+    if (i < data.length) {
+        auto def = data[i];
+        return foo_rt(i+1, data, results ~ def.val);
+    }
+    else {
+        return results;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test16492.d b/gcc/testsuite/gdc.test/compilable/test16492.d
deleted file mode 100644 (file)
index 833be1d..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// ARG_SETS: -debug; -o-; -debug -preview=dip1000
-// https://issues.dlang.org/show_bug.cgi?id=16492
-
-void mayCallGC();
-
-void test() @nogc pure
-{
-    debug new int(1);
-    debug
-    {
-        mayCallGC();
-        auto b = [1, 2, 3];
-        b ~= 4;
-    }
-}
-
-void debugSafe() @safe
-{
-    debug unsafeSystem();
-    debug unsafeTemplated();
-}
-
-void unsafeSystem() @system {}
-void unsafeTemplated()() {
-    int[] arr;
-    auto b = arr.ptr;
-}
-
-void debugSafe2() @safe
-{
-    char[] arr1, arr2;
-    debug unsafeDIP1000Lifetime(arr1, arr2);
-
-    char* ptr;
-    char[] arr;
-    debug ptr = arr.ptr;
-}
-
-void unsafeDIP1000Lifetime()(ref char[] p, scope char[] s)
-{
-    p = s;
-}
-
-
-void test2() nothrow
-{
-    debug throw new Exception("");
-}
-
-void test3() nothrow
-{
-    debug {
-        foreach (_; 0 .. 10) {
-            if (1) {
-                throw new Exception("");
-            }
-        }
-    }
-}
-
-void test4() nothrow
-{
-    debug throwException();
-}
-
-void test5() nothrow
-{
-    debug willThrowException();
-}
-
-void willThrowException()()
-{
-    throwException();
-}
-
-void throwException()
-{
-    throw new Exception("");
-}
-
-void test6() nothrow
-{
-    debug
-    {
-        () {throw new Exception("");}();
-    }
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test19482.d b/gcc/testsuite/gdc.test/compilable/test19482.d
new file mode 100644 (file)
index 0000000..09485a3
--- /dev/null
@@ -0,0 +1,68 @@
+// https://issues.dlang.org/show_bug.cgi?id=19482
+
+alias AliasSeq(T...) = T;
+
+extern (C++, "cppns")
+@("asd", 123)
+private
+deprecated
+immutable
+static foreach (i; 0 .. 1)
+{
+    static assert(is(typeof(i) == int));
+    static assert(__traits(getLinkage, i) == "D");
+    static assert(__traits(isDeprecated, i) == false);
+    static assert(__traits(getAttributes, i).length == 0);
+    static assert(__traits(getCppNamespaces, i).length == 0);
+    static assert(__traits(getVisibility, i) == "public");
+
+    extern int x;
+    static assert(is(typeof(x) == immutable int));
+    static assert(__traits(getLinkage, x) == "C++");
+    static assert(__traits(isDeprecated, x) == true);
+    static assert(__traits(getAttributes, x) == AliasSeq!("asd", 123));
+    static assert(__traits(getCppNamespaces, x) == AliasSeq!("cppns"));
+    static assert(__traits(getVisibility, x) == "private");
+}
+
+struct S
+{
+    @disable static foreach (j; 0 .. 1)
+    {
+        int y;
+        static assert(__traits(isDisabled, j) == false);
+        static assert(__traits(isDisabled, S.y) == true);
+    }
+}
+
+const
+static foreach (i, v; ['a'])
+{
+    static assert(is(typeof(i) == size_t));
+    static assert(is(typeof(v) == char));
+}
+
+const
+static foreach (i, s, f; Range())
+{
+    static assert(is(typeof(i) == int));
+    static assert(is(typeof(s) == string));
+    static assert(is(typeof(f) == float));
+}
+
+struct Range
+{
+    int i;
+    auto front()
+    {
+        return Tup!(int, string, float)(123, "asd", 3.14f);
+    }
+    bool empty() { return i > 0; }
+    void popFront() { ++i; }
+}
+
+struct Tup(T...)
+{
+    T fields;
+    alias fields this;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21438.d b/gcc/testsuite/gdc.test/compilable/test21438.d
new file mode 100644 (file)
index 0000000..02e2d8d
--- /dev/null
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=21438
+
+int genGBPLookup() {
+    static struct Table {
+        int[1] entries;
+    }
+
+    auto table = new Table;
+    auto x = table.entries[0];
+
+    static assert(is(typeof(x) == int));
+    return 0;
+}
+
+enum x = genGBPLookup;
diff --git a/gcc/testsuite/gdc.test/compilable/test21794.d b/gcc/testsuite/gdc.test/compilable/test21794.d
new file mode 100644 (file)
index 0000000..68e504b
--- /dev/null
@@ -0,0 +1,52 @@
+// https://issues.dlang.org/show_bug.cgi?id=21794
+/*
+TEST_OUTPUT:
+---
+0
+0u
+0L
+0LU
+0.0F
+0.0
+0.0L
+---
+*/
+
+bool fun(void* p) {
+    const x = cast(ulong)p;
+    return 1;
+}
+
+static assert(fun(null));
+
+T fun2(T)(void* p) {
+    const x = cast(T)p;
+    return x;
+}
+
+// These were an error before, they were returning a NullExp instead of IntegerExp/RealExp
+
+static assert(fun2!int(null)    == 0);
+static assert(fun2!uint(null)   == 0);
+static assert(fun2!long(null)   == 0);
+static assert(fun2!ulong(null)  == 0);
+static assert(fun2!float(null)  == 0);
+static assert(fun2!double(null) == 0);
+static assert(fun2!real(null)   == 0);
+
+// These were printing 'null' instead of the corresponding number
+
+const i = cast(int)null;
+const ui = cast(uint)null;
+const l = cast(long)null;
+const ul = cast(ulong)null;
+const f = cast(float)null;
+const d = cast(double)null;
+const r = cast(real)null;
+pragma(msg, i);
+pragma(msg, ui);
+pragma(msg, l);
+pragma(msg, ul);
+pragma(msg, f);
+pragma(msg, d);
+pragma(msg, r);
diff --git a/gcc/testsuite/gdc.test/compilable/test21850.d b/gcc/testsuite/gdc.test/compilable/test21850.d
new file mode 100644 (file)
index 0000000..e7fe2d4
--- /dev/null
@@ -0,0 +1,35 @@
+// https://issues.dlang.org/show_bug.cgi?id=21850
+
+struct Strukt2 {
+    this(int* _block) {  }
+}
+
+struct Strukt {
+    int* block;
+    Strukt2 foo() { return Strukt2(null); }
+    alias foo this;
+}
+
+bool wrapper(T)(ref T a, ref T b)
+{
+    return doesPointTo(a, b);
+}
+
+void johan() pure {
+    Strukt a;
+    Strukt b;
+    assert(wrapper(a, b));         // error wrapper is not pure
+    assert(doesPointTo(a, b));     // fine
+}
+
+bool doesPointTo(S, T)(S , T) {
+    return false;
+}
+
+bool doesPointTo(S)(shared S) {
+    return false;
+}
+
+bool mayPointTo(){
+    return false;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22214.d b/gcc/testsuite/gdc.test/compilable/test22214.d
new file mode 100644 (file)
index 0000000..d218125
--- /dev/null
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=22214
+
+struct S
+{
+    struct T
+    {
+    }
+}
+
+void main() {
+    const S s;
+    static if (__traits(compiles, { auto t = s.T; }))
+    {
+        auto t = s.T;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22224.d b/gcc/testsuite/gdc.test/compilable/test22224.d
new file mode 100644 (file)
index 0000000..d16b2f4
--- /dev/null
@@ -0,0 +1,4 @@
+// REQUIRED_ARGS: -profile -c
+
+import core.stdc.stdarg; 
+void error(...) { }
diff --git a/gcc/testsuite/gdc.test/compilable/test22228.d b/gcc/testsuite/gdc.test/compilable/test22228.d
new file mode 100644 (file)
index 0000000..ef31b4b
--- /dev/null
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=22228
+// Note: fixed by reverting pull #11545
+
+auto f()
+{   immutable int i;
+    auto p = (() => &i)();
+
+    return 0;
+}
+
+enum ctfeInvocation = f;
diff --git a/gcc/testsuite/gdc.test/compilable/test22292.d b/gcc/testsuite/gdc.test/compilable/test22292.d
new file mode 100644 (file)
index 0000000..945dffb
--- /dev/null
@@ -0,0 +1,155 @@
+// https://issues.dlang.org/show_bug.cgi?id=22292
+
+// Original case
+
+class C1
+{
+    C1 c1;
+    this () pure
+    {
+        c1 = this;
+    }
+}
+immutable x = cast(immutable)r;
+
+auto r()
+{
+    C1 c1 = new C1;
+    return c1;
+}
+
+// Reference stored in another class
+
+template Test2()
+{
+    class C1
+    {
+        C2 c2;
+        this () pure
+        {
+            C1 a = this;
+            c2 = new C2(a);
+        }
+    }
+    class C2
+    {
+        C1 c1;
+        this (C1 c) pure
+        {
+            c1 = c;
+        }
+    }
+    immutable x = cast(immutable)r;
+
+    auto r()
+    {
+        C1 c1 = new C1();
+        return c1;
+    }
+}
+
+alias test2 = Test2!();
+
+// Ditto but using a struct in the middle
+
+template Test3()
+{
+    class C0
+    {
+        S1 s1;
+
+        this()
+        {
+            s1 = S1(this);
+        }
+    }
+    struct S1
+    {
+        C1 c1;
+        this (C0 c)
+        {
+            c1 = new C1(c);
+        }
+    }
+    class C1
+    {
+        C0 c0;
+        this(C0 c)
+        {
+            c0 = c;
+        }
+    }
+    immutable x = cast(immutable)r;
+
+    auto r()
+    {
+        C0 c0 = new C0();
+        return c0;
+    }
+}
+
+alias test3 = Test3!();
+
+// From https://issues.dlang.org/show_bug.cgi?id=22114
+
+template Test4()
+{
+    public class Test1(T)
+    {
+        private Test2!T val;
+
+        this()
+        {
+            val = new Test2!T(this);
+        }
+
+        private class Test2(T)
+        {
+            private Test1!(T) m_source;
+
+            this(Test1!T source)
+            {
+                m_source = source;
+            }
+        }
+    }
+
+    public class Demo
+    {
+        auto val = new Test1!int();
+    }
+}
+
+alias test4 = Test4!();
+
+// ditto
+
+template Test5()
+{
+    public @nogc class TestA(T)
+    {
+        private TestB!T valA;
+        private TestB!T valB;
+        this()
+        {
+            valB = valA = new TestB!T(this);
+        }
+
+        private @nogc class TestB(T)
+        {
+            private TestA!(T) m_source;
+
+            this(TestA!T source)
+            {
+                m_source = source;
+            }
+        }
+    }
+
+    public class Demo
+    {
+        auto val = new TestA!int();
+    }
+}
+
+alias test5 = Test5!();
diff --git a/gcc/testsuite/gdc.test/compilable/test22388.d b/gcc/testsuite/gdc.test/compilable/test22388.d
new file mode 100644 (file)
index 0000000..cf8c3fc
--- /dev/null
@@ -0,0 +1,22 @@
+// https://issues.dlang.org/show_bug.cgi?id=22388
+
+void setTimer(void delegate()) @system;
+void setTimer(void delegate() @safe) @safe;
+
+void setTimer2(void delegate() @safe) @safe;
+void setTimer2(void delegate()) @system;
+
+void main() @safe
+{
+    setTimer(() => assert(false));
+
+    alias lambda = () => assert(false);
+    setTimer(lambda);
+
+    // Reversed order
+
+    setTimer2(() => assert(false));
+
+    alias lambda2 = () => assert(false);
+    setTimer2(lambda2);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22410.d b/gcc/testsuite/gdc.test/compilable/test22410.d
new file mode 100644 (file)
index 0000000..7e631b7
--- /dev/null
@@ -0,0 +1,59 @@
+// https://issues.dlang.org/show_bug.cgi?id=22410
+
+alias A(T...) = T;
+
+void fun0(const A!(int, string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(const int, const string)));
+}
+
+void fun1(const A!(immutable int, string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(immutable int, const string)));
+}
+
+void fun2(shared A!(int, string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(shared int, shared string)));
+}
+
+void fun3(shared const A!(int, string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(shared const int, shared const string)));
+}
+
+void fun4(inout A!(int, const string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(inout int, inout const string)));
+}
+
+void fun5(ref const A!(int, string) x = A!(1, "asdf"))
+{
+    static assert(is(typeof(x) == A!(const int, const string)));
+    static assert(__traits(isRef, x[0]) && __traits(isRef, x[1]));
+}
+
+// Implicitly conversion is also fixed, for example:
+// from (ulong, double) to (int, float)
+
+// Integral narrowing here, ulong(uint.max + 1UL) would fail.
+void fun10(A!(uint, float) x = A!(ulong(uint.max), 3.14))
+{
+    static assert(is(typeof(x) == A!(uint, float)));
+}
+
+void fun11(A!(int, double) x = A!(byte(1), 2.5f))
+{
+    static assert(is(typeof(x) == A!(int, double)));
+}
+
+void fun12(A!(byte, float) x = A!(1, 'a'))
+{
+    static assert(is(typeof(x) == A!(byte, float)));
+}
+
+A!(const int, shared char) tup = A!(1, 'a');
+void fun13(A!(byte, float) x = tup)
+{
+    static assert(is(typeof(x) == A!(byte, float)));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22420.d b/gcc/testsuite/gdc.test/compilable/test22420.d
new file mode 100644 (file)
index 0000000..c18d0a9
--- /dev/null
@@ -0,0 +1,88 @@
+// https://issues.dlang.org/show_bug.cgi?id=22420
+
+struct File
+{
+    ~this()
+    {
+    }
+    File impl()
+    {
+        return File.init;
+    }
+    alias impl this;
+}
+struct Variable
+{
+    this(File)(File) { }
+    this(File)(File[]) { }
+}
+Variable wrapFunctionReturn(alias handler)(Variable params)
+{
+    return Variable(handler(params));
+}
+void registerFile()
+{
+    wrapFunctionReturn!((Variable) {
+            return File.init;
+        })(Variable.init);
+}
+
+// Reduction from an 'automem' test
+
+struct Issue156 {}
+
+void test2()
+{
+    RefCounted!Issue156 s;
+    auto r1 = repeat(s);
+    zip(r1);
+}
+
+struct RefCounted(RefCountedType)
+{
+    ~this() {}
+    alias _impl this;
+
+    struct Impl {}
+    alias ImplType = Impl;
+
+    private ImplType* _impl;
+
+}
+template Tuple(Specs)
+{
+    struct Tuple
+    {
+        this(U)(U) {}
+        this()(int) {}
+    }
+}
+
+template ElementType(R)
+{
+    static if (is(typeof(R.init) T))
+        alias ElementType = T;
+}
+
+struct Repeat(T)
+{
+    inout(T) front() inout {assert(0);}
+}
+
+Repeat!T repeat(T)(T ) {assert(0);}
+
+auto zip(Ranges)(Ranges )
+{
+    return ZipShortest!Ranges();
+}
+
+struct ZipShortest(Ranges...)
+{
+    Ranges ranges;
+    alias ElementType = Tuple!(.ElementType!(Ranges[0]));
+
+    ElementType front()
+    {
+        return typeof(return)(ranges[0].front);
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22421.d b/gcc/testsuite/gdc.test/compilable/test22421.d
new file mode 100644 (file)
index 0000000..902646d
--- /dev/null
@@ -0,0 +1,19 @@
+// https://issues.dlang.org/show_bug.cgi?id=22421
+
+alias AliasSeq(T...) = T;
+
+template staticMap(alias fun, args...)
+{
+    alias staticMap = AliasSeq!();
+    static foreach(arg; args)
+        staticMap = AliasSeq!(staticMap, fun!arg);
+}
+
+template id(alias what)
+{
+    enum id = __traits(identifier, what);
+}
+
+enum A { a }
+
+static assert(staticMap!(id, A.a) == AliasSeq!("a"));
diff --git a/gcc/testsuite/gdc.test/compilable/test318.d b/gcc/testsuite/gdc.test/compilable/test318.d
new file mode 100644 (file)
index 0000000..fd3cabe
--- /dev/null
@@ -0,0 +1,19 @@
+// LINK:
+// PERMUTE_ARGS: -version=C_Main
+
+version (C_Main)
+{
+    // Fine, infers int
+    extern(C) auto main(int argc, const char** argv)
+    {
+        return argc;
+    }
+}
+else
+{
+    // Fine, infers void
+    auto main()
+    {
+
+    }
+}
index 8f8f7c9f26d86cdf655220206854953c4d08dffc..0e785cf21c969dfbcc61f0aca932321214faedf9 100644 (file)
@@ -12,9 +12,6 @@ void test4090a()
         // inference + qualifier + ref
         foreach (          ref x; arr) static assert(is(typeof(x) == int));
         foreach (    const ref x; arr) static assert(is(typeof(x) == const int));
-      static assert(!__traits(compiles, {
-        foreach (immutable ref x; arr) {}
-      }));
 
         // with exact type + qualifier
         foreach (          int x; arr) static assert(is(typeof(x) == int));
@@ -24,25 +21,11 @@ void test4090a()
         // with exact type + qualifier + ref
         foreach (          ref int x; arr) static assert(is(typeof(x) == int));
         foreach (    const ref int x; arr) static assert(is(typeof(x) == const int));
-      static assert(!__traits(compiles, {
-        foreach (immutable ref int x; arr) {}
-      }));
 
         // convertible type + qualifier
         foreach (          double x; arr) static assert(is(typeof(x) == double));
         foreach (    const double x; arr) static assert(is(typeof(x) == const double));
         foreach (immutable double x; arr) static assert(is(typeof(x) == immutable double));
-
-        // convertible type + qualifier + ref
-      static assert(!__traits(compiles, {
-        foreach (          ref double x; arr) {}
-      }));
-      static assert(!__traits(compiles, {
-        foreach (    const ref double x; arr) {}
-      }));
-      static assert(!__traits(compiles, {
-        foreach (immutable ref double x; arr) {}
-      }));
     }
     // for the immutable elements
     {
index 3cfc22f0464c50b88fc1004352c882e2e0272c88..aaceb7d95e144989b06451c57b3bcdca33201b03 100644 (file)
@@ -69,9 +69,9 @@ static assert(U9766.var4.offsetof == 40);
 
 struct TestMaxAlign
 {
-align(1u << 31):
+align(1u << 15):
     ubyte a;
     ubyte b;
 }
 
-static assert(TestMaxAlign.b.offsetof == 2147483648u);
+static assert(TestMaxAlign.b.offsetof == (1 << 15));
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff3.d b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
deleted file mode 100644 (file)
index 89228a9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-// EXTRA_FILES: imports/cstuff3.c
-import imports.cstuff3;
-
-static assert(squared(4) == 16);
diff --git a/gcc/testsuite/gdc.test/compilable/transition_in.d b/gcc/testsuite/gdc.test/compilable/transition_in.d
new file mode 100644 (file)
index 0000000..cc492a7
--- /dev/null
@@ -0,0 +1,26 @@
+// REQUIRED_ARGS: -transition=in
+/*
+TRANSFORM_OUTPUT: remove_lines(druntime)
+TEST_OUTPUT:
+---
+compilable/transition_in.d(3): Usage of 'in' on parameter
+compilable/transition_in.d(3): Usage of 'in' on parameter
+compilable/transition_in.d(8): Usage of 'in' on parameter
+compilable/transition_in.d(13): Usage of 'in' on parameter
+---
+*/
+#line 1
+struct Foobar
+{
+    void bar (in int a, in Object c);
+}
+
+version (none)
+{
+    void barfoo (in string arg);
+}
+
+void main ()
+{
+    void nested (in char c) {}
+}
index 3c0062ead30302ec3a4457d3685a6a1b9a777c66..6e26deb5490c7695ceca37ab1e622d98ccd69b69 100644 (file)
@@ -1,12 +1,17 @@
 
 extern (C) struct S { }
 
-static assert(S.sizeof == 0);
-static assert(S.alignof == 1);
+version (CRuntime_Microsoft)
+    static assert(S.sizeof == 4);
+else
+    static assert(S.sizeof == 0);
+
+version (CRuntime_DigitalMars)
+    static assert(S.alignof == 0);
+else
+    static assert(S.alignof == 1);
 
 extern (C++) struct T { }
 
 static assert(T.sizeof == 1);
 static assert(T.alignof == 1);
-
-
index 38f9ccbe12b8e8facd55f303bd206796b8da640b..1366882edeb88055fee00731fc254e76f8a410c7 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag10327.d(11): Error: module `test10327` is in file 'imports/test10327.d' which cannot be read
+fail_compilation/diag10327.d(12): Error: unable to read module `test10327`
+fail_compilation/diag10327.d(12):        Expected 'imports/test10327.d' or 'imports/test10327/package.d' in one of the following import paths:
 import path[0] = fail_compilation
 import path[1] = $p:druntime/import$
 import path[2] = $p:phobos$
index a7a5914cfcef99a66029d46fcaa2ed6603abb5c4..2c8063a243011b95b460963689a4bf62b26ae507 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag20059.d(15): Error: Expected return type of `string`, not `string[]`:
+fail_compilation/diag20059.d(15): Error: expected return type of `string`, not `string[]`:
 fail_compilation/diag20059.d(13):        Return type of `string` inferred here.
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20618.d b/gcc/testsuite/gdc.test/fail_compilation/fail20618.d
new file mode 100644 (file)
index 0000000..ac6b33a
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail20618.d(13): Error: in slice `a[1 .. 12]`, upper bound is greater than array length `10`
+fail_compilation/fail20618.d(14): Error: in slice `a[4 .. 3]`, lower bound is greater than upper bound
+fail_compilation/fail20618.d(15): Error: in slice `a[0 .. 11]`, upper bound is greater than array length `10`
+---
+*/
+
+void main()
+{
+    int[10] a;
+    auto b = a[1..12];
+    auto c = a[4..3];
+    auto d = a[0..$ + 1];
+}
index 74f40c2eeb53c1e8641675178155fad0ed856ba9..c2bbe4d59e4d99b25d779621297a206d0494fcbd 100644 (file)
@@ -3,7 +3,8 @@
 /*
 TEST_OUTPUT:
 ----
-fail_compilation/fail21091a.d(15): Error: module `Ternary` is in file 'Ternary.d' which cannot be read
+fail_compilation/fail21091a.d(16): Error: unable to read module `Ternary`
+fail_compilation/fail21091a.d(16):        Expected 'Ternary.d' or 'Ternary/package.d' in one of the following import paths:
 import path[0] = fail_compilation
 import path[1] = $p:druntime/import$
 import path[2] = $p:phobos$
index d9467aafdb3363551f96d396f67431af10f017a6..3d7d6001bd2a9fbc04844224d419676f43089b16 100644 (file)
@@ -3,7 +3,8 @@
 /*
 TEST_OUTPUT:
 ----
-fail_compilation/fail21091b.d(15): Error: module `Tid` is in file 'Tid.d' which cannot be read
+fail_compilation/fail21091b.d(16): Error: unable to read module `Tid`
+fail_compilation/fail21091b.d(16):        Expected 'Tid.d' or 'Tid/package.d' in one of the following import paths:
 import path[0] = fail_compilation
 import path[1] = $p:druntime/import$
 import path[2] = $p:phobos$
index 02fff2f6cc680e3659432f6aa7a7befcf2f7a7c2..bd11832adebb54fc51dcc3e88a935d0efd2bf899 100644 (file)
@@ -18,6 +18,6 @@ struct Destructor
 
 void test()
 {
-    auto a0 = Destructor;
+    auto a0 = Destructor();
     testVariadic(1, a0);
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22151.d b/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
new file mode 100644 (file)
index 0000000..c6c3b1b
--- /dev/null
@@ -0,0 +1,24 @@
+// https://issues.dlang.org/show_bug.cgi?id=22151
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22151.d(14): Error: function `test` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(15): Error: function `test2` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(18): Error: function pointed to by `fp` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(21): Error: function pointed to by `ff` is not an lvalue and cannot be modified
+---
+*/
+
+void test()
+{
+    *&test = *&test;
+    *&test2 = *&test;
+
+    void function() fp;
+    *fp = *fp;
+
+    auto ff = &test2;
+    *ff = *&test2;
+}
+
+void test2();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22366.d b/gcc/testsuite/gdc.test/fail_compilation/fail22366.d
new file mode 100644 (file)
index 0000000..3a2469f
--- /dev/null
@@ -0,0 +1,15 @@
+// REQUIRED_ARGS: -dip1000
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22366.d(13): Error: scope variable `__aaval2` assigned to non-scope `aa[0]`
+---
+*/
+
+int* fun(scope int* x) @safe
+{
+    int*[int] aa;
+    aa[0] = x; // should give an error
+    return aa[0];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail225.d b/gcc/testsuite/gdc.test/fail_compilation/fail225.d
deleted file mode 100644 (file)
index dee9a54..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail225.d(15): Error: cannot implicitly convert expression `1` of type `int` to `immutable(char*)`
-fail_compilation/fail225.d(15): Error: cannot implicitly convert expression `& ch` of type `char*` to `immutable(char*)`
----
-*/
-struct Struct { 
-        char* chptr; 
-}
-
-void main()
-{
-        char ch = 'd';
-        immutable Struct iStruct = {1, &ch};
-}
-
index 7ed8f134c97356fb40c5933bb46e47481e79a17b..e5b1a79bb048e73e3bad08059852d2d1f9c7ee28 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail287.d(14): Error: had 299 cases which is more than 256 cases in case range
+fail_compilation/fail287.d(14): Error: had 300 cases which is more than 257 cases in case range
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail318.d b/gcc/testsuite/gdc.test/fail_compilation/fail318.d
deleted file mode 100644 (file)
index d99175e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail318.d(8): Error: function `D main` must return `int` or `void`
----
-*/
-
-auto main() { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail318_b.d b/gcc/testsuite/gdc.test/fail_compilation/fail318_b.d
new file mode 100644 (file)
index 0000000..efbf45b
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail318_b.d(8): Error: function `D main` must return `int`, `void` or `noreturn`, not `string`
+---
+*/
+
+auto main()
+{
+    return "";
+}
index 2a2e46bb9f02ffb44d7d5e11cf11d0e3aaaa182b..05ba7f9fc0a4da496a05482addacfc24e80853bb 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7173.d(23): Error: cannot implicitly convert expression `b1._a.opBinary(b2._a).fun()` of type `void` to `B`
+fail_compilation/fail7173.d(23): Error: expression `b1._a.opBinary(b2._a).fun()` is `void` and has no value
 ---
 */
 struct A{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/foreach.d b/gcc/testsuite/gdc.test/fail_compilation/foreach.d
new file mode 100644 (file)
index 0000000..9a1c7c8
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/foreach.d(12): Error: cannot declare `out` loop variable, use `ref` instead
+fail_compilation/foreach.d(13): Error: cannot declare `out` loop variable, use `ref` instead
+fail_compilation/foreach.d(13): Error: cannot declare `out` loop variable, use `ref` instead
+---
+*/
+void main ()
+{
+    int[] array;
+    foreach (out val; array) {}
+    foreach (out idx, out val; array) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/foreach2.d b/gcc/testsuite/gdc.test/fail_compilation/foreach2.d
new file mode 100644 (file)
index 0000000..8bd4893
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/foreach2.d(15): Error: argument type mismatch, `int` to `ref immutable(int)`
+fail_compilation/foreach2.d(16): Error: argument type mismatch, `int` to `ref immutable(int)`
+fail_compilation/foreach2.d(19): Error: argument type mismatch, `int` to `ref double`
+fail_compilation/foreach2.d(20): Error: argument type mismatch, `int` to `ref const(double)`
+fail_compilation/foreach2.d(21): Error: argument type mismatch, `int` to `ref immutable(double)`
+---
+*/
+void test4090 ()
+{
+    // From https://issues.dlang.org/show_bug.cgi?id=4090
+    int[] arr = [1,2,3];
+    foreach (immutable ref x; arr) {}
+    foreach (immutable ref int x; arr) {}
+
+    // convertible type + qualifier + ref
+    foreach (          ref double x; arr) {}
+    foreach (    const ref double x; arr) {}
+    foreach (immutable ref double x; arr) {}
+}
index b9fe2aa6557b421c5a0d5c5548f810975adfcf80..99fe1edf3e0e5e50bb6a205cfd27a38bf4c9e0c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10212.d(13): Error: Expected return type of `int`, not `int function() pure nothrow @nogc @safe`:
+fail_compilation/ice10212.d(13): Error: expected return type of `int`, not `int function() pure nothrow @nogc @safe`:
 fail_compilation/ice10212.d(13):        Return type of `int` inferred here.
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice22377.d b/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
new file mode 100644 (file)
index 0000000..4616f99
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice22377.d(8): Error: Internal Compiler Error: type `string` cannot be mapped to C++
+---
+*/
+
+extern(C++) void foo(string a) {}
index d42011a0dd06b4b3c11ab0862ced6af079f3e9d8..551933b382d242405cda3f5aefa7b04c17b6ec02 100644 (file)
@@ -2,7 +2,8 @@
 EXTRA_FILES: imports/ice7782algorithm.d imports/ice7782range.d
 TEST_OUTPUT:
 ----
-fail_compilation/ice7782.d(13): Error: module `ice7782math` is in file 'imports/ice7782range/imports/ice7782math.d' which cannot be read
+fail_compilation/ice7782.d(14): Error: unable to read module `ice7782math`
+fail_compilation/ice7782.d(14):        Expected 'imports/ice7782range/imports/ice7782math.d' or 'imports/ice7782range/imports/ice7782math/package.d' in one of the following import paths:
 import path[0] = fail_compilation
 import path[1] = $p:druntime/import$
 import path[2] = $p:phobos$
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d b/gcc/testsuite/gdc.test/fail_compilation/imports/imp22329.d
new file mode 100644 (file)
index 0000000..9dc3c8e
--- /dev/null
@@ -0,0 +1,4 @@
+void func(T)(T arg)
+{
+    auto a = arg + 1;
+}
index 3b340e84c4dbb8690d56fd149a94712df6263715..4a588b4c00d2e8660a18fa3b4a0817810537deff 100644 (file)
@@ -72,7 +72,7 @@ noreturn casting(int i)
             return cast() n;
         }
     }
-
+    assert(false);
 }
 
 enum forceCasting0 = casting(0);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
new file mode 100644 (file)
index 0000000..e7d28dc
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+REQUIRED_ARGS: -w -o-
+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(18): Error: expected return type of `noreturn`, not `void`
+---
+
+https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md
+*/
+
+alias noreturn = typeof(*null);
+
+void doStuff();
+
+noreturn returnVoid()
+{
+    return doStuff();
+}
+
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(37): Error: expected return type of `int`, not `string`:
+fail_compilation/noreturn2.d(35):        Return type of `int` inferred here.
+---
++/
+
+auto missmatch(int i)
+{
+    if (i < 0)
+        return assert(false);
+    if (i == 0)
+        return i;
+    if (i > 0)
+        return "";
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(50): Error: function `noreturn2.returns` is typed as `NR` but does return
+fail_compilation/noreturn2.d(50):        `noreturn` functions must either throw, abort or loop indefinitely
+---
++/
+
+enum NR : noreturn;
+
+NR returns()
+{
+    // Fallthrough despite noreturn
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(64): Error: cannot implicitly convert expression `1` of type `int` to `noreturn`
+---
++/
+
+noreturn returnsValue()
+{
+    return 1;
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(75): Error: expected return type of `int`, not `void`
+---
++/
+int returnVoid2()
+{
+    return doStuff();
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(89): Error: mismatched function return type inference of `void` and `int`
+---
++/
+auto returnVoid3(int i)
+{
+    if (i > 0)
+        return i;
+    else
+        return doStuff();
+}
index 034fa541234ffb8e2479cb58419d792c5d9471a0..43998b9f47cb2a35d03a7e2b3c1efbe052b078a0 100644 (file)
@@ -113,6 +113,8 @@ fail_compilation/reserved_version.d(214): Error: version identifier `CppRuntime_
 fail_compilation/reserved_version.d(215): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
 fail_compilation/reserved_version.d(216): Error: version identifier `D_PIE` is reserved and cannot be set
 fail_compilation/reserved_version.d(217): Error: version identifier `AVR` is reserved and cannot be set
+fail_compilation/reserved_version.d(218): Error: version identifier `D_PreConditions` is reserved and cannot be set
+fail_compilation/reserved_version.d(219): Error: version identifier `D_PostConditions` is reserved and cannot be set
 ---
 */
 
@@ -232,6 +234,8 @@ version = CppRuntime_Microsoft;
 version = CppRuntime_Sun;
 version = D_PIE;
 version = AVR;
+version = D_PreConditions;
+version = D_PostConditions;
 
 // This should work though
 debug = DigitalMars;
@@ -340,3 +344,5 @@ debug = none;
 debug = D_P16;
 debug = MSP430;
 debug = AVR;
+debug = D_PreConditions;
+debug = D_PostConditions;
index b8b6fa4d8e8528594f6387fb34536806f2699cee..633330908c8e6394902886c3d6371c8be5d96695 100644 (file)
 // REQUIRED_ARGS: -version=assert
 // REQUIRED_ARGS: -version=all
 // REQUIRED_ARGS: -version=none
+// REQUIRED_ARGS: -version=D_PreConditions
+// REQUIRED_ARGS: -version=D_PostConditions
 // REQUIRED_ARGS: -debug=DigitalMars
 // REQUIRED_ARGS: -debug=GNU
 // REQUIRED_ARGS: -debug=LDC
 // REQUIRED_ARGS: -debug=assert
 // REQUIRED_ARGS: -debug=all
 // REQUIRED_ARGS: -debug=none
+// REQUIRED_ARGS: -debug=D_PreConditions
+// REQUIRED_ARGS: -debug=D_PostConditions
 /*
 TEST_OUTPUT:
 ---
@@ -309,5 +313,7 @@ Error: version identifier `unittest` is reserved and cannot be set
 Error: version identifier `assert` is reserved and cannot be set
 Error: version identifier `all` is reserved and cannot be set
 Error: version identifier `none` is reserved and cannot be set
+Error: version identifier `D_PreConditions` is reserved and cannot be set
+Error: version identifier `D_PostConditions` is reserved and cannot be set
 ---
 */
index f7628b83e22ba1cc8b98afb16570e5e4e5850b24..77c49567e47e9ed244cce81f7741954da54a834e 100644 (file)
@@ -1,7 +1,7 @@
 /* TEST_OUTPUT:
 ---
 fail_compilation/test17425.d(24): Error: parameter index must be in range 0..4 not 4
-fail_compilation/test17425.d(27): Error: first argument to `__traits(getParameterStorageClasses, i, 4)` is not a function
+fail_compilation/test17425.d(27): Error: first argument to `__traits(getParameterStorageClasses, i, 4)` is not a function or a function call
 fail_compilation/test17425.d(29): Error: expression expected as second argument of `__traits(getParameterStorageClasses, foo, int)`
 fail_compilation/test17425.d(31): Error: expected 2 arguments for `getParameterStorageClasses` but had 3
 ---
index 5bfff5cf50a6cb8ff5b752228ad297860fe0e6e3..7833b61a9495da8ed110ea7edf37a5a732d218ee 100644 (file)
@@ -1,9 +1,9 @@
 /*
 TEST_OUTPUT:
 ----
+fail_compilation/test17868b.d(9): Error: pragma `crt_constructor` can only apply to a single declaration
 fail_compilation/test17868b.d(10): Error: function `test17868b.foo` must be `extern(C)` for `pragma(crt_constructor)`
 fail_compilation/test17868b.d(14): Error: function `test17868b.bar` must be `extern(C)` for `pragma(crt_constructor)`
-fail_compilation/test17868b.d(9): Error: pragma `crt_constructor` can only apply to a single declaration
 ----
  */
 pragma(crt_constructor):
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20998.d b/gcc/testsuite/gdc.test/fail_compilation/test20998.d
new file mode 100644 (file)
index 0000000..16eb026
--- /dev/null
@@ -0,0 +1,120 @@
+// https://issues.dlang.org/show_bug.cgi?id=20998
+/*
+REQUIRED_ARGS: -verrors=context
+TEST_OUTPUT:
+---
+fail_compilation/test20998.d(76): Error: undefined identifier `invalid`
+X x = { invalid, 2, "asd" };
+        ^
+fail_compilation/test20998.d(76): Error: too many initializers for `X`
+X x = { invalid, 2, "asd" };
+                    ^
+fail_compilation/test20998.d(83): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+                     ^
+fail_compilation/test20998.d(83): Error: duplicate initializer for field `ptr`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+                               ^
+fail_compilation/test20998.d(83): Error: too many initializers for `X2`
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+                                  ^
+fail_compilation/test20998.d(90): Error: overlapping initialization for field `ptr` and `x`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+               ^
+fail_compilation/test20998.d(90): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+                     ^
+fail_compilation/test20998.d(90): Error: duplicate initializer for field `ptr`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+                               ^
+fail_compilation/test20998.d(90): Error: too many initializers for `X3`
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+                                  ^
+fail_compilation/test20998.d(98): Error: field `X4.ptr` cannot assign to misaligned pointers in `@safe` code
+    X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+                   ^
+fail_compilation/test20998.d(98): Error: cannot implicitly convert expression `"a"` of type `string` to `int`
+    X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+                         ^
+fail_compilation/test20998.d(98): Error: too many initializers for `X4`
+    X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+                              ^
+fail_compilation/test20998.d(102):        called from here: `test()`
+auto e = test();
+             ^
+fail_compilation/test20998.d(104): Error: cannot implicitly convert expression `1` of type `int` to `void*`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+               ^
+fail_compilation/test20998.d(104): Error: duplicate initializer for field `ptr`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+                       ^
+fail_compilation/test20998.d(104): Error: duplicate initializer for field `ptr`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+                               ^
+fail_compilation/test20998.d(104): Error: too many initializers for `X2`
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+                                         ^
+fail_compilation/test20998.d(107): Error: too many initializers for `X2`
+X2 c6 = { null, 2, true, null };
+                         ^
+fail_compilation/test20998.d(116): Error: cannot implicitly convert expression `1` of type `int` to `immutable(char*)`
+    immutable Struct iStruct = {1, &ch};
+                                ^
+fail_compilation/test20998.d(116): Error: too many initializers for `Struct`
+    immutable Struct iStruct = {1, &ch};
+                                   ^
+fail_compilation/test20998.d(120):        called from here: `test2()`
+auto t = test2();
+              ^
+---
+*/
+
+struct X {
+       void* ptr;
+       int x;
+}
+X x = { invalid, 2, "asd" };
+
+struct X2 {
+       void* ptr;
+       int x;
+       bool y;
+}
+X2 x2 = { ptr: null, "a", ptr: 2, 444 };
+
+union X3 {
+    void* ptr;
+    int x;
+    bool y;
+}
+X3 x3 = { ptr: null, "a", ptr: 2, 444 };
+
+int test() @safe
+{
+    align (1) struct X4 {
+        void* ptr;
+        int x;
+    }
+    X4 x4 = { ptr: null, "a", 444, ptr: 2, true };
+    return 0;
+}
+
+auto e = test();
+
+X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 };
+X2 b5 = { ptr: null, y: true };
+X2 c5 = { x: 2, true, ptr: null };
+X2 c6 = { null, 2, true, null };
+
+struct Struct {
+        char* chptr;
+}
+
+int test2()
+{
+    char ch = 'd';
+    immutable Struct iStruct = {1, &ch};
+    return 0;
+}
+
+auto t = test2();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21093.d b/gcc/testsuite/gdc.test/fail_compilation/test21093.d
new file mode 100644 (file)
index 0000000..b85d0c3
--- /dev/null
@@ -0,0 +1,56 @@
+// https://issues.dlang.org/show_bug.cgi?id=21093
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21093.d(24): Error: function `test21093.LocalTime.hasDST` does not override any function
+fail_compilation/test21093.d(32): Error: class `test21093.LocalTime2` cannot implicitly generate a default constructor when base class `test21093.TimeZone2` is missing a default constructor
+fail_compilation/test21093.d(44): Error: function `test21093.LocalTime3.string` does not override any function
+fail_compilation/test21093.d(55): Error: cannot implicitly override base class method `test21093.TimeZone4.hasDST` with `test21093.LocalTime4.hasDST`; add `override` attribute
+---
+*/
+
+void fromUnixTime(immutable TimeZone tz = LocalTime()) { }
+void fromUnixTime(immutable TimeZone2 tz = LocalTime2()) { }
+void fromUnixTime(immutable TimeZone3 tz = LocalTime3()) { }
+void fromUnixTime(immutable TimeZone4 tz = LocalTime4()) { }
+
+class TimeZone
+{
+}
+
+class LocalTime : TimeZone
+{
+    static immutable(LocalTime) opCall() { }
+    override hasDST() { }
+}
+
+class TimeZone2
+{
+    this(string) { }
+}
+
+class LocalTime2 : TimeZone2
+{
+    static immutable(LocalTime2) opCall() { }
+}
+
+class TimeZone3
+{
+}
+
+class LocalTime3 : TimeZone3
+{
+    static immutable(LocalTime3) opCall() { }
+    override string () { }
+}
+
+class TimeZone4
+{
+    bool hasDST();
+}
+
+class LocalTime4 : TimeZone4
+{
+    static immutable(LocalTime4) opCall() { }
+    bool hasDST() { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21380.d b/gcc/testsuite/gdc.test/fail_compilation/test21380.d
new file mode 100644 (file)
index 0000000..6a2da1b
--- /dev/null
@@ -0,0 +1,46 @@
+// https://issues.dlang.org/show_bug.cgi?id=21380
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21380.d(39): Error: partial template instance `MySerializer().serializeSinkType!int` has no value
+fail_compilation/test21380.d(44): Error: template instance `test21380.SupportSinkTypeSer!(MySerializer!int)` error instantiating
+---
+*/
+
+template isSomeFunction(T...)
+if (T.length == 1)
+{
+    static if (is(typeof(& T[0]) U : U*) && is(U == function) || is(typeof(& T[0]) U == delegate))
+    {
+        // T is a (nested) function symbol.
+        enum bool isSomeFunction = true;
+    }
+    else static if (is(T[0] W) || is(typeof(T[0]) W))
+    {
+        // T is an expression or a type.  Take the type of it and examine.
+        static if (is(W F : F*) && is(F == function))
+            enum bool isSomeFunction = true; // function pointer
+        else
+            enum bool isSomeFunction = is(W == function) || is(W == delegate);
+    }
+    else
+        enum bool isSomeFunction = false;
+}
+
+struct MySerializer (T)
+{
+       void serializeSinkType(T2) (scope auto ref T2 record) {}
+}
+
+template SupportSinkTypeSer(SerT)
+{
+    /* Note: Partial template instance because it needs inference, in this case
+       it cannot infer 'auto ref' parameter */
+       enum SupportSinkTypeSer = isSomeFunction!(SerT.init.serializeSinkType!int);
+}
+
+int main()
+{
+       enum x = SupportSinkTypeSer!(MySerializer!int);
+       return 0;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21930.d b/gcc/testsuite/gdc.test/fail_compilation/test21930.d
new file mode 100644 (file)
index 0000000..6c93243
--- /dev/null
@@ -0,0 +1,27 @@
+// https://issues.dlang.org/show_bug.cgi?id=21930
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21930.d(21): Error: variable `string` is used as a type
+fail_compilation/test21930.d(15):        variable `string` is declared here
+fail_compilation/test21930.d(26): Error: constructor `test21930.R.this(string)` is not callable using argument types `()`
+---
+*/
+
+alias AliasSeq(T...) = T;
+
+alias TP(alias name) = AliasSeq!name;
+
+int string; // 'string' declared as a variable
+
+alias a = TP!(main);
+
+class R
+{
+    this(string) { } // so constructor have errors
+}
+
+@system main()
+{
+    new R;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22329.d b/gcc/testsuite/gdc.test/fail_compilation/test22329.d
new file mode 100644 (file)
index 0000000..237f9c7
--- /dev/null
@@ -0,0 +1,21 @@
+// https://issues.dlang.org/show_bug.cgi?id=22329
+// EXTRA_FILES: imports/imp22329.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo`
+fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int`
+fail_compilation/test22329.d(20): Error: template instance `imp22329.func!(Foo)` error instantiating
+---
+*/
+
+public struct Foo {
+    private int values;
+    alias values this;
+}
+
+void main()
+{
+    import imports.imp22329 : func;
+    func(Foo());
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22361.d b/gcc/testsuite/gdc.test/fail_compilation/test22361.d
new file mode 100644 (file)
index 0000000..11255ff
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test22361.d(11): Error: unable to read module `this_module_does_not_exist`
+fail_compilation/test22361.d(11):        Expected 'this_module_does_not_exist.d' or 'this_module_does_not_exist/package.d' in one of the following import paths:
+import path[0] = fail_compilation
+import path[1] = $p:druntime/import$
+import path[2] = $p:phobos$
+---
+*/
+import this_module_does_not_exist;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
new file mode 100644 (file)
index 0000000..9203685
--- /dev/null
@@ -0,0 +1,161 @@
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(27): Error: `testOpApply.SameAttr.opApply` called with argument types `(int delegate(int i) pure nothrow @nogc @safe)` matches both:
+fail_compilation/testOpApply.d(13):     `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+and:
+fail_compilation/testOpApply.d(18):     `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+---
++/
+
+struct SameAttr
+{
+    int opApply(int delegate(int) @system dg) @system
+    {
+        return 0;
+    }
+
+    int opApply(int delegate(int) @system dg) @safe
+    {
+        return 0;
+    }
+}
+
+void testSameAttr() @safe
+{
+    SameAttr sa;
+    foreach (int i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(104): Error: `testOpApply.SameAttr.opApply` called with argument types `(int delegate(int i) pure nothrow @nogc @system)` matches both:
+fail_compilation/testOpApply.d(13):     `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+and:
+fail_compilation/testOpApply.d(18):     `testOpApply.SameAttr.opApply(int delegate(int) @system dg)`
+---
++/
+#line 100
+
+void testSameAttr() @system
+{
+    SameAttr sa;
+    foreach (int i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(217): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(203)`:     `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(208)`:     `int(int delegate(string) dg)`
+fail_compilation/testOpApply.d(217): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 200
+
+struct DifferentTypes
+{
+    int opApply(int delegate(int) dg)
+    {
+        return 0;
+    }
+
+    int opApply(int delegate(string) dg)
+    {
+        return 0;
+    }
+}
+
+void testDifferentTypes()
+{
+    DifferentTypes sa;
+    foreach (i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(317): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(303)`:     `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(308)`:     `int(int delegate(long) dg)`
+fail_compilation/testOpApply.d(317): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 300
+
+struct CovariantTypes
+{
+    int opApply(int delegate(int) dg)
+    {
+        return 0;
+    }
+
+    int opApply(int delegate(long) dg)
+    {
+        return 0;
+    }
+}
+
+void testCovariantTypes()
+{
+    CovariantTypes sa;
+    foreach (i; sa) {}
+}
+
+/+
+See https://issues.dlang.org/show_bug.cgi?id=21683
+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(420): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(404)`:     `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(410)`:     `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(420): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 400
+
+struct DifferentQualifiers
+{
+    int x;
+    int opApply(int delegate(int) dg)
+    {
+        x = 1;
+        return 0;
+    }
+
+    int opApply(int delegate(ref int) dg)
+    {
+        x = 2;
+        return 0;
+    }
+}
+
+void testDifferentQualifiers()
+{
+    DifferentQualifiers sa;
+    foreach (i; sa) {}
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/testOpApply.d(504): Error: `sa.opApply` matches more than one declaration:
+`fail_compilation/testOpApply.d(404)`:     `int(int delegate(int) dg)`
+and:
+`fail_compilation/testOpApply.d(410)`:     `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(504): Error: cannot uniquely infer `foreach` argument types
+---
++/
+#line 500
+
+void testDifferentQualifiersRef()
+{
+    DifferentQualifiers sa;
+    foreach (ref i; sa) {}
+}
index cc12f55935d84cd80ee3e2881fa347b8100b83d1..db5913c83899897719a5e124ae2925ae06abb428 100644 (file)
@@ -2102,6 +2102,42 @@ void test16633()
     root.populate;
 }
 
+/***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=13009
+
+struct RefCounted13009_2(T)
+{
+    ref T refCountedPayload()
+    {
+        assert(false);
+    }
+
+    ref inout(T) refCountedPayload() inout
+    {
+        assert(false);
+    }
+
+    alias refCountedPayload this;
+}
+
+struct S13009_2
+{
+    struct Payload
+    {
+        int[] data;
+    }
+
+    RefCounted13009_2!Payload payload;
+    alias X = typeof(payload.data[0]);
+
+    void foo()
+    {
+        payload.data[0] = 0;
+    }
+}
+
+/***************************************************/
+
 int main()
 {
     test1();
index f772d6160ad1ad7f9ffe1d29a96a991a24f2b117..1eb463ce8cc1138d4aff05d07ec01604091dca30 100644 (file)
@@ -929,3 +929,19 @@ version (NetBSD)
      return q;
     }
 }
+
+version (OpenBSD)
+{
+    import core.sys.posix.sys.time;
+
+    double dtime()
+    {
+     double q;
+     timeval tv;
+
+     gettimeofday(&tv,null);
+     q = cast(double)tv.tv_sec + cast(double)tv.tv_usec * 1.0e-6;
+
+     return q;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/fix22372.d b/gcc/testsuite/gdc.test/runnable/fix22372.d
new file mode 100644 (file)
index 0000000..55864a0
--- /dev/null
@@ -0,0 +1,38 @@
+/* PERMUTE_ARGS: -O
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=22104
+
+struct S { int a1, a2, a3; }
+
+version (none)
+void throws2ndCall(ref S x);
+else
+{
+void throws2ndCall(ref S x)
+{
+    __gshared bool b;
+    if (b)
+        throw new Exception("n == 1");
+    b = true;
+}
+}
+
+void main() { foo(); }
+
+void foo()
+{
+    S[] arr = [S(), S()];
+    size_t i;
+    try
+    {
+        for (i = 0; i < 2; i++)
+            throws2ndCall(arr[i]);
+    }
+    catch (Exception o)
+    {
+        //printf("Exception: i = %lu\n", i);
+        assert(i == 1);  // this fails
+    }
+}
+
index a626749ee463b0fc7019995a272beec75f3564ea..989fb2e1e908203f7241a5b7911faab0868c69ae 100644 (file)
@@ -3604,6 +3604,62 @@ void test21878()
     ctfeFunc21878(); // succeeds at runtime
 }
 
+/************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=20133
+
+void bar20133(ref string text)
+{
+    text = text[1 .. $];
+    assert(text.length < 3);
+    if (text.length == 2) assert(text == "oo");
+    if (text.length == 1) assert(text == "o");
+    if (text.length == 0) assert(text == "");
+    string tcopy = text;
+    if (tcopy.length > 0)
+        bar20133(tcopy);
+    assert(tcopy.length < 2);
+    if (tcopy.length == 1) assert(tcopy == "o");
+    if (tcopy.length == 0) assert(tcopy == "");
+}
+
+void bar20133_2(ref string text)
+{
+    auto ptext = &text;
+    *ptext = text[1 .. $];
+    assert(text.length < 3);
+    if (text.length == 2) assert(text == "oo");
+    if (text.length == 1) assert(text == "o");
+    if (text.length == 0) assert(text == "");
+    string tcopy = text;
+    if (tcopy.length > 0)
+        bar20133_2(tcopy);
+    assert(tcopy.length < 2);
+    if (tcopy.length == 1) assert(tcopy == "o");
+    if (tcopy.length == 0) assert(tcopy == "");
+}
+
+alias fun20133 = {
+    string input = "foo";
+    bar20133(input);
+    assert(input == "oo");
+    return input;
+};
+
+alias fun20133_2 = {
+    string input = "foo";
+    bar20133_2(input);
+    assert(input == "oo");
+    return input;
+};
+
+void test20133()
+{
+    enum ctest = fun20133();
+    enum ctest2 = fun20133_2();
+    auto rtest = fun20133();
+    auto rtest2 = fun20133_2();
+}
+
 /************************************************/
 
 int main()
@@ -3732,6 +3788,7 @@ int main()
     test20366();
     test20400();
     test21878();
+    test20133();
 
     printf("Success\n");
     return 0;
index 447ea28294c39618539c85455d0df39efdd9ff7f..1da0479d9f6eb583063a7b4355c1dde779e8f436 100644 (file)
@@ -66,9 +66,56 @@ void test2()
 
 /*****************************************/
 
+struct BasicStruct
+{
+       int firstInt;
+       noreturn noRet;
+       long lastLong;
+}
+
+struct AlignedStruct
+{
+       int firstInt;
+       align(16) noreturn noRet;
+       long lastLong;
+}
+
+void takeBasic(BasicStruct bs)
+{
+    assert(bs.firstInt == 13);
+    assert(bs.lastLong == 42);
+
+    assert(&bs.noRet == (&bs.firstInt + 1));
+}
+
+void takeAligned(AlignedStruct as)
+{
+    assert(as.firstInt == 99);
+    assert(as.lastLong == 0xDEADBEEF);
+
+    assert(&as.noRet == &as.lastLong);
+}
+
+void test3()
+{
+    {
+        BasicStruct bs;
+        bs.firstInt = 13;
+        bs.lastLong = 42;
+        takeBasic(bs);
+    }
+    {
+        AlignedStruct as;
+        as.firstInt = 99;
+        as.lastLong = 0xDEADBEEF;
+        takeAligned(as);
+    }
+}
+
 int main()
 {
     test1();
     test2();
+    test3();
     return 0;
 }
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn2.d b/gcc/testsuite/gdc.test/runnable/noreturn2.d
new file mode 100644 (file)
index 0000000..1d3d362
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+PERMUTE_ARGS: -O -inline
+RUN_OUTPUT:
+---
+getAndPrintS
+---
+*/
+
+import core.stdc.stdio;
+import core.exception : AssertError;
+
+/*****************************************/
+
+// noreturn is inferred for functions that always throw
+// The code must not strip the destructor when calling a noreturn function
+
+struct WithDtor
+{
+    __gshared int destroyed;
+
+    int num;
+
+    int acceptNoreturn(int a, int b, int c)
+    {
+        puts("unreachable");
+        return num + a + b + c;
+    }
+
+    ~this()
+    {
+        destroyed += num;
+    }
+}
+
+noreturn doesThrow()
+{
+    WithDtor wd = WithDtor(1);
+    throw new Exception("");
+}
+
+noreturn callDoesThrow()
+{
+    WithDtor wd = WithDtor(2);
+    doesThrow();
+}
+
+
+void testDtors()
+{
+    try
+    {
+        callDoesThrow();
+        assert(0);
+    } catch (Exception e) {}
+
+    assert(WithDtor.destroyed == 3);
+}
+
+/*****************************************************************************/
+
+/// Verifies that `func` throws a `Throwable` with `message` at `line`
+void testAssertFailure(size_t expLine, string expMsg, void function() func, size_t callLine = __LINE__)
+{
+    void enforce(bool check, string error)
+    {
+        if (!check)
+            throw new AssertError(error, __FILE__, callLine);
+    }
+
+    bool caught;
+    try
+    {
+        func();
+    }
+    catch (Throwable t)
+    {
+        // Save members because t might be overwritten by an Assertion failure below
+        string actFile = t.file;
+        size_t actLine = t.line;
+        string actMsg = t.msg;
+        caught = true;
+
+        scope (failure)
+        {
+            printf("\nfile = \"%.*s\"\nline = %zu\nmsg = \"%.*s\"\n\n",
+                cast(int) actFile.length, actFile.ptr,
+                actLine,
+                cast(int) actMsg.length, actMsg.ptr
+            );
+            fflush(stdout);
+        }
+
+        enforce(actFile == __FILE__, "Wrong file");
+        enforce(actLine == expLine, "Wrong line");
+        enforce(actMsg == expMsg, "Wrong message");
+    }
+
+    enforce(caught, "No Throwable was thrown!");
+}
+
+void testAccess()
+{
+    enum msg = "Accessed expression of type `noreturn`";
+
+    // FIXME: Another assertion failure in the backend trying to generate noreturn.sizeof = 0 byte assignment
+    version (FIXME)
+    testAssertFailure(__LINE__ + 3, msg, function noreturn()
+    {
+        noreturn a;
+        noreturn b = a;
+    });
+
+    if (false) // read does not assert!
+    testAssertFailure(__LINE__ + 3, msg, function noreturn()
+    {
+        noreturn a;
+        int b = a;
+        assert(false, "Unreachable!"); // Statement above not detected as noreturn
+    });
+
+    testAssertFailure(__LINE__ + 2, msg, function noreturn()
+    {
+        cast(noreturn) 1;
+    });
+
+    version (FIXME)
+    testAssertFailure(__LINE__ + 3, msg, function noreturn()
+    {
+        noreturn a;
+        noreturn b = cast(noreturn) 1;
+    });
+
+    if (false) // Read does not assert
+    testAssertFailure(__LINE__ + 3, msg, function noreturn()
+    {
+        noreturn a;
+        return a;
+    });
+
+    if (false) // Read does not assert
+    testAssertFailure(__LINE__ + 4, msg, function noreturn()
+    {
+        static void foo(noreturn) {}
+        noreturn a;
+        foo(a);
+        assert(false, "Unreachable!"); // Ditto
+    });
+}
+
+/*****************************************/
+
+void testFuncCall()
+{
+    enum msg = "Called abort()";
+    enum line = __LINE__ + 1;
+    static noreturn abort() { assert(0, msg); }
+
+    // Canaries to check for side effects
+    __gshared int countLeft, countRight;
+
+    scope (failure) printf("countLeft = %d\ncountRight = %d\n", countLeft, countRight);
+
+
+    // D function arguments are evaluated left to right
+    testAssertFailure(line, msg, function()
+    {
+        static void acceptNoreturnD(int, int, int) { puts("unreachable"); }
+
+        acceptNoreturnD(countLeft++, abort(), countRight++);
+    });
+
+    assert(countLeft == 1);
+    assert(countRight == 0);
+
+//     // C function arguments are still evaluated left to right
+//     // Despite them being push in reverse order
+    testAssertFailure(line, msg, function()
+    {
+        static extern(C) void acceptNoreturnC(int, int, int) { puts("unreachable"); }
+
+        acceptNoreturnC(countLeft++, abort(), countRight++);
+
+        assert(false);
+    });
+
+    assert(countLeft == 2);
+    assert(countRight == 0);
+
+    WithDtor.destroyed = 0;
+
+    testAssertFailure(__LINE__ + 2, "Error", function()
+    {
+        static WithDtor getS() { assert(false, "Error"); }
+
+        getS().acceptNoreturn(countLeft++, abort(), countRight++);
+    });
+
+    assert(countLeft == 2); // No changes
+    assert(countRight == 0);
+    assert(WithDtor.destroyed == 0); // No temporary to destruct
+
+    testAssertFailure(line, msg, function()
+    {
+        static WithDtor getAndPrintS() { puts("getAndPrintS"); return WithDtor(1); }
+
+        getAndPrintS().acceptNoreturn(countLeft++, abort(), countRight++);
+    });
+
+    assert(countLeft == 3);
+    assert(countRight == 0);
+    assert(WithDtor.destroyed == 1);
+}
+
+int main()
+{
+    testDtors();
+    testAccess();
+    testFuncCall();
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/sroa13220.d b/gcc/testsuite/gdc.test/runnable/sroa13220.d
new file mode 100644 (file)
index 0000000..2cec666
--- /dev/null
@@ -0,0 +1,103 @@
+/* REQUIRED_ARGS: -O -inline -noboundscheck
+ */
+// https://github.com/dlang/pull/13220
+
+version (D_SIMD)
+{
+
+mixin template VectorOps(VectorType, ArrayType: BaseType[N], BaseType, size_t N)
+{
+    enum Count = N;
+    alias Base = BaseType;
+
+    BaseType* ptr() return pure nothrow @nogc
+    {
+        return array.ptr;
+    }
+
+    // Unary operators
+    VectorType opUnary(string op)() pure nothrow @safe @nogc
+    {
+        VectorType res = void;
+        mixin("res.array[] = " ~ op ~ "array[];");
+        return res;
+    }
+
+    // Binary operators
+    VectorType opBinary(string op)(VectorType other) pure const nothrow @safe @nogc
+    {
+        VectorType res = void;
+        mixin("res.array[] = array[] " ~ op ~ " other.array[];");
+        return res;
+    }
+
+    // Assigning a BaseType value
+    void opAssign(BaseType e) pure nothrow @safe @nogc
+    {
+        array[] = e;
+    }
+
+    // Assigning a static array
+    void opAssign(ArrayType v) pure nothrow @safe @nogc
+    {
+        array[] = v[];
+    }
+
+    void opOpAssign(string op)(VectorType other) pure nothrow @safe @nogc
+    {
+        mixin("array[] "  ~ op ~ "= other.array[];");
+    }
+
+    // Assigning a dyn array
+    this(ArrayType v) pure nothrow @safe @nogc
+    {
+        array[] = v[];
+    }
+
+    // Broadcast constructor
+    this(BaseType x) pure nothrow @safe @nogc
+    {
+        array[] = x;
+    }
+
+    ref inout(BaseType) opIndex(size_t i) inout pure nothrow @safe @nogc
+    {
+        return array[i];
+    }
+}
+
+// Note: can't be @safe with this signature
+Vec loadUnaligned(Vec)(const(BaseType!Vec)* pvec) @trusted
+{
+    // Since this vector is emulated, it doesn't have alignement constraints
+    // and as such we can just cast it.
+    return *cast(Vec*)(pvec);
+}
+
+private template BaseType(V)
+{
+    alias typeof( ( { V v; return v; }()).array[0]) BaseType;
+}
+
+struct int4
+{
+    int[4] array;
+    mixin VectorOps!(int4, int[4]);
+}
+
+alias __m128i = int4;
+}
+
+int main()
+{
+  version (D_SIMD)
+  {
+    int4 A = [1, 2, 3, 4];
+    int4 ia = A;
+    ia.ptr[2] = 5;
+    int4 C = ia;
+    int[4] result = [1, 2, 5, 4];
+    assert(C.array == result);
+  }
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test15624.d b/gcc/testsuite/gdc.test/runnable/test15624.d
deleted file mode 100644 (file)
index 7927579..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* PERMUTE_ARGS:
- */
-
-// https://issues.dlang.org/show_bug.cgi?id=15624
-
-struct Foo {
-        int x;
-        int opApply(int delegate(int, string, string) @safe dg) @safe {
-                x = 1;
-                return 0;
-        }
-        int opApply(int delegate(int, string, string) @system dg) @system {
-                x = 2;
-                return 0;
-        }
-}
-
-void testSafe() @safe {
-        Foo foo;
-        foreach (i, k, v; foo) {
-        }
-        assert(foo.x == 1);
-}
-
-void testSystem() @system {
-        Foo foo;
-        foreach (i, k, v; foo) {
-        }
-        assert(foo.x == 2);
-}
-
-void test() @system
-{
-    Foo f;
-
-    int dgsafe  (int x, string s, string t) @safe   { return 1; }
-    int dgsystem(int x, string s, string t) @system { return 1; }
-
-    f.opApply(&dgsafe);
-    assert(f.x == 1);
-    f.opApply(&dgsystem);
-    assert(f.x == 2);
-}
-
-int main()
-{
-    testSafe();
-    testSystem();
-    test();
-    return 0;
-}
diff --git a/gcc/testsuite/gdc.test/runnable/test21039.d b/gcc/testsuite/gdc.test/runnable/test21039.d
new file mode 100644 (file)
index 0000000..c58600f
--- /dev/null
@@ -0,0 +1,27 @@
+// https://issues.dlang.org/show_bug.cgi?id=21039
+
+class Inner {}
+
+class Outer {
+    Inner inner;
+    alias inner this;
+    this(Inner i) { inner = i; }
+}
+
+void main() {
+  auto inner = new Inner;
+  auto outer = new Outer(new Inner);
+
+  // implicit cast goes through 'alias this'
+
+  Inner inner1 = outer;  // Already does it
+  assert(inner1);
+
+  Inner[] inners = [inner, outer]; // Fixed
+
+  assert(inners[0], "first element is null");
+  assert(inners[1], "second element is null");
+
+  Inner inner2 = 1 ? outer : inner; // Fixed
+  assert(inner2);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22205.d b/gcc/testsuite/gdc.test/runnable/test22205.d
new file mode 100644 (file)
index 0000000..78abf2f
--- /dev/null
@@ -0,0 +1,17 @@
+// REQUIRED_ARGS: -debug
+
+void main() nothrow
+{
+    debug
+    {
+        try
+        {
+            throw new Exception("2");
+        }
+        catch (Exception) {}
+        catch (Throwable)
+        {
+            assert(0);
+        }
+    }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22278.d b/gcc/testsuite/gdc.test/runnable/test22278.d
new file mode 100644 (file)
index 0000000..72332a4
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+REQUIRED_ARGS: -release
+PERMUTE_ARGS:  -check=in=on -check=out=on
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=22278
+
+bool resultIn;
+bool resultOut;
+
+void foo22278()
+    in { resultIn = true; }
+    out { resultOut = true; }
+do {}
+
+int main()
+{
+    foo22278();
+
+    version(D_PreConditions)  assert(resultIn);  else assert(!resultIn);
+    version(D_PostConditions) assert(resultOut); else assert(!resultOut);
+
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testOpApply.d b/gcc/testsuite/gdc.test/runnable/testOpApply.d
new file mode 100644 (file)
index 0000000..7b884e5
--- /dev/null
@@ -0,0 +1,142 @@
+/* PERMUTE_ARGS:
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=15624
+
+struct Foo {
+        int x;
+        int opApply(int delegate(int, string, string) @safe dg) @safe {
+                x = 1;
+                return 0;
+        }
+        int opApply(int delegate(int, string, string) @system dg) @system {
+                x = 2;
+                return 0;
+        }
+}
+
+void testSafe() @safe {
+        Foo foo;
+        foreach (i, k, v; foo) {
+        }
+        assert(foo.x == 1);
+}
+
+void testSystem() @system {
+        Foo foo;
+        foreach (i, k, v; foo) {
+        }
+        assert(foo.x == 2);
+}
+
+void test() @system
+{
+    Foo f;
+
+    int dgsafe  (int x, string s, string t) @safe   { return 1; }
+    int dgsystem(int x, string s, string t) @system { return 1; }
+
+    f.opApply(&dgsafe);
+    assert(f.x == 1);
+    f.opApply(&dgsystem);
+    assert(f.x == 2);
+}
+
+int main()
+{
+    testSafe();
+    testSystem();
+    test();
+    testDifferentTypes();
+    testSameAttributes();
+    testInverseAttributes();
+    return 0;
+}
+
+void testDifferentTypes()
+{
+    static struct DifferentTypes
+    {
+        int x;
+        int opApply(int delegate(int) dg) @safe {
+            x = 1;
+            return 0;
+        }
+        int opApply(int delegate(long) dg) @safe {
+            x = 2;
+            return 0;
+        }
+    }
+
+    DifferentTypes dt;
+    foreach (int i; dt) {}
+    assert(dt.x == 1);
+
+    foreach (long i; dt) {}
+    assert(dt.x == 2);
+}
+
+void testSameAttributes()
+{
+    static struct SameAttributes
+    {
+        int x;
+        int opApply(int delegate(int) @system dg) @safe {
+            x = 1;
+            return 0;
+        }
+        int opApply(int delegate(int) @safe dg) @safe {
+            x = 2;
+            return 0;
+        }
+    }
+
+    static void safe() @safe
+    {
+        SameAttributes sa;
+        foreach (i; sa) {}
+        assert(sa.x == 2);
+    }
+    safe();
+
+    static void system() @system
+    {
+        SameAttributes sa;
+        foreach (i; sa) {}
+        assert(sa.x == 1);
+    }
+    system();
+}
+
+// Not useful but enabled by the associated patch
+void testInverseAttributes()
+{
+    static struct InverseAttributes
+    {
+        int x;
+        int opApply(int delegate(int) @system dg) @safe {
+            x = 1;
+            return 0;
+        }
+        int opApply(int delegate(int) @safe dg) @system {
+            x = 2;
+            return 0;
+        }
+    }
+
+    static void system() @system
+    {
+        InverseAttributes sa;
+        foreach (i; sa) {}
+        assert(sa.x == 1);
+    }
+    system();
+
+    static void safe() @safe
+    {
+        InverseAttributes sa;
+        (() @trusted { foreach (i; sa) {} })();
+        assert(sa.x == 2);
+    }
+    safe();
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testmainb.d b/gcc/testsuite/gdc.test/runnable/testmainb.d
new file mode 100644 (file)
index 0000000..d6452ec
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+Test that -main does nothing when main is already defined
+
+REQUIRED_ARGS: -main
+RUN_OUTPUT:
+---
+Success
+---
+*/
+extern(C) int printf(const char*, ...);
+
+void main()
+{
+    printf("Success\n");
+}
index cdb9aa660cbd8ba8e2df553b67de5bec75febaf7..1d01098964613b870bb12b4463fc5b64df647a6c 100644 (file)
@@ -697,6 +697,54 @@ static if(is(typeof(foo20831) Params20831 == __parameters))
 
 /************************************************/
 
+/************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=15804
+
+template test15804()
+{
+    alias AliasSeq(T...) = T;
+
+    @(42) struct Foo(D) {}
+    auto fooFac(T)()
+    {
+        static assert(__traits(getAttributes, Foo) == AliasSeq!42);
+        static assert(__traits(getAttributes, Foo!int) == AliasSeq!42);
+        return Foo!T();
+    }
+
+    auto booFac(T)()
+    {
+        @(43) struct Boo {}
+        static assert(__traits(getAttributes, Boo) == AliasSeq!43);
+        return Boo();
+    }
+
+    auto barFac(T)()
+    {
+        @(44) struct Bar(D) {}
+        static assert(__traits(getAttributes, Bar) == AliasSeq!44); // Fixed
+        static assert(__traits(getAttributes, Bar!int) == AliasSeq!44);
+        return Bar!T();
+    }
+
+    auto bazFac(T)()
+    {
+        @(45) static struct Baz(D) {}
+        static assert(__traits(getAttributes, Baz) == AliasSeq!45); // Fixed
+        static assert(__traits(getAttributes, Baz!int) == AliasSeq!45);
+        return Baz!T();
+    }
+
+    auto foo = fooFac!int;
+    auto boo = booFac!int;
+    auto bar = barFac!int;
+    auto baz = bazFac!int;
+}
+
+alias a15804 = test15804!();
+
+/************************************************/
+
 int main()
 {
     test1();
index 2d9bf1559836cf39b9843e5ba0c5d730d6b45825..8fd7bb2fba246254b3a01aac638dd214910e76a7 100644 (file)
@@ -196,6 +196,7 @@ void test5()
     {
         // f5_1 .. f5_5 are symbols which declared in module scope
         assert(100.f5_1() == 1);
+        assert(001.f5_1() == 1); // https://issues.dlang.org/show_bug.cgi?id=8346
         assert("s".f5_2() == 2);
         assert(1.4.f5_3() == 3);
         assert(100.f5_4() == 1);
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp22287.cpp
new file mode 100644 (file)
index 0000000..ba7b25a
--- /dev/null
@@ -0,0 +1,337 @@
+#include <assert.h>
+
+class X
+{
+public:
+    virtual ~X();
+    int i;
+};
+
+X::~X()
+{
+}
+
+class Y : public X
+{
+};
+
+class A
+{
+public:
+    virtual ~A();
+    virtual int f1() const;
+
+    int i;
+};
+
+class I
+{
+public:
+    virtual int f2() const = 0;
+    virtual X *f4() = 0;
+};
+
+class B : public A, public I
+{
+public:
+    virtual int f1() const;
+    virtual int f2() const;
+    virtual int f3() const;
+    virtual X *f4();
+};
+
+class C : public B
+{
+public:
+    virtual int f1() const;
+    virtual int f2() const;
+    virtual int f3() const;
+    virtual Y *f4();
+};
+
+#ifdef _WIN32
+class D : public B
+{
+public:
+    virtual int f1() const;
+    virtual int f2() const;
+    virtual int f3() const;
+    virtual Y *f4();
+};
+
+class E : public B
+{
+public:
+    virtual int f1() const;
+    virtual int f2() const;
+    virtual int f3() const;
+    virtual Y *f4();
+};
+#endif
+
+A::~A()
+{
+}
+
+int A::f1() const
+{
+    return i + 11;
+}
+
+int B::f1() const
+{
+    return i + 21;
+}
+
+int B::f2() const
+{
+    return i + 22;
+}
+
+int B::f3() const
+{
+    return i + 23;
+}
+
+X *B::f4()
+{
+    X *r = new X;
+    r->i = i + 24;
+    return r;
+}
+
+int C::f1() const
+{
+    return i + 31;
+}
+
+int C::f2() const
+{
+    return i + 32;
+}
+
+int C::f3() const
+{
+    return i + 33;
+}
+
+Y *C::f4()
+{
+    Y *r = new Y;
+    r->i = i + 34;
+    return r;
+}
+
+I *createIFromCPP(char type, int i)
+{
+    switch (type)
+    {
+    case 'B':
+    {
+        B *b = new B();
+        b->i = i;
+        return b;
+    }
+    case 'C':
+    {
+        C *c = new C();
+        c->i = i;
+        return c;
+    }
+#ifdef _WIN32
+    case 'D':
+    {
+        D *d = new D();
+        d->i = i;
+        return d;
+    }
+    case 'E':
+    {
+        E *e = new E();
+        e->i = i;
+        return e;
+    }
+#endif
+    default:
+        return 0;
+    }
+}
+
+B *createBFromCPP(char type, int i)
+{
+    switch (type)
+    {
+    case 'B':
+    {
+        B *b = new B();
+        b->i = i;
+        return b;
+    }
+    case 'C':
+    {
+        C *c = new C();
+        c->i = i;
+        return c;
+    }
+#ifdef _WIN32
+    case 'D':
+    {
+        D *d = new D();
+        d->i = i;
+        return d;
+    }
+    case 'E':
+    {
+        E *e = new E();
+        e->i = i;
+        return e;
+    }
+#endif
+    default:
+        return 0;
+    }
+}
+
+C *createCFromCPP(int i)
+{
+    C *c = new C();
+    c->i = i;
+    return c;
+}
+
+#ifdef _WIN32
+D *createDFromCPP(int i)
+{
+    D *d = new D();
+    d->i = i;
+    return d;
+}
+
+E *createEFromCPP(int i)
+{
+    E *e = new E();
+    e->i = i;
+    return e;
+}
+#endif
+
+I *createIFromD(char type, int i);
+B *createBFromD(char type, int i);
+C *createCFromD(int i);
+#ifdef _WIN32
+D *createDFromD(int i);
+E *createEFromD(int i);
+#endif
+
+void runCPPTests()
+{
+    {
+        B *b = new B();
+        b->i = 100;
+        assert(b->f1() == 121);
+        assert(b->f2() == 122);
+        assert(b->f3() == 123);
+        assert(b->f4()->i == 124);
+    }
+    {
+        C *c = new C();
+        c->i = 100;
+        assert(c->f1() == 131);
+        assert(c->f2() == 132);
+        assert(c->f3() == 133);
+        assert(c->f4()->i == 134);
+    }
+#ifdef _WIN32
+    {
+        D *d = new D();
+        d->i = 100;
+        assert(d->f1() == 141);
+        assert(d->f2() == 142);
+        assert(d->f3() == 143);
+        assert(d->f4()->i == 144);
+    }
+    {
+        E *e = new E();
+        e->i = 100;
+        assert(e->f1() == 151);
+        assert(e->f2() == 152);
+        assert(e->f3() == 153);
+        assert(e->f4()->i == 154);
+    }
+#endif
+    {
+        I *i = createIFromD('B', 100);
+        assert(i->f2() == 122);
+        assert(i->f4()->i == 124);
+    }
+    {
+        I *i = createIFromD('C', 100);
+        assert(i->f2() == 132);
+        assert(i->f4()->i == 134);
+    }
+#ifdef _WIN32
+    {
+        I *i = createIFromD('D', 100);
+        assert(i->f2() == 142);
+        assert(i->f4()->i == 144);
+    }
+    {
+        I *i = createIFromD('E', 100);
+        assert(i->f2() == 152);
+        assert(i->f4()->i == 154);
+    }
+#endif
+    {
+        B *b = createBFromD('B', 100);
+        assert(b->f1() == 121);
+        assert(b->f2() == 122);
+        assert(b->f3() == 123);
+        assert(b->f4()->i == 124);
+    }
+    {
+        B *b = createBFromD('C', 100);
+        assert(b->f1() == 131);
+        assert(b->f2() == 132);
+        assert(b->f3() == 133);
+        assert(b->f4()->i == 134);
+    }
+#ifdef _WIN32
+    {
+        B *b = createBFromD('D', 100);
+        assert(b->f1() == 141);
+        assert(b->f2() == 142);
+        assert(b->f3() == 143);
+        assert(b->f4()->i == 144);
+    }
+    {
+        B *b = createBFromD('E', 100);
+        assert(b->f1() == 151);
+        assert(b->f2() == 152);
+        assert(b->f3() == 153);
+        assert(b->f4()->i == 154);
+    }
+#endif
+    {
+        C *c = createCFromD(100);
+        assert(c->f1() == 131);
+        assert(c->f2() == 132);
+        assert(c->f3() == 133);
+        assert(c->f4()->i == 134);
+    }
+#ifdef _WIN32
+    {
+        D *d = createDFromD(100);
+        assert(d->f1() == 141);
+        assert(d->f2() == 142);
+        assert(d->f3() == 143);
+        assert(d->f4()->i == 144);
+    }
+    {
+        E *e = createEFromD(100);
+        assert(e->f1() == 151);
+        assert(e->f2() == 152);
+        assert(e->f3() == 153);
+        assert(e->f4()->i == 154);
+    }
+#endif
+}
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test22287.d b/gcc/testsuite/gdc.test/runnable_cxx/test22287.d
new file mode 100644 (file)
index 0000000..a0c7475
--- /dev/null
@@ -0,0 +1,327 @@
+// EXTRA_CPP_SOURCES: cpp22287.cpp
+
+extern(C++):
+
+class X
+{
+public:
+    ~this();
+    int i;
+}
+
+class Y : X
+{
+}
+
+class A
+{
+    ~this();
+    int f1() const;
+
+    int i;
+}
+
+interface I
+{
+    int f2() const;
+    X f4();
+}
+
+class B : A, I
+{
+    override int f1() const;
+    override int f2() const;
+    int f3() const;
+    override X f4();
+}
+
+class C : B
+{
+    override int f1() const;
+    override int f2() const;
+    override int f3() const;
+    override Y f4();
+}
+
+version(Windows)
+{
+class D : B
+{
+    override int f1() const
+    {
+        return i + 41;
+    }
+
+    override int f2() const
+    {
+        return i + 42;
+    }
+
+    override int f3() const
+    {
+        return i + 43;
+    }
+
+    override Y f4()
+    {
+        Y r = new Y;
+        r.i = i + 44;
+        return r;
+    }
+}
+
+mixin template MixinE()
+{
+    override int f1() const
+    {
+        return i + 51;
+    }
+
+    override int f2() const
+    {
+        return i + 52;
+    }
+
+    override int f3() const
+    {
+        return i + 53;
+    }
+
+    override Y f4()
+    {
+        Y r = new Y;
+        r.i = i + 54;
+        return r;
+    }
+}
+
+class E : B
+{
+    mixin MixinE;
+}
+}
+
+I createIFromCPP(char type, int i);
+B createBFromCPP(char type, int i);
+C createCFromCPP(int i);
+version(Windows)
+{
+D createDFromCPP(int i);
+E createEFromCPP(int i);
+}
+
+I createIFromD(char type, int i)
+{
+    switch (type)
+    {
+    case 'B':
+    {
+        B b = new B();
+        b.i = i;
+        return b;
+    }
+    case 'C':
+    {
+        C c = new C();
+        c.i = i;
+        return c;
+    }
+    version(Windows)
+    {
+    case 'D':
+    {
+        D d = new D();
+        d.i = i;
+        return d;
+    }
+    case 'E':
+    {
+        E e = new E();
+        e.i = i;
+        return e;
+    }
+    }
+    default:
+        return null;
+    }
+}
+
+B createBFromD(char type, int i)
+{
+    switch (type)
+    {
+    case 'B':
+    {
+        B b = new B();
+        b.i = i;
+        return b;
+    }
+    case 'C':
+    {
+        C c = new C();
+        c.i = i;
+        return c;
+    }
+    version(Windows)
+    {
+    case 'D':
+    {
+        D d = new D();
+        d.i = i;
+        return d;
+    }
+    case 'E':
+    {
+        E e = new E();
+        e.i = i;
+        return e;
+    }
+    }
+    default:
+        return null;
+    }
+}
+
+C createCFromD(int i)
+{
+    C c = new C();
+    c.i = i;
+    return c;
+}
+
+version(Windows)
+{
+D createDFromD(int i)
+{
+    D d = new D();
+    d.i = i;
+    return d;
+}
+
+E createEFromD(int i)
+{
+    E e = new E();
+    e.i = i;
+    return e;
+}
+}
+
+void runCPPTests();
+
+extern(D) void main()
+{
+    {
+        B b = new B();
+        b.i = 100;
+        assert(b.f1() == 121);
+        assert(b.f2() == 122);
+        assert(b.f3() == 123);
+        assert(b.f4().i == 124);
+    }
+    {
+        C c = new C();
+        c.i = 100;
+        assert(c.f1() == 131);
+        assert(c.f2() == 132);
+        assert(c.f3() == 133);
+        assert(c.f4().i == 134);
+    }
+    version(Windows)
+    {
+    {
+        D d = new D();
+        d.i = 100;
+        assert(d.f1() == 141);
+        assert(d.f2() == 142);
+        assert(d.f3() == 143);
+        assert(d.f4().i == 144);
+    }
+    {
+        E e = new E();
+        e.i = 100;
+        assert(e.f1() == 151);
+        assert(e.f2() == 152);
+        assert(e.f3() == 153);
+        assert(e.f4().i == 154);
+    }
+    }
+    {
+        I i = createIFromCPP('B', 100);
+        assert(i.f2() == 122);
+        assert(i.f4().i == 124);
+    }
+    {
+        I i = createIFromCPP('C', 100);
+        assert(i.f2() == 132);
+        assert(i.f4().i == 134);
+    }
+    version(Windows)
+    {
+    {
+        I i = createIFromCPP('D', 100);
+        assert(i.f2() == 142);
+        assert(i.f4().i == 144);
+    }
+    {
+        I i = createIFromCPP('E', 100);
+        assert(i.f2() == 152);
+        assert(i.f4().i == 154);
+    }
+    }
+    {
+        B b = createBFromCPP('B', 100);
+        assert(b.f1() == 121);
+        assert(b.f2() == 122);
+        assert(b.f3() == 123);
+        assert(b.f4().i == 124);
+    }
+    {
+        B b = createBFromCPP('C', 100);
+        assert(b.f1() == 131);
+        assert(b.f2() == 132);
+        assert(b.f3() == 133);
+        assert(b.f4().i == 134);
+    }
+    version(Windows)
+    {
+    {
+        B b = createBFromCPP('D', 100);
+        assert(b.f1() == 141);
+        assert(b.f2() == 142);
+        assert(b.f3() == 143);
+        assert(b.f4().i == 144);
+    }
+    {
+        B b = createBFromCPP('E', 100);
+        assert(b.f1() == 151);
+        assert(b.f2() == 152);
+        assert(b.f3() == 153);
+        assert(b.f4().i == 154);
+    }
+    }
+    {
+        C c = createCFromCPP(100);
+        assert(c.f1() == 131);
+        assert(c.f2() == 132);
+        assert(c.f3() == 133);
+        assert(c.f4().i == 134);
+    }
+    version(Windows)
+    {
+    {
+        D d = createDFromCPP(100);
+        assert(d.f1() == 141);
+        assert(d.f2() == 142);
+        assert(d.f3() == 143);
+        assert(d.f4().i == 144);
+    }
+    {
+        E e = createEFromCPP(100);
+        assert(e.f1() == 151);
+        assert(e.f2() == 152);
+        assert(e.f3() == 153);
+        assert(e.f4().i == 154);
+    }
+    }
+    runCPPTests();
+}
index 11bef0f338861a50b6bcc6deb7de4081e87779c5..d0d3a25ad1e85b133404ea99ad3cbbff14cc6b58 100644 (file)
@@ -1,4 +1,4 @@
-e6caaab9d359198b760c698dcb6d253afb3f81f6
+178c44ff362902af589603767055cfac89215652
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
index 80c7567079ae95f8c561a21b84a3d4d6bcc4ca6f..44d4fe16be0cbe0e21824cc169240079badfac6b 100644 (file)
@@ -280,8 +280,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.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/time.d \
-       core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d
+       core/sys/linux/syscalls.d core/sys/linux/termios.d \
+       core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \
+       core/sys/linux/unistd.d
 
 DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
        core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
@@ -294,12 +295,13 @@ DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
 
 DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
        core/sys/openbsd/err.d core/sys/openbsd/execinfo.d \
-       core/sys/openbsd/stdlib.d core/sys/openbsd/string.d \
-       core/sys/openbsd/sys/cdefs.d core/sys/openbsd/sys/elf.d \
-       core/sys/openbsd/sys/elf32.d core/sys/openbsd/sys/elf64.d \
-       core/sys/openbsd/sys/elf_common.d core/sys/openbsd/sys/link_elf.d \
-       core/sys/openbsd/sys/mman.d core/sys/openbsd/sys/sysctl.d \
-       core/sys/openbsd/time.d core/sys/openbsd/unistd.d
+       core/sys/openbsd/pthread_np.d core/sys/openbsd/stdlib.d \
+       core/sys/openbsd/string.d core/sys/openbsd/sys/cdefs.d \
+       core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
+       core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
+       core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
+       core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \
+       core/sys/openbsd/unistd.d
 
 DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
        core/sys/posix/arpa/inet.d core/sys/posix/config.d \
index b5f29da8540f9a0243a0da6b072e77ff6fc5996b..84be8082f7a4c7644aa8b2b2e3fa0424a9695ef9 100644 (file)
@@ -343,10 +343,10 @@ am__objects_14 = core/sys/netbsd/dlfcn.lo core/sys/netbsd/err.lo \
        core/sys/netbsd/sys/sysctl.lo core/sys/netbsd/time.lo
 @DRUNTIME_OS_NETBSD_TRUE@am__objects_15 = $(am__objects_14)
 am__objects_16 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/err.lo \
-       core/sys/openbsd/execinfo.lo core/sys/openbsd/stdlib.lo \
-       core/sys/openbsd/string.lo core/sys/openbsd/sys/cdefs.lo \
-       core/sys/openbsd/sys/elf.lo core/sys/openbsd/sys/elf32.lo \
-       core/sys/openbsd/sys/elf64.lo \
+       core/sys/openbsd/execinfo.lo core/sys/openbsd/pthread_np.lo \
+       core/sys/openbsd/stdlib.lo core/sys/openbsd/string.lo \
+       core/sys/openbsd/sys/cdefs.lo core/sys/openbsd/sys/elf.lo \
+       core/sys/openbsd/sys/elf32.lo core/sys/openbsd/sys/elf64.lo \
        core/sys/openbsd/sys/elf_common.lo \
        core/sys/openbsd/sys/link_elf.lo core/sys/openbsd/sys/mman.lo \
        core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo \
@@ -367,9 +367,9 @@ am__objects_18 = core/sys/linux/config.lo core/sys/linux/dlfcn.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/time.lo \
-       core/sys/linux/timerfd.lo core/sys/linux/tipc.lo \
-       core/sys/linux/unistd.lo
+       core/sys/linux/syscalls.lo core/sys/linux/termios.lo \
+       core/sys/linux/time.lo core/sys/linux/timerfd.lo \
+       core/sys/linux/tipc.lo core/sys/linux/unistd.lo
 @DRUNTIME_OS_LINUX_TRUE@am__objects_19 = $(am__objects_18)
 am__objects_20 = core/sys/windows/accctrl.lo \
        core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \
@@ -944,8 +944,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.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/time.d \
-       core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d
+       core/sys/linux/syscalls.d core/sys/linux/termios.d \
+       core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \
+       core/sys/linux/unistd.d
 
 DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
        core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
@@ -958,12 +959,13 @@ DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
 
 DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
        core/sys/openbsd/err.d core/sys/openbsd/execinfo.d \
-       core/sys/openbsd/stdlib.d core/sys/openbsd/string.d \
-       core/sys/openbsd/sys/cdefs.d core/sys/openbsd/sys/elf.d \
-       core/sys/openbsd/sys/elf32.d core/sys/openbsd/sys/elf64.d \
-       core/sys/openbsd/sys/elf_common.d core/sys/openbsd/sys/link_elf.d \
-       core/sys/openbsd/sys/mman.d core/sys/openbsd/sys/sysctl.d \
-       core/sys/openbsd/time.d core/sys/openbsd/unistd.d
+       core/sys/openbsd/pthread_np.d core/sys/openbsd/stdlib.d \
+       core/sys/openbsd/string.d core/sys/openbsd/sys/cdefs.d \
+       core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
+       core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
+       core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
+       core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \
+       core/sys/openbsd/unistd.d
 
 DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
        core/sys/posix/arpa/inet.d core/sys/posix/config.d \
@@ -1616,6 +1618,7 @@ core/sys/openbsd/$(am__dirstamp):
 core/sys/openbsd/dlfcn.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/openbsd/err.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/openbsd/execinfo.lo: core/sys/openbsd/$(am__dirstamp)
+core/sys/openbsd/pthread_np.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/openbsd/stdlib.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/openbsd/string.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/openbsd/sys/$(am__dirstamp):
@@ -1672,6 +1675,7 @@ core/sys/linux/sys/socket.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/syscalls.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 ad9b44a1ee5f6ab76566c1895c1df5d264845953..33ca0ddc7bd64fff667d54974389adbf48d5567b 100644 (file)
@@ -346,6 +346,13 @@ pure @safe:
     }
 
 
+    void popFront(int i)
+    {
+        while (i--)
+            popFront();
+    }
+
+
     void match( char val )
     {
         test( val );
@@ -636,6 +643,7 @@ pure @safe:
         TypeDelegate
         TypeNone
         TypeVoid
+        TypeNoreturn
         TypeByte
         TypeUbyte
         TypeShort
@@ -715,6 +723,9 @@ pure @safe:
     TypeVoid:
         v
 
+    TypeNoreturn
+        Nn
+
     TypeByte:
         g
 
@@ -873,6 +884,10 @@ pure @safe:
             popFront();
             switch ( front )
             {
+            case 'n': // Noreturn
+                popFront();
+                put("noreturn");
+                return dst[beg .. len];
             case 'g': // Wild (Ng Type)
                 popFront();
                 // TODO: Anything needed here?
@@ -1164,9 +1179,11 @@ pure @safe:
             case 'g':
             case 'h':
             case 'k':
+            case 'n':
                 // NOTE: The inout parameter type is represented as "Ng".
                 //       The vector parameter type is represented as "Nh".
                 //       The return parameter type is represented as "Nk".
+                //       The noreturn parameter type is represented as "Nn".
                 //       These make it look like a FuncAttr, but infact
                 //       if we see these, then we know we're really in
                 //       the parameter list.  Rewind and break.
@@ -1217,6 +1234,59 @@ pure @safe:
                 break;
             }
             putComma(n);
+
+            /* Do special return, scope, ref, out combinations
+             */
+            int npops;
+            if ( 'M' == front && peek(1) == 'N' && peek(2) == 'k')
+            {
+                const c3 = peek(3);
+                if (c3 == 'J')
+                {
+                    put("scope return out ");   // MNkJ
+                    npops = 4;
+                }
+                else if (c3 == 'K')
+                {
+                    put("scope return ref ");   // MNkK
+                    npops = 4;
+                }
+            }
+            else if ('N' == front && peek(1) == 'k')
+            {
+                const c2 = peek(2);
+                if (c2 == 'J')
+                {
+                    put("return out ");         // NkJ
+                    npops = 3;
+                }
+                else if (c2 == 'K')
+                {
+                    put("return ref ");         // NkK
+                    npops = 3;
+                }
+                else if (c2 == 'M')
+                {
+                    const c3 = peek(3);
+                    if (c3 == 'J')
+                    {
+                        put("return scope out ");       // NkMJ
+                        npops = 4;
+                    }
+                    else if (c3 == 'K')
+                    {
+                        put("return scope ref ");       // NkMK
+                        npops = 4;
+                    }
+                    else
+                    {
+                        put("return scope ");           // NkM
+                        npops = 3;
+                    }
+                }
+            }
+            popFront(npops);
+
             if ( 'M' == front )
             {
                 popFront();
@@ -2558,6 +2628,15 @@ else
          `nothrow @trusted ulong std.algorithm.iteration.FilterResult!(std.typecons.Tuple!(int, "a", int, "b", int, "c").`
         ~`Tuple.rename!([0:"c", 2:"a"]).rename().__lambda1, int[]).FilterResult.__xtoHash(ref const(std.algorithm.iteration.`
         ~`FilterResult!(std.typecons.Tuple!(int, "a", int, "b", int, "c").Tuple.rename!([0:"c", 2:"a"]).rename().__lambda1, int[]).FilterResult))`],
+
+        ["_D4test4rrs1FKPiZv",    "void test.rrs1(ref int*)"],
+        ["_D4test4rrs1FMNkJPiZv", "void test.rrs1(scope return out int*)"],
+        ["_D4test4rrs1FMNkKPiZv", "void test.rrs1(scope return ref int*)"],
+        ["_D4test4rrs1FNkJPiZv",  "void test.rrs1(return out int*)"],
+        ["_D4test4rrs1FNkKPiZv",  "void test.rrs1(return ref int*)"],
+        ["_D4test4rrs1FNkMJPiZv", "void test.rrs1(return scope out int*)"],
+        ["_D4test4rrs1FNkMKPiZv", "void test.rrs1(return scope ref int*)"],
+        ["_D4test4rrs1FNkMPiZv",  "void test.rrs1(return scope int*)"],
     ];
 
 
@@ -2621,6 +2700,25 @@ unittest
     assert(s.demangle == expected);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=22235
+unittest
+{
+    enum parent = __MODULE__ ~ '.' ~ __traits(identifier, __traits(parent, {}));
+
+    static noreturn abort() { assert(false); }
+    assert(demangle(abort.mangleof) == "pure nothrow @nogc @safe noreturn " ~ parent ~ "().abort()");
+
+    static void accept(noreturn) {}
+    assert(demangle(accept.mangleof) == "pure nothrow @nogc @safe void " ~ parent ~ "().accept(noreturn)");
+
+    static void templ(T)(T, T) {}
+    assert(demangle(templ!noreturn.mangleof) == "pure nothrow @nogc @safe void " ~ parent ~ "().templ!(noreturn).templ(noreturn, noreturn)");
+
+    static struct S(T) {}
+    static void aggr(S!noreturn) { assert(0); }
+    assert(demangle(aggr.mangleof) == "pure nothrow @nogc @safe void " ~ parent ~ "().aggr(" ~ parent ~ "().S!(noreturn).S)");
+}
+
 /*
  *
  */
index fe298d4a09fdef8b3ff360e3bd31dc4638ae4951..a69286607737d7b01f1b671827548d33b02a1815 100644 (file)
@@ -97,7 +97,7 @@ class ArrayIndexError : RangeError
         this.length = length;
 
         // Constructing the message is a bit clumsy:
-        // It's essentially `printf("index [%zu] exceeds array of length [%zu]", index, length)`,
+        // It's essentially `printf("index [%zu] is out of bounds for array of length [%zu]", index, length)`,
         // but even `snprintf` isn't `pure`.
         // Also string concatenation isn't `@nogc`, and casting to/from immutable isn't `@safe`
         import core.internal.string : unsignedToTempString;
@@ -106,8 +106,7 @@ class ArrayIndexError : RangeError
         char[] sink = buf[];
         sink.rangeMsgPut("index [");
         sink.rangeMsgPut(unsignedToTempString!10(index, tmpBuf));
-        sink.rangeMsgPut("]");
-        sink.rangeMsgPut(" exceeds array of length ");
+        sink.rangeMsgPut("] is out of bounds for array of length ");
         sink.rangeMsgPut(unsignedToTempString!10(length, tmpBuf));
         this.msgBuf = buf;
         super(msgBuf[0..$-sink.length], file, line, next);
@@ -116,7 +115,7 @@ class ArrayIndexError : RangeError
 
 @safe pure unittest
 {
-    assert(new ArrayIndexError(900, 700).msg == "index [900] exceeds array of length 700");
+    assert(new ArrayIndexError(900, 700).msg == "index [900] is out of bounds for array of length 700");
     // Ensure msg buffer doesn't overflow on large numbers
     assert(new ArrayIndexError(size_t.max, size_t.max-1).msg);
 }
@@ -836,12 +835,24 @@ extern (C)
         onArraySliceError(lower, upper, length, file[0 .. strlen(file)], line);
     }
 
+    /// ditto
+    void _d_arraybounds_slice(string file, uint line, size_t lower, size_t upper, size_t length)
+    {
+        onArraySliceError(lower, upper, length, file, line);
+    }
+
     /// Called when an out of range array index is accessed
     void _d_arraybounds_indexp(immutable(char*) file, uint line, size_t index, size_t length)
     {
         import core.stdc.string : strlen;
         onArrayIndexError(index, length, file[0 .. strlen(file)], line);
     }
+
+    /// ditto
+    void _d_arraybounds_index(string file, uint line, size_t index, size_t length)
+    {
+        onArrayIndexError(index, length, file, line);
+    }
 }
 
 // TLS storage shared for all errors, chaining might create circular reference
index b58ed51557fd238132360921cd3004b31434be2d..9c8223767e1cef77e543ffbaff3458d512d573c4 100644 (file)
@@ -9,44 +9,50 @@
 */
 module core.internal.array.construction;
 
+import core.internal.traits : Unqual;
+
 /**
  * Does array initialization (not assignment) from another array of the same element type.
  * Params:
- *  to = what array to initialize
  *  from = what data the array should be initialized with
  * Returns:
- *  The constructed `to`
+ *  The created and initialized array `to`
  * 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` until the implementation can be brought up to modern D expectations.
  */
-Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
+Tarr1 _d_arrayctor(Tarr1 : T1[], Tarr2 : T2[], T1, T2)(scope Tarr2 from) @trusted
+    if (is(Unqual!T1 == Unqual!T2))
 {
     pragma(inline, false);
-    import core.internal.traits : hasElaborateCopyConstructor, Unqual;
+    import core.internal.traits : hasElaborateCopyConstructor;
     import core.lifetime : copyEmplace;
     import core.stdc.string : memcpy;
-    debug(PRINTF) import core.stdc.stdio;
+    import core.stdc.stdint : uintptr_t;
+    debug(PRINTF) import core.stdc.stdio : printf;
+
+    debug(PRINTF) printf("_d_arrayctor(to = %p,%d, from = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, T1.tsize);
+
+    Tarr1 to = void;
+
+    void[] vFrom = (cast(void*)from.ptr)[0..from.length];
+    void[] vTo = (cast(void*)to.ptr)[0..to.length];
 
     // Force `enforceRawArraysConformable` to be `pure`
-    void enforceRawArraysConformable(const char[] action, const size_t elementSize, const void[] a1, const void[] a2, in bool allowOverlap = false) @trusted
+    void enforceRawArraysConformable(const char[] action, const size_t elementSize,
+        const void[] a1, const void[] a2) @trusted
     {
-        import core.internal.util.array : enforceRawArraysConformable;
+        import core.internal.util.array : enforceRawArraysConformableNogc;
 
-        alias Type = void function(const char[] action, const size_t elementSize, const void[] a1, const void[] a2, in bool allowOverlap = false) pure nothrow;
-        (cast(Type)&enforceRawArraysConformable)(action, elementSize, a1, a2, allowOverlap);
+        alias Type = void function(const char[] action, const size_t elementSize,
+            const void[] a1, const void[] a2, in bool allowOverlap = false) @nogc pure nothrow;
+        (cast(Type)&enforceRawArraysConformableNogc)(action, elementSize, a1, a2, false);
     }
 
-    debug(PRINTF) printf("_d_arrayctor(to = %p,%d, from = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, T.tsize);
-
-    auto element_size = T.sizeof;
-
-    void[] vFrom = (cast(void*)from.ptr)[0..from.length];
-    void[] vTo = (cast(void*)to.ptr)[0..to.length];
-    enforceRawArraysConformable("initialization", element_size, vFrom, vTo, false);
+    enforceRawArraysConformable("initialization", T1.sizeof, vFrom, vTo);
 
-    static if (hasElaborateCopyConstructor!T)
+    static if (hasElaborateCopyConstructor!T1)
     {
         size_t i;
         try
@@ -60,7 +66,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
             */
             while (i--)
             {
-                auto elem = cast(Unqual!T*)&to[i];
+                auto elem = cast(Unqual!T1*)&to[i];
                 destroy(*elem);
             }
 
@@ -70,7 +76,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
     else
     {
         // blit all elements at once
-        memcpy(cast(void*) to.ptr, from.ptr, to.length * T.sizeof);
+        memcpy(cast(void*) to.ptr, from.ptr, to.length * T1.sizeof);
     }
 
     return to;
@@ -88,7 +94,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
 
     S[4] arr1;
     S[4] arr2 = [S(0), S(1), S(2), S(3)];
-    _d_arrayctor(arr1[], arr2[]);
+    arr1 = _d_arrayctor!(typeof(arr1))(arr2[]);
 
     assert(counter == 4);
     assert(arr1 == arr2);
@@ -111,7 +117,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
 
     S[4] arr1;
     S[4] arr2 = [S(0), S(1), S(2), S(3)];
-    _d_arrayctor(arr1[], arr2[]);
+    arr1 = _d_arrayctor!(typeof(arr1))(arr2[]);
 
     assert(counter == 4);
     assert(arr1 == arr2);
@@ -137,7 +143,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
     {
         Throw[4] a;
         Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)];
-        _d_arrayctor(a[], b[]);
+        a = _d_arrayctor!(typeof(a))(b[]);
     }
     catch (Exception)
     {
@@ -162,7 +168,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
     {
         NoThrow[4] a;
         NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)];
-        _d_arrayctor(a[], b[]);
+        a = _d_arrayctor!(typeof(a))(b[]);
     }
     catch (Exception)
     {
@@ -186,7 +192,6 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted
 void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted
 {
     pragma(inline, false);
-    import core.internal.traits : Unqual;
     import core.lifetime : copyEmplace;
 
     size_t i;
@@ -269,7 +274,7 @@ void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted
     {
         Throw[4] a;
         Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)];
-        _d_arrayctor(a[], b[]);
+        a = _d_arrayctor!(typeof(a))(b[]);
     }
     catch (Exception)
     {
index 3036ea72d158ff09d03a60cd2ca29019834cc54c..5daab89a3876a777a7e798e0d8374d46f9e88a83 100644 (file)
@@ -104,7 +104,7 @@ version (DigitalMars)
                             pop RBX;
                             ret;
                         }
-                    }, SrcPtr, RetPtr));
+                    }, [SrcPtr, RetPtr]));
                 }
                 else
                 {
@@ -139,7 +139,7 @@ version (DigitalMars)
                         mov %0, src;
                         lock; cmpxchg [%0], %1;
                     }
-                }, SrcReg, ZeroReg, ResReg));
+                }, [SrcReg, ZeroReg, ResReg]));
             }
             else version (D_InlineAsm_X86_64)
             {
@@ -159,7 +159,7 @@ version (DigitalMars)
                         lock; cmpxchg [%0], %1;
                         ret;
                     }
-                }, SrcReg, ZeroReg, ResReg));
+                }, [SrcReg, ZeroReg, ResReg]));
             }
         }
         else
@@ -252,7 +252,7 @@ version (DigitalMars)
                     mov %0, dest;
                     lock; xadd[%0], %1;
                 }
-            }, DestReg, ValReg));
+            }, [DestReg, ValReg]));
         }
         else version (D_InlineAsm_X86_64)
         {
@@ -276,7 +276,7 @@ version (DigitalMars)
     ?2                mov %2, %1;
                     ret;
                 }
-            }, DestReg, ValReg, ResReg));
+            }, [DestReg, ValReg, ResReg]));
         }
         else
             static assert (false, "Unsupported architecture.");
@@ -305,7 +305,7 @@ version (DigitalMars)
                     mov %0, dest;
                     xchg [%0], %1;
                 }
-            }, DestReg, ValReg));
+            }, [DestReg, ValReg]));
         }
         else version (D_InlineAsm_X86_64)
         {
@@ -329,7 +329,7 @@ version (DigitalMars)
     ?2                mov %2, %1;
                     ret;
                 }
-            }, DestReg, ValReg, ResReg));
+            }, [DestReg, ValReg, ResReg]));
         }
         else
             static assert (false, "Unsupported architecture.");
@@ -362,7 +362,7 @@ version (DigitalMars)
                         setz AL;
                         pop %1;
                     }
-                }, DestAddr, CmpAddr, Val, Cmp));
+                }, [DestAddr, CmpAddr, Val, Cmp]));
             }
             else static if (T.sizeof == 8)
             {
@@ -421,7 +421,7 @@ version (DigitalMars)
                         xor AL, AL;
                         ret;
                     }
-                }, DestAddr, CmpAddr, Val, Res));
+                }, [DestAddr, CmpAddr, Val, Res]));
             }
             else
             {
@@ -500,7 +500,7 @@ version (DigitalMars)
                         lock; cmpxchg [%0], %2;
                         setz AL;
                     }
-                }, DestAddr, Cmp, Val));
+                }, [DestAddr, Cmp, Val]));
             }
             else static if (T.sizeof == 8)
             {
@@ -551,7 +551,7 @@ version (DigitalMars)
                         setz AL;
                         ret;
                     }
-                }, DestAddr, Cmp, Val, AXReg));
+                }, [DestAddr, Cmp, Val, AXReg]));
             }
             else
             {
@@ -1094,7 +1094,7 @@ template needsStoreBarrier( MemoryOrder ms )
 }
 
 // this is a helper to build asm blocks
-string simpleFormat(string format, string[] args...)
+string simpleFormat(string format, scope string[] args)
 {
     string result;
     outer: while (format.length)
index ac7600f8a03f21c9a177e9f737eb3817eb53e787..2c51b8641ae1373c585ff2f592424a998e05bf89 100644 (file)
@@ -191,7 +191,7 @@ private string miniFormat(V)(const scope ref V v)
         }
 
         // Fall back to a simple cast - we're violating the type system anyways
-        return miniFormat(__ctfe ? cast(const T) v : *cast(const T*) &v);
+        return miniFormat(*cast(const T*) &v);
     }
     // Format enum members using their name
     else static if (is(V BaseType == enum))
index 0c49955c6691216acdf3daa2aff690e627eaea06..a731d6f7ae429247dbc6ede8e2f6204fbdfc4192 100644 (file)
@@ -150,7 +150,11 @@ class ConservativeGC : GC
     static bool _inFinalizer;
     __gshared bool isPrecise = false;
 
-    // lock GC, throw InvalidMemoryOperationError on recursive locking during finalization
+    /*
+     * Lock the GC.
+     *
+     * Throws: InvalidMemoryOperationError on recursive locking during finalization.
+     */
     static void lockNR() @nogc nothrow
     {
         if (_inFinalizer)
@@ -158,6 +162,12 @@ class ConservativeGC : GC
         gcLock.lock();
     }
 
+    /*
+     * Initialize the GC based on command line configuration.
+     *
+     * Throws:
+     *  OutOfMemoryError if failed to initialize GC due to not enough memory.
+     */
     this()
     {
         //config is assumed to have already been initialized
@@ -194,6 +204,10 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Enables the GC if disable() was previously called. Must be called
+     * for each time disable was called in order to enable the GC again.
+     */
     void enable()
     {
         static void go(Gcx* gcx) nothrow
@@ -205,6 +219,9 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Disable the GC. The GC may still run if it deems necessary.
+     */
     void disable()
     {
         static void go(Gcx* gcx) nothrow
@@ -216,6 +233,13 @@ class ConservativeGC : GC
 
     debug (GC_RECURSIVE_LOCK) static bool lockedOnThisThread;
 
+    /**
+     * Run a function inside a lock/unlock set.
+     *
+     * Params:
+     *  func = The function to run.
+     *  args = The function arguments.
+     */
     auto runLocked(alias func, Args...)(auto ref Args args)
     {
         debug(PROFILE_API) immutable tm = (config.profile > 1 ? currTime.ticks : 0);
@@ -248,7 +272,17 @@ class ConservativeGC : GC
             return res;
     }
 
-
+    /**
+     * Run a function in an lock/unlock set that keeps track of
+     * how much time was spend inside this function (in ticks)
+     * and how many times this fuction was called.
+     *
+     * Params:
+     *  func = The function to run.
+     *  time = The variable keeping track of the time (in ticks).
+     *  count = The variable keeping track of how many times this fuction was called.
+     *  args = The function arguments.
+     */
     auto runLocked(alias func, alias time, alias count, Args...)(auto ref Args args)
     {
         debug(PROFILE_API) immutable tm = (config.profile > 1 ? currTime.ticks : 0);
@@ -287,6 +321,17 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Returns a bit field representing all block attributes set for the memory
+     * referenced by p.
+     *
+     * Params:
+     *  p = A pointer to the base of a valid memory block or to null.
+     *
+     * Returns:
+     *  A bit field containing any bits set for the memory block referenced by
+     *  p or zero on error.
+     */
     uint getAttr(void* p) nothrow
     {
         if (!p)
@@ -314,7 +359,20 @@ class ConservativeGC : GC
         return runLocked!(go, otherTime, numOthers)(gcx, p);
     }
 
-
+    /**
+     * Sets the specified bits for the memory references by p.
+     *
+     * If p was not allocated by the GC, points inside a block, or is null, no
+     * action will be taken.
+     *
+     * Params:
+     *  p = A pointer to the base of a valid memory block or to null.
+     *  mask = A bit field containing any bits to set for this memory block.
+     *
+     * Returns:
+     *  The result of a call to getAttr after the specified bits have been
+     *  set.
+     */
     uint setAttr(void* p, uint mask) nothrow
     {
         if (!p)
@@ -344,6 +402,20 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Clears the specified bits for the memory references by p.
+     *
+     * If p was not allocated by the GC, points inside a block, or is null, no
+     * action will be taken.
+     *
+     * Params:
+     *  p = A pointer to the base of a valid memory block or to null.
+     *  mask = A bit field containing any bits to clear for this memory block.
+     *
+     * Returns:
+     *  The result of a call to getAttr after the specified bits have been
+     *  cleared
+     */
     uint clrAttr(void* p, uint mask) nothrow
     {
         if (!p)
@@ -372,8 +444,21 @@ class ConservativeGC : GC
         return runLocked!(go, otherTime, numOthers)(gcx, p, mask);
     }
 
-
-    void *malloc(size_t size, uint bits, const TypeInfo ti) nothrow
+    /**
+     * Requests an aligned block of managed memory from the garbage collector.
+     *
+     * Params:
+     *  size = The desired allocation size in bytes.
+     *  bits = A bitmask of the attributes to set on this block.
+     *  ti = TypeInfo to describe the memory.
+     *
+     * Returns:
+     *  A reference to the allocated memory or null if no memory was requested.
+     *
+     * Throws:
+     *  OutOfMemoryError on allocation failure
+     */
+    void *malloc(size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
     {
         if (!size)
         {
@@ -394,7 +479,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation for malloc and calloc.
     //
     private void *mallocNoSync(size_t size, uint bits, ref size_t alloc_size, const TypeInfo ti = null) nothrow
     {
@@ -423,7 +508,6 @@ class ConservativeGC : GC
         return p;
     }
 
-
     BlkInfo qalloc( size_t size, uint bits, const scope TypeInfo ti) nothrow
     {
 
@@ -446,7 +530,22 @@ class ConservativeGC : GC
     }
 
 
-    void *calloc(size_t size, uint bits, const TypeInfo ti) nothrow
+    /**
+     * Requests an aligned block of managed memory from the garbage collector,
+     * which is initialized with all bits set to zero.
+     *
+     * Params:
+     *  size = The desired allocation size in bytes.
+     *  bits = A bitmask of the attributes to set on this block.
+     *  ti = TypeInfo to describe the memory.
+     *
+     * Returns:
+     *  A reference to the allocated memory or null if no memory was requested.
+     *
+     * Throws:
+     *  OutOfMemoryError on allocation failure.
+     */
+    void *calloc(size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
     {
         if (!size)
         {
@@ -466,8 +565,27 @@ class ConservativeGC : GC
         return p;
     }
 
-
-    void *realloc(void *p, size_t size, uint bits, const TypeInfo ti) nothrow
+    /**
+     * Request that the GC reallocate a block of memory, attempting to adjust
+     * the size in place if possible. If size is 0, the memory will be freed.
+     *
+     * If p was not allocated by the GC, points inside a block, or is null, no
+     * action will be taken.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *  size = The desired allocation size in bytes.
+     *  bits = A bitmask of the attributes to set on this block.
+     *  ti = TypeInfo to describe the memory.
+     *
+     * Returns:
+     *  A reference to the allocated memory on success or null if size is
+     *  zero.
+     *
+     * Throws:
+     *  OutOfMemoryError on allocation failure.
+     */
+    void *realloc(void *p, size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
     {
         size_t localAllocSize = void;
         auto oldp = p;
@@ -483,6 +601,8 @@ class ConservativeGC : GC
     }
 
 
+    //
+    // The implementation of realloc.
     //
     // bits will be set to the resulting bits of the new block
     //
@@ -624,7 +744,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of extend.
     //
     private size_t extendNoSync(void* p, size_t minsize, size_t maxsize, const TypeInfo ti = null) nothrow
     in
@@ -678,6 +798,16 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Requests that at least size bytes of memory be obtained from the operating
+     * system and marked as free.
+     *
+     * Params:
+     *  size = The desired size in bytes.
+     *
+     * Returns:
+     *  The actual number of bytes reserved or zero on error.
+     */
     size_t reserve(size_t size) nothrow
     {
         if (!size)
@@ -690,7 +820,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of reserve
     //
     private size_t reserveNoSync(size_t size) nothrow
     {
@@ -701,7 +831,16 @@ class ConservativeGC : GC
     }
 
 
-    void free(void *p) nothrow @nogc
+    /**
+     * Deallocates the memory referenced by p.
+     *
+     * If p was not allocated by the GC, points inside a block, is null, or
+     * if free is called from a finalizer, no action will be taken.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     */
+    void free(void *p) nothrow
     {
         if (!p || _inFinalizer)
         {
@@ -713,7 +852,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of free.
     //
     private void freeNoSync(void *p) nothrow @nogc
     {
@@ -792,7 +931,18 @@ class ConservativeGC : GC
     }
 
 
-    void* addrOf(void *p) nothrow @nogc
+    /**
+     * Determine the base address of the block containing p.  If p is not a gc
+     * allocated pointer, return null.
+     *
+     * Params:
+     *  p = A pointer to the root or the interior of a valid memory block or to
+     *      null.
+     *
+     * Returns:
+     *  The base address of the memory block referenced by p or null on error.
+     */
+    void* addrOf(void *p) nothrow
     {
         if (!p)
         {
@@ -804,7 +954,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of addrOf.
     //
     void* addrOfNoSync(void *p) nothrow @nogc
     {
@@ -820,7 +970,17 @@ class ConservativeGC : GC
     }
 
 
-    size_t sizeOf(void *p) nothrow @nogc
+    /**
+     * Determine the allocated size of pointer p.  If p is an interior pointer
+     * or not a gc allocated pointer, return 0.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *
+     * Returns:
+     *  The size in bytes of the memory block referenced by p or zero on error.
+     */
+    size_t sizeOf(void *p) nothrow
     {
         if (!p)
         {
@@ -832,7 +992,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of sizeOf.
     //
     private size_t sizeOfNoSync(void *p) nothrow @nogc
     {
@@ -852,6 +1012,18 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Determine the base address of the block containing p.  If p is not a gc
+     * allocated pointer, return null.
+     *
+     * Params:
+     *  p = A pointer to the root or the interior of a valid memory block or to
+     *      null.
+     *
+     * Returns:
+     *  Information regarding the memory block referenced by p or BlkInfo.init
+     *  on error.
+     */
     BlkInfo query(void *p) nothrow
     {
         if (!p)
@@ -864,7 +1036,7 @@ class ConservativeGC : GC
     }
 
     //
-    //
+    // Implementation of query
     //
     BlkInfo queryNoSync(void *p) nothrow
     {
@@ -884,10 +1056,14 @@ class ConservativeGC : GC
 
 
     /**
-     * Verify that pointer p:
-     *  1) belongs to this memory pool
-     *  2) points to the start of an allocated piece of memory
-     *  3) is not on a free list
+     * Performs certain checks on a pointer. These checks will cause asserts to
+     * fail unless the following conditions are met:
+     *  1) The poiinter belongs to this memory pool.
+     *  2) The pointer points to the start of an allocated piece of memory.
+     *  3) The pointer is not on a free list.
+     *
+     * Params:
+     *  p = The pointer to be checked.
      */
     void check(void *p) nothrow
     {
@@ -901,7 +1077,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of check
     //
     private void checkNoSync(void *p) nothrow
     {
@@ -939,6 +1115,12 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Add p to list of roots. If p is null, no operation is performed.
+     *
+     * Params:
+     *  p = A pointer into a GC-managed memory block or null.
+     */
     void addRoot(void *p) nothrow @nogc
     {
         if (!p)
@@ -950,6 +1132,13 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Remove p from list of roots. If p is null or is not a value
+     * previously passed to addRoot() then no operation is performed.
+     *
+     * Params:
+     *  p = A pointer into a GC-managed memory block or null.
+     */
     void removeRoot(void *p) nothrow @nogc
     {
         if (!p)
@@ -960,13 +1149,23 @@ class ConservativeGC : GC
         gcx.removeRoot(p);
     }
 
-
+    /**
+     * Returns an iterator allowing roots to be traversed via a foreach loop.
+     */
     @property RootIterator rootIter() @nogc
     {
         return &gcx.rootsApply;
     }
 
 
+    /**
+     * Add range to scan for roots. If p is null or sz is 0, no operation is performed.
+     *
+     * Params:
+     *  p  = A pointer to a valid memory address or to null.
+     *  sz = The size in bytes of the block to add.
+     *  ti = TypeInfo to describe the memory.
+     */
     void addRange(void *p, size_t sz, const TypeInfo ti = null) nothrow @nogc
     {
         if (!p || !sz)
@@ -978,6 +1177,14 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Remove range from list of ranges. If p is null or does not represent
+     * a value previously passed to addRange() then no operation is
+     * performed.
+     *
+     * Params:
+     *  p  = A pointer to a valid memory address or to null.
+     */
     void removeRange(void *p) nothrow @nogc
     {
         if (!p)
@@ -989,12 +1196,21 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Returns an iterator allowing ranges to be traversed via a foreach loop.
+     */
     @property RangeIterator rangeIter() @nogc
     {
         return &gcx.rangesApply;
     }
 
 
+    /**
+     * Run all finalizers in the code segment.
+     *
+     * Params:
+     *  segment = address range of a code segment
+     */
     void runFinalizers(const scope void[] segment) nothrow
     {
         static void go(Gcx* gcx, const scope void[] segment) nothrow
@@ -1024,8 +1240,10 @@ class ConservativeGC : GC
 
 
     /**
-     * Do full garbage collection.
-     * Return number of pages free'd.
+     * Begins a full collection, scanning all stack segments for roots.
+     *
+     * Returns:
+     *  The number of pages freed.
      */
     size_t fullCollect() nothrow
     {
@@ -1054,7 +1272,7 @@ class ConservativeGC : GC
 
 
     /**
-     * do full garbage collection ignoring roots
+     * Begins a full collection while ignoring all stack segments for roots.
      */
     void fullCollectNoStack() nothrow
     {
@@ -1068,6 +1286,9 @@ class ConservativeGC : GC
     }
 
 
+    /**
+     * Minimize free space usage.
+     */
     void minimize() nothrow
     {
         static void go(Gcx* gcx) nothrow
@@ -1109,7 +1330,7 @@ class ConservativeGC : GC
 
 
     //
-    //
+    // Implementation of getStats
     //
     private void getStatsNoSync(out core.memory.GC.Stats stats) nothrow
     {
index ca4cbe2b1c8ddf4094ae9576c4128d2f429d7d99..64f12033c95a185a298b788459348aab423797fa 100644 (file)
@@ -213,46 +213,38 @@ else
    Returns:
        true if memory is scarce
 */
-// TOOD: get virtual mem sizes and current usage from OS
+// TODO: get virtual mem sizes and current usage from OS
 // TODO: compare current RSS and avail. physical memory
-version (Windows)
+bool isLowOnMem(size_t mapped) nothrow @nogc
 {
-    bool isLowOnMem(size_t mapped) nothrow @nogc
+    version (Windows)
     {
-        version (D_LP64)
+        import core.sys.windows.winbase : GlobalMemoryStatusEx, MEMORYSTATUSEX;
+
+        MEMORYSTATUSEX stat;
+        stat.dwLength = stat.sizeof;
+        const success = GlobalMemoryStatusEx(&stat) != 0;
+        assert(success, "GlobalMemoryStatusEx() failed");
+        if (!success)
             return false;
-        else
-        {
-            import core.sys.windows.winbase : GlobalMemoryStatus, MEMORYSTATUS;
-            MEMORYSTATUS stat;
-            GlobalMemoryStatus(&stat);
-            // Less than 5 % of virtual address space available
-            return stat.dwAvailVirtual < stat.dwTotalVirtual / 20;
-        }
+
+        // dwMemoryLoad is the 'approximate percentage of physical memory that is in use'
+        // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex
+        const percentPhysicalRAM = stat.ullTotalPhys / 100;
+        return (stat.dwMemoryLoad >= 95 && mapped > percentPhysicalRAM)
+            || (stat.dwMemoryLoad >= 90 && mapped > 10 * percentPhysicalRAM);
     }
-}
-else version (Darwin)
-{
-    bool isLowOnMem(size_t mapped) nothrow @nogc
+    else
     {
         enum GB = 2 ^^ 30;
         version (D_LP64)
             return false;
-        else
+        else version (Darwin)
         {
             // 80 % of available 4GB is used for GC (excluding malloc and mmap)
             enum size_t limit = 4UL * GB * 8 / 10;
             return mapped > limit;
         }
-    }
-}
-else
-{
-    bool isLowOnMem(size_t mapped) nothrow @nogc
-    {
-        enum GB = 2 ^^ 30;
-        version (D_LP64)
-            return false;
         else
         {
             // be conservative and assume 3GB
index e999f0cada945fc5b3e6e73162cb9fecf49f9567..ef9f1e525c0022ca9cbb4b98b4182243b6443099 100644 (file)
@@ -646,13 +646,8 @@ size_t hashOf(T)(T aa) if (!is(T == enum) && __traits(isAssociativeArray, T))
     size_t h = 0;
 
     // The computed hash is independent of the foreach traversal order.
-    foreach (key, ref val; aa)
-    {
-        size_t[2] hpair;
-        hpair[0] = key.hashOf();
-        hpair[1] = val.hashOf();
-        h += hpair.hashOf();
-    }
+    foreach (ref key, ref val; aa)
+        h += hashOf(hashOf(val), hashOf(key));
     return h;
 }
 
index 4e5105d82da194693779d80c612594797fcb7f41..99204432374e2d5329955062940db697f94d64dd 100644 (file)
@@ -4,7 +4,7 @@
 * Copyright: Copyright Digital Mars 2017
 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
 *
-* Source: $(DRUNTIMESRC src/core/internal/parseoptions.d)
+* Source: $(DRUNTIMESRC core/internal/parseoptions.d)
 */
 
 module core.internal.parseoptions;
index 1856eb8b881e16244d1b5a8f3e767f106c439bf7..60d9be3ac9bb1c7356af16c05378c07ff13f5f16 100644 (file)
@@ -14,7 +14,7 @@ template Fields(T)
 {
     static if (is(T == struct) || is(T == union))
         alias Fields = typeof(T.tupleof[0 .. $ - __traits(isNested, T)]);
-    else static if (is(T == class))
+    else static if (is(T == class) || is(T == interface))
         alias Fields = typeof(T.tupleof);
     else
         alias Fields = AliasSeq!T;
@@ -326,7 +326,7 @@ template hasElaborateAssign(S)
 template hasIndirections(T)
 {
     static if (is(T == struct) || is(T == union))
-        enum hasIndirections = anySatisfy!(.hasIndirections, Fields!T);
+        enum hasIndirections = anySatisfy!(.hasIndirections, typeof(T.tupleof));
     else static if (is(T == E[N], E, size_t N))
         enum hasIndirections = T.sizeof && is(E == void) ? true : hasIndirections!(BaseElemOf!E);
     else static if (isFunctionPointer!T)
@@ -367,6 +367,10 @@ unittest
     static assert( hasUnsharedIndirections!(Foo*));
     static assert(!hasUnsharedIndirections!(shared(Foo)*));
     static assert(!hasUnsharedIndirections!(immutable(Foo)*));
+
+    int local;
+    struct HasContextPointer { int opCall() { return ++local; } }
+    static assert(hasIndirections!HasContextPointer);
 }
 
 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
index bc9b72c1474d2408eabd93a0c9843b5370dfece4..6136cfef17d2f20a1d2d268df3d60030907ba8ee 100644 (file)
@@ -13,6 +13,17 @@ import core.internal.string;
 import core.stdc.stdint;
 
 
+// TLS storage shared for all error messages.
+private align(2 * size_t.sizeof) char[256] _store;
+
+private char[] errorMessage(Args...)(scope const(char*) format,
+    const char[] action, Args args) @trusted
+{
+    import core.stdc.stdio : snprintf;
+    snprintf(&_store[0], _store.sizeof, format, &action[0], args);
+    return _store;
+}
+
 @safe /* pure dmd @@@BUG11461@@@ */ nothrow:
 
 void enforceTypedArraysConformable(T)(const char[] action,
@@ -65,6 +76,44 @@ private void _enforceNoOverlap(const char[] action,
     assert(0, msg);
 }
 
+void enforceTypedArraysConformableNogc(T)(const char[] action,
+    const T[] a1, const T[] a2, const bool allowOverlap = false)
+{
+    _enforceSameLengthNogc(action, a1.length, a2.length);
+    if (!allowOverlap)
+        _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
+}
+
+void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize,
+    const void[] a1, const void[] a2, const bool allowOverlap = false)
+{
+    _enforceSameLengthNogc(action, a1.length, a2.length);
+    if (!allowOverlap)
+        _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), elementSize * a1.length);
+}
+
+private void _enforceNoOverlapNogc(const ref char[] action,
+    uintptr_t ptr1, uintptr_t ptr2, const size_t bytes)
+{
+    const d = ptr1 > ptr2 ? ptr1 - ptr2 : ptr2 - ptr1;
+    if (d >= bytes)
+        return;
+    const overlappedBytes = bytes - d;
+
+    assert(0, errorMessage("Overlapping arrays in %s: %zu byte(s) overlap of %zu",
+        action, overlappedBytes, bytes));
+}
+
+private void _enforceSameLengthNogc(const ref char[] action,
+    const size_t length1, const size_t length2)
+{
+    if (length1 == length2)
+        return;
+
+    assert(0, errorMessage("Array lengths don't match for %s: %zu != %zu",
+        action, length1, length2));
+}
+
 private uintptr_t arrayToPtr(const void[] array) @trusted
 {
     // Ok because the user will never dereference the pointer
index fc47b1d9394076e2d6f93c27cd4b69fbb2efe68a..d93b891226ce0b403ebb85dba57b3589f7c42143 100644 (file)
@@ -2124,7 +2124,9 @@ private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
                 () @trusted { memset(&source, 0, sz); }();
             else
             {
-                auto init = typeid(T).initializer();
+                import core.internal.lifetime : emplaceInitializer;
+                ubyte[T.sizeof] init = void;
+                emplaceInitializer(*(() @trusted { return cast(T*)init.ptr; }()));
                 () @trusted { memcpy(&source, init.ptr, sz); }();
             }
         }
index bfb72e07b056ff127d87730ef604cac724b37c07..b08ec52a246fd83db056f89347a0dbce1aef7746 100644 (file)
@@ -848,6 +848,7 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf
         version (linux) enum enableDwarf = true;
         else version (FreeBSD) enum enableDwarf = true;
         else version (DragonFlyBSD) enum enableDwarf = true;
+        else version (OpenBSD) enum enableDwarf = true;
         else version (Darwin) enum enableDwarf = true;
         else enum enableDwarf = false;
 
index 35e81a254142968e30b3ecc40265593f13eaa09d..2f11a663eb540edbf3d974d54d7d5bb9191441a9 100644 (file)
@@ -9,7 +9,7 @@
  *    (See accompanying file LICENSE)
  * Authors:   Sean Kelly
  * Standards: ISO/IEC 9899:1999 (E)
- * Source: $(DRUNTIMESRC src/core/stdc/_stdlib.d)
+ * Source: $(DRUNTIMESRC core/stdc/_stdlib.d)
  */
 
 module core.stdc.stdlib;
index 89ef6671e2fae10bdc392892e7c3d1d7a268f7ab..07c5bdbe360660d14e099a8b12a3b1abba798460 100644 (file)
@@ -86,7 +86,7 @@ class ReadWriteMutex
      * Throws:
      *  SyncError on error.
      */
-    this( Policy policy = Policy.PREFER_WRITERS )
+    this( Policy policy = Policy.PREFER_WRITERS ) @safe nothrow
     {
         m_commonMutex = new Mutex;
         if ( !m_commonMutex )
@@ -105,6 +105,26 @@ class ReadWriteMutex
         m_writer = new Writer;
     }
 
+    /// ditto
+    shared this( Policy policy = Policy.PREFER_WRITERS ) @safe nothrow
+    {
+        m_commonMutex = new shared Mutex;
+        if ( !m_commonMutex )
+            throw new SyncError( "Unable to initialize mutex" );
+
+        m_readerQueue = new shared Condition( m_commonMutex );
+        if ( !m_readerQueue )
+            throw new SyncError( "Unable to initialize mutex" );
+
+        m_writerQueue = new shared Condition( m_commonMutex );
+        if ( !m_writerQueue )
+            throw new SyncError( "Unable to initialize mutex" );
+
+        m_policy = policy;
+        m_reader = new shared Reader;
+        m_writer = new shared Writer;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // General Properties
     ////////////////////////////////////////////////////////////////////////////
@@ -116,11 +136,16 @@ class ReadWriteMutex
      * Returns:
      *  The policy used by this mutex.
      */
-    @property Policy policy()
+    @property Policy policy() @safe nothrow
     {
         return m_policy;
     }
 
+    ///ditto
+    @property Policy policy() shared @safe nothrow
+    {
+        return m_policy;
+    }
 
     ////////////////////////////////////////////////////////////////////////////
     // Reader/Writer Handles
@@ -133,11 +158,16 @@ class ReadWriteMutex
      * Returns:
      *  A reader sub-mutex.
      */
-    @property Reader reader()
+    @property Reader reader() @safe nothrow
     {
         return m_reader;
     }
 
+    ///ditto
+    @property shared(Reader) reader() shared @safe nothrow
+    {
+        return m_reader;
+    }
 
     /**
      * Gets an object representing the writer lock for the associated mutex.
@@ -145,7 +175,13 @@ class ReadWriteMutex
      * Returns:
      *  A writer sub-mutex.
      */
-    @property Writer writer()
+    @property Writer writer() @safe nothrow
+    {
+        return m_writer;
+    }
+
+    ///ditto
+    @property shared(Writer) writer() shared @safe nothrow
     {
         return m_writer;
     }
@@ -166,13 +202,13 @@ class ReadWriteMutex
         /**
          * Initializes a read/write mutex reader proxy object.
          */
-        this()
+        this(this Q)() @trusted nothrow
+            if (is(Q == Reader) || is(Q == shared Reader))
         {
             m_proxy.link = this;
-            this.__monitor = &m_proxy;
+            this.__monitor = cast(void*) &m_proxy;
         }
 
-
         /**
          * Acquires a read lock on the enclosing mutex.
          */
@@ -189,6 +225,19 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted void lock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                ++(cast()m_numQueuedReaders);
+                scope(exit) --(cast()m_numQueuedReaders);
+
+                while ( shouldQueueReader )
+                    m_readerQueue.wait();
+                ++(cast()m_numActiveReaders);
+            }
+        }
 
         /**
          * Releases a read lock on the enclosing mutex.
@@ -205,6 +254,18 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted void unlock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                if ( --(cast()m_numActiveReaders) < 1 )
+                {
+                    if ( m_numQueuedWriters > 0 )
+                        m_writerQueue.notify();
+                }
+            }
+        }
 
         /**
          * Attempts to acquire a read lock on the enclosing mutex.  If one can
@@ -214,7 +275,7 @@ class ReadWriteMutex
          * Returns:
          *  true if the lock was acquired and false if not.
          */
-        bool tryLock()
+        @trusted bool tryLock()
         {
             synchronized( m_commonMutex )
             {
@@ -225,6 +286,18 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted bool tryLock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                if ( shouldQueueReader )
+                    return false;
+                ++(cast()m_numActiveReaders);
+                return true;
+            }
+        }
+
         /**
          * Attempts to acquire a read lock on the enclosing mutex. If one can
          * be obtained without blocking, the lock is acquired and true is
@@ -237,7 +310,7 @@ class ReadWriteMutex
          * Returns:
          *  true if the lock was acquired and false if not.
          */
-        bool tryLock(Duration timeout)
+        @trusted bool tryLock(Duration timeout)
         {
             synchronized( m_commonMutex )
             {
@@ -270,9 +343,34 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted bool tryLock(Duration timeout) shared
+        {
+            const initialTime = MonoTime.currTime;
+            synchronized( m_commonMutex )
+            {
+                ++(cast()m_numQueuedReaders);
+                scope(exit) --(cast()m_numQueuedReaders);
+
+                while (shouldQueueReader)
+                {
+                    const timeElapsed = MonoTime.currTime - initialTime;
+                    if (timeElapsed >= timeout)
+                        return false;
+                    auto nextWait = timeout - timeElapsed;
+                    // Avoid problems calling wait(Duration) with huge arguments.
+                    enum maxWaitPerCall = dur!"hours"(24 * 365);
+                    m_readerQueue.wait(nextWait < maxWaitPerCall ? nextWait : maxWaitPerCall);
+                }
+                ++(cast()m_numActiveReaders);
+                return true;
+            }
+        }
+
 
     private:
-        @property bool shouldQueueReader()
+        @property bool shouldQueueReader(this Q)() nothrow @safe @nogc
+            if (is(Q == Reader) || is(Q == shared Reader))
         {
             if ( m_numActiveWriters > 0 )
                 return true;
@@ -314,10 +412,11 @@ class ReadWriteMutex
         /**
          * Initializes a read/write mutex writer proxy object.
          */
-        this()
+        this(this Q)() @trusted nothrow
+            if (is(Q == Writer) || is(Q == shared Writer))
         {
             m_proxy.link = this;
-            this.__monitor = &m_proxy;
+            this.__monitor = cast(void*) &m_proxy;
         }
 
 
@@ -337,6 +436,20 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted void lock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                ++(cast()m_numQueuedWriters);
+                scope(exit) --(cast()m_numQueuedWriters);
+
+                while ( shouldQueueWriter )
+                    m_writerQueue.wait();
+                ++(cast()m_numActiveWriters);
+            }
+        }
+
 
         /**
          * Releases a write lock on the enclosing mutex.
@@ -366,6 +479,32 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted void unlock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                if ( --(cast()m_numActiveWriters) < 1 )
+                {
+                    switch ( m_policy )
+                    {
+                    default:
+                    case Policy.PREFER_READERS:
+                        if ( m_numQueuedReaders > 0 )
+                            m_readerQueue.notifyAll();
+                        else if ( m_numQueuedWriters > 0 )
+                            m_writerQueue.notify();
+                        break;
+                    case Policy.PREFER_WRITERS:
+                        if ( m_numQueuedWriters > 0 )
+                            m_writerQueue.notify();
+                        else if ( m_numQueuedReaders > 0 )
+                            m_readerQueue.notifyAll();
+                    }
+                }
+            }
+        }
+
 
         /**
          * Attempts to acquire a write lock on the enclosing mutex.  If one can
@@ -375,7 +514,7 @@ class ReadWriteMutex
          * Returns:
          *  true if the lock was acquired and false if not.
          */
-        bool tryLock()
+        @trusted bool tryLock()
         {
             synchronized( m_commonMutex )
             {
@@ -386,6 +525,18 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted bool tryLock() shared
+        {
+            synchronized( m_commonMutex )
+            {
+                if ( shouldQueueWriter )
+                    return false;
+                ++(cast()m_numActiveWriters);
+                return true;
+            }
+        }
+
         /**
          * Attempts to acquire a write lock on the enclosing mutex. If one can
          * be obtained without blocking, the lock is acquired and true is
@@ -398,7 +549,7 @@ class ReadWriteMutex
          * Returns:
          *  true if the lock was acquired and false if not.
          */
-        bool tryLock(Duration timeout)
+        @trusted bool tryLock(Duration timeout)
         {
             synchronized( m_commonMutex )
             {
@@ -431,8 +582,33 @@ class ReadWriteMutex
             }
         }
 
+        /// ditto
+        @trusted bool tryLock(Duration timeout) shared
+        {
+            const initialTime = MonoTime.currTime;
+            synchronized( m_commonMutex )
+            {
+                ++(cast()m_numQueuedWriters);
+                scope(exit) --(cast()m_numQueuedWriters);
+
+                while (shouldQueueWriter)
+                {
+                    const timeElapsed = MonoTime.currTime - initialTime;
+                    if (timeElapsed >= timeout)
+                        return false;
+                    auto nextWait = timeout - timeElapsed;
+                    // Avoid problems calling wait(Duration) with huge arguments.
+                    enum maxWaitPerCall = dur!"hours"(24 * 365);
+                    m_writerQueue.wait(nextWait < maxWaitPerCall ? nextWait : maxWaitPerCall);
+                }
+                ++(cast()m_numActiveWriters);
+                return true;
+            }
+        }
+
     private:
-        @property bool shouldQueueWriter()
+        @property bool shouldQueueWriter(this Q)()
+            if (is(Q == Writer) || is(Q == shared Writer))
         {
             if ( m_numActiveWriters > 0 ||
                 m_numActiveReaders > 0 )
@@ -691,3 +867,215 @@ unittest
         otherThread.join;
     }
 }
+
+unittest
+{
+    import core.atomic, core.thread, core.sync.semaphore;
+
+    static void runTest(ReadWriteMutex.Policy policy)
+    {
+        shared scope mutex = new shared ReadWriteMutex(policy);
+        scope rdSemA = new Semaphore, rdSemB = new Semaphore,
+              wrSemA = new Semaphore, wrSemB = new Semaphore;
+        shared size_t numReaders, numWriters;
+
+        void readerFn()
+        {
+            synchronized (mutex.reader)
+            {
+                atomicOp!"+="(numReaders, 1);
+                rdSemA.notify();
+                rdSemB.wait();
+                atomicOp!"-="(numReaders, 1);
+            }
+        }
+
+        void writerFn()
+        {
+            synchronized (mutex.writer)
+            {
+                atomicOp!"+="(numWriters, 1);
+                wrSemA.notify();
+                wrSemB.wait();
+                atomicOp!"-="(numWriters, 1);
+            }
+        }
+
+        void waitQueued(size_t queuedReaders, size_t queuedWriters)
+        {
+            for (;;)
+            {
+                synchronized (mutex.m_commonMutex)
+                {
+                    if (mutex.m_numQueuedReaders == queuedReaders &&
+                        mutex.m_numQueuedWriters == queuedWriters)
+                        break;
+                }
+                Thread.yield();
+            }
+        }
+
+        scope group = new ThreadGroup;
+
+        // 2 simultaneous readers
+        group.create(&readerFn); group.create(&readerFn);
+        rdSemA.wait(); rdSemA.wait();
+        assert(numReaders == 2);
+        rdSemB.notify(); rdSemB.notify();
+        group.joinAll();
+        assert(numReaders == 0);
+        foreach (t; group) group.remove(t);
+
+        // 1 writer at a time
+        group.create(&writerFn); group.create(&writerFn);
+        wrSemA.wait();
+        assert(!wrSemA.tryWait());
+        assert(numWriters == 1);
+        wrSemB.notify();
+        wrSemA.wait();
+        assert(numWriters == 1);
+        wrSemB.notify();
+        group.joinAll();
+        assert(numWriters == 0);
+        foreach (t; group) group.remove(t);
+
+        // reader and writer are mutually exclusive
+        group.create(&readerFn);
+        rdSemA.wait();
+        group.create(&writerFn);
+        waitQueued(0, 1);
+        assert(!wrSemA.tryWait());
+        assert(numReaders == 1 && numWriters == 0);
+        rdSemB.notify();
+        wrSemA.wait();
+        assert(numReaders == 0 && numWriters == 1);
+        wrSemB.notify();
+        group.joinAll();
+        assert(numReaders == 0 && numWriters == 0);
+        foreach (t; group) group.remove(t);
+
+        // writer and reader are mutually exclusive
+        group.create(&writerFn);
+        wrSemA.wait();
+        group.create(&readerFn);
+        waitQueued(1, 0);
+        assert(!rdSemA.tryWait());
+        assert(numReaders == 0 && numWriters == 1);
+        wrSemB.notify();
+        rdSemA.wait();
+        assert(numReaders == 1 && numWriters == 0);
+        rdSemB.notify();
+        group.joinAll();
+        assert(numReaders == 0 && numWriters == 0);
+        foreach (t; group) group.remove(t);
+
+        // policy determines whether queued reader or writers progress first
+        group.create(&writerFn);
+        wrSemA.wait();
+        group.create(&readerFn);
+        group.create(&writerFn);
+        waitQueued(1, 1);
+        assert(numReaders == 0 && numWriters == 1);
+        wrSemB.notify();
+
+        if (policy == ReadWriteMutex.Policy.PREFER_READERS)
+        {
+            rdSemA.wait();
+            assert(numReaders == 1 && numWriters == 0);
+            rdSemB.notify();
+            wrSemA.wait();
+            assert(numReaders == 0 && numWriters == 1);
+            wrSemB.notify();
+        }
+        else if (policy == ReadWriteMutex.Policy.PREFER_WRITERS)
+        {
+            wrSemA.wait();
+            assert(numReaders == 0 && numWriters == 1);
+            wrSemB.notify();
+            rdSemA.wait();
+            assert(numReaders == 1 && numWriters == 0);
+            rdSemB.notify();
+        }
+        group.joinAll();
+        assert(numReaders == 0 && numWriters == 0);
+        foreach (t; group) group.remove(t);
+    }
+    runTest(ReadWriteMutex.Policy.PREFER_READERS);
+    runTest(ReadWriteMutex.Policy.PREFER_WRITERS);
+}
+
+unittest
+{
+    import core.atomic, core.thread;
+    shared static ReadWriteMutex rwmutex;
+    shared static bool threadTriedOnceToGetLock;
+    shared static bool threadFinallyGotLock;
+
+    rwmutex = new shared ReadWriteMutex();
+    atomicFence;
+    const maxTimeAllowedForTest = dur!"seconds"(20);
+    // Test ReadWriteMutex.Reader.tryLock(Duration).
+    {
+        static void testReaderTryLock()
+        {
+            assert(!rwmutex.reader.tryLock(Duration.min));
+            threadTriedOnceToGetLock.atomicStore(true);
+            assert(rwmutex.reader.tryLock(Duration.max));
+            threadFinallyGotLock.atomicStore(true);
+            rwmutex.reader.unlock;
+        }
+        assert(rwmutex.writer.tryLock(Duration.zero), "should have been able to obtain lock without blocking");
+        auto otherThread = new Thread(&testReaderTryLock).start;
+        const failIfThisTimeisReached = MonoTime.currTime + maxTimeAllowedForTest;
+        Thread.yield;
+        // We started otherThread with the writer lock held so otherThread's
+        // first rwlock.reader.tryLock with timeout Duration.min should fail.
+        while (!threadTriedOnceToGetLock.atomicLoad)
+        {
+            assert(MonoTime.currTime < failIfThisTimeisReached, "timed out");
+            Thread.yield;
+        }
+        rwmutex.writer.unlock;
+        // Soon after we release the writer lock otherThread's second
+        // rwlock.reader.tryLock with timeout Duration.max should succeed.
+        while (!threadFinallyGotLock.atomicLoad)
+        {
+            assert(MonoTime.currTime < failIfThisTimeisReached, "timed out");
+            Thread.yield;
+        }
+        otherThread.join;
+    }
+    threadTriedOnceToGetLock.atomicStore(false); // Reset.
+    threadFinallyGotLock.atomicStore(false); // Reset.
+    // Test ReadWriteMutex.Writer.tryLock(Duration).
+    {
+        static void testWriterTryLock()
+        {
+            assert(!rwmutex.writer.tryLock(Duration.min));
+            threadTriedOnceToGetLock.atomicStore(true);
+            assert(rwmutex.writer.tryLock(Duration.max));
+            threadFinallyGotLock.atomicStore(true);
+            rwmutex.writer.unlock;
+        }
+        assert(rwmutex.reader.tryLock(Duration.zero), "should have been able to obtain lock without blocking");
+        auto otherThread = new Thread(&testWriterTryLock).start;
+        const failIfThisTimeisReached = MonoTime.currTime + maxTimeAllowedForTest;
+        Thread.yield;
+        // We started otherThread with the reader lock held so otherThread's
+        // first rwlock.writer.tryLock with timeout Duration.min should fail.
+        while (!threadTriedOnceToGetLock.atomicLoad)
+        {
+            assert(MonoTime.currTime < failIfThisTimeisReached, "timed out");
+            Thread.yield;
+        }
+        rwmutex.reader.unlock;
+        // Soon after we release the reader lock otherThread's second
+        // rwlock.writer.tryLock with timeout Duration.max should succeed.
+        while (!threadFinallyGotLock.atomicLoad)
+        {
+            assert(MonoTime.currTime < failIfThisTimeisReached, "timed out");
+            Thread.yield;
+        }
+        otherThread.join;
+    }
+}
index 4eda066b293eedac2199ce4044ed9fd9860a614a..5e3129e2422291f1dc758724f293b6b03be1bf66 100644 (file)
@@ -13,7 +13,9 @@ public import core.sys.posix.config;
 // __FreeBSD_version numbers are documented in the Porter's Handbook.
 // NOTE: When adding newer versions of FreeBSD, verify all current versioned
 // bindings are still compatible with the release.
-     version (FreeBSD_12) enum __FreeBSD_version = 1202000;
+
+     version (FreeBSD_13) enum __FreeBSD_version = 1300000;
+else version (FreeBSD_12) enum __FreeBSD_version = 1202000;
 else version (FreeBSD_11) enum __FreeBSD_version = 1104000;
 else version (FreeBSD_10) enum __FreeBSD_version = 1004000;
 else version (FreeBSD_9)  enum __FreeBSD_version = 903000;
index 5faa7564d1b06bbe73837357c8f16a4d38bc5e9f..c55250669691a486db57c3442368f48cc6732455 100644 (file)
@@ -154,39 +154,42 @@ enum {
     S_XFLAG_HASATTR = 0x80000000, /// no DIFLAG for this
 }
 
-enum BLKROSET = _IO(0x12, 93); /// set device read-only
-enum BLKROGET = _IO(0x12, 94); /// get read-only status
-enum BLKRRPART = _IO(0x12, 95); /// re-read partition table
-enum BLKGETSIZE = _IO(0x12, 96); /// return device size
-enum BLKFLSBUF = _IO(0x12, 97); /// flush buffer cache
-enum BLKRASET = _IO(0x12, 98); /// set read ahead for block device
-enum BLKRAGET = _IO(0x12, 99); /// get current read ahead setting
-enum BLKFRASET = _IO(0x12, 100); /// set filesystem
-enum BLKFRAGET = _IO(0x12, 101); /// get filesystem
-enum BLKSECTSET = _IO(0x12, 102); /// set max sectors per request
-enum BLKSECTGET = _IO(0x12, 103); /// get max sectors per request
-enum BLKSSZGET = _IO(0x12, 104); /// get block device sector size
+static if (__traits(compiles, _IO(1, 2)))
+{
+    enum BLKROSET = _IO(0x12, 93); /// set device read-only
+    enum BLKROGET = _IO(0x12, 94); /// get read-only status
+    enum BLKRRPART = _IO(0x12, 95); /// re-read partition table
+    enum BLKGETSIZE = _IO(0x12, 96); /// return device size
+    enum BLKFLSBUF = _IO(0x12, 97); /// flush buffer cache
+    enum BLKRASET = _IO(0x12, 98); /// set read ahead for block device
+    enum BLKRAGET = _IO(0x12, 99); /// get current read ahead setting
+    enum BLKFRASET = _IO(0x12, 100); /// set filesystem
+    enum BLKFRAGET = _IO(0x12, 101); /// get filesystem
+    enum BLKSECTSET = _IO(0x12, 102); /// set max sectors per request
+    enum BLKSECTGET = _IO(0x12, 103); /// get max sectors per request
+    enum BLKSSZGET = _IO(0x12, 104); /// get block device sector size
 
 
-enum BLKBSZGET = _IOR!size_t(0x12, 112);
-enum BLKBSZSET = _IOW!size_t(0x12, 113);
-enum BLKGETSIZE64 = _IOR!size_t(0x12, 114);
-enum BLKTRACESTART = _IO(0x12, 116);
-enum BLKTRACESTOP = _IO(0x12, 117);
-enum BLKTRACETEARDOWN = _IO(0x12, 118);
-enum BLKDISCARD = _IO(0x12, 119);
-enum BLKIOMIN = _IO(0x12, 120);
-enum BLKIOOPT = _IO(0x12, 121);
-enum BLKALIGNOFF = _IO(0x12, 122);
-enum BLKPBSZGET = _IO(0x12, 123);
-enum BLKDISCARDZEROES = _IO(0x12, 124);
-enum BLKSECDISCARD = _IO(0x12, 125);
-enum BLKROTATIONAL = _IO(0x12, 126);
-enum BLKZEROOUT = _IO(0x12, 127);
+    enum BLKBSZGET = _IOR!size_t(0x12, 112);
+    enum BLKBSZSET = _IOW!size_t(0x12, 113);
+    enum BLKGETSIZE64 = _IOR!size_t(0x12, 114);
+    enum BLKTRACESTART = _IO(0x12, 116);
+    enum BLKTRACESTOP = _IO(0x12, 117);
+    enum BLKTRACETEARDOWN = _IO(0x12, 118);
+    enum BLKDISCARD = _IO(0x12, 119);
+    enum BLKIOMIN = _IO(0x12, 120);
+    enum BLKIOOPT = _IO(0x12, 121);
+    enum BLKALIGNOFF = _IO(0x12, 122);
+    enum BLKPBSZGET = _IO(0x12, 123);
+    enum BLKDISCARDZEROES = _IO(0x12, 124);
+    enum BLKSECDISCARD = _IO(0x12, 125);
+    enum BLKROTATIONAL = _IO(0x12, 126);
+    enum BLKZEROOUT = _IO(0x12, 127);
 
-enum BMAP_IOCTL = 1; /// obsolete - kept for compatibility
-enum FIBMAP = _IO(0x00, 1); /// bmap access
-enum FIGETBSZ = _IO(0x00, 2); /// get the block size used for bmap
+    enum BMAP_IOCTL = 1; /// obsolete - kept for compatibility
+    enum FIBMAP = _IO(0x00, 1); /// bmap access
+    enum FIGETBSZ = _IO(0x00, 2); /// get the block size used for bmap
+}
 
 enum FSLABEL_MAX = 256; /// Max chars for the interface; each fs may differ
 
index 805b47e6e33cbaa30e7239224db7a372d5931d01..9e96a7f5f4350b3a9b87738f0792ed36a89b9909 100644 (file)
@@ -2073,8 +2073,6 @@ else
 
                 struct
                 {
-                        import std.bitmanip : bitfields;
-
                         /* mixin(bitfields!(ulong, "mem_rsvd", 24, ulong, "mem_snoopx", 2, ulong,
                     "mem_remote", 1, ulong, "mem_lvl_num", 4, ulong, "mem_dtlb", 7, ulong,
                     "mem_lock", 2, ulong, "mem_snoop", 5, ulong, "mem_lvl",
index 20e8cf29f8d7cc89efd6feb8570e17e83c0a1a19..a6548a7802c0e2702af260c375606f9cc3f595ea 100644 (file)
@@ -32,7 +32,7 @@ public import core.sys.posix.sys.mman;
 import core.sys.linux.config;
 
 // <bits/mman.h>
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/powerpc/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/powerpc/bits/mman.h
 version (PPC_Any)
 {
     enum PROT_SAO = 0x10;
@@ -57,7 +57,7 @@ version (PPC_Any)
     //     MCL_FUTURE = 0x4000,
     // }
 }
-// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/riscv/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/riscv/bits/mman.h
 else version (RISCV_Any)
 {
     static if (__USE_MISC) enum
@@ -82,7 +82,7 @@ else version (RISCV_Any)
     //     MCL_FUTURE = 0x4000,
     // }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/s390/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/s390/bits/mman.h
 else version (IBMZ_Any)
 {
     static if (__USE_MISC) enum
@@ -98,7 +98,7 @@ else version (IBMZ_Any)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/sh/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sh/bits/mman.h
 else version (SH)
 {
     static if (__USE_MISC) enum
@@ -114,7 +114,7 @@ else version (SH)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
 else version (SPARC_Any)
 {
     static if (__USE_MISC) enum
@@ -138,7 +138,7 @@ else version (SPARC_Any)
     //     MCL_FUTURE = 0x4000,
     // }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/x86/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86/bits/mman.h
 else version (X86_Any)
 {
     static if (__USE_MISC) enum MAP_32BIT = 0x40;
@@ -156,7 +156,7 @@ else version (X86_Any)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/aarch64/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/aarch64/bits/mman.h
 else version (AArch64)
 {
     static if (__USE_MISC) enum
@@ -172,7 +172,7 @@ else version (AArch64)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/alpha/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/alpha/bits/mman.h
 else version (Alpha)
 {
     enum
@@ -264,7 +264,7 @@ else version (Alpha)
     //         POSIX_MADV_DONTNEED = 6,
     // }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/arm/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/arm/bits/mman.h
 else version (ARM)
 {
     static if (__USE_MISC) enum
@@ -280,7 +280,7 @@ else version (ARM)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/hppa/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/hppa/bits/mman.h
 else version (HPPA_Any)
 {
     enum
@@ -384,7 +384,7 @@ else version (HPPA_Any)
     //     POSIX_MADV_DONTNEED = 4,
     // }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/ia64/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/ia64/bits/mman.h
 else version (IA64)
 {
     static if (__USE_MISC) enum
@@ -401,7 +401,7 @@ else version (IA64)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/m68k/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/m68k/bits/mman.h
 else version (M68K)
 {
     static if (__USE_MISC) enum
@@ -417,7 +417,7 @@ else version (M68K)
         MAP_HUGETLB = 0x40000,
     }
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
 else version (MIPS_Any)
 {
     static if (__USE_MISC) enum
@@ -440,7 +440,7 @@ else
 
 
 // <bits/mman-linux.h>
-// https://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=bits/mman-linux.h
+// https://sourceware.org/git/?p=glibc.git;a=blob;f=bits/mman-linux.h
 version (Alpha)
 {
 }
@@ -527,12 +527,12 @@ else
 }
 
 // Workaround https://issues.dlang.org/show_bug.cgi?id=17883
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
 version (SPARC_Any)
 {
     static if (__USE_MISC) enum MAP_RENAME = MAP_ANONYMOUS;
 }
-// http://sourceware.org/git/?p=glibc.git;a=blob;hb=51e945a8f950a6695754b11c1e6fba8bb750e100;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
 else version (MIPS_Any)
 {
     static if (__USE_MISC) enum MAP_RENAME = MAP_ANONYMOUS;
diff --git a/libphobos/libdruntime/core/sys/linux/syscalls.d b/libphobos/libdruntime/core/sys/linux/syscalls.d
new file mode 100644 (file)
index 0000000..8c65371
--- /dev/null
@@ -0,0 +1,745 @@
+module core.sys.linux.syscalls;
+
+version (linux):
+extern (C):
+@system:
+nothrow:
+@nogc:
+
+import core.stdc.config : c_long;
+
+version (CoreDdoc)
+{
+    /// Linux system call number from Linux's asm/unistd.h
+    enum SystemCall : c_long;
+}
+else version (X86_64)
+{
+    // https://github.com/torvalds/linux/blob/v4.14/arch/sh/include/uapi/asm/unistd_64.h
+    // https://github.com/torvalds/linux/blob/v4.14/arch/x86/entry/syscalls/syscall_64.tbl
+    enum SystemCall : c_long
+    {
+        read = 0,
+        write = 1,
+        open = 2,
+        close = 3,
+        stat = 4,
+        fstat = 5,
+        lstat = 6,
+        poll = 7,
+        lseek = 8,
+        mmap = 9,
+        mprotect = 10,
+        munmap = 11,
+        brk = 12,
+        rt_sigaction = 13,
+        rt_sigprocmask = 14,
+        rt_sigreturn = 15,
+        ioctl = 16,
+        pread64 = 17,
+        pwrite64 = 18,
+        readv = 19,
+        writev = 20,
+        access = 21,
+        pipe = 22,
+        select = 23,
+        sched_yield = 24,
+        mremap = 25,
+        msync = 26,
+        mincore = 27,
+        madvise = 28,
+        shmget = 29,
+        shmat = 30,
+        shmctl = 31,
+        dup = 32,
+        dup2 = 33,
+        pause = 34,
+        nanosleep = 35,
+        getitimer = 36,
+        alarm = 37,
+        setitimer = 38,
+        getpid = 39,
+        sendfile = 40,
+        socket = 41,
+        connect = 42,
+        accept = 43,
+        sendto = 44,
+        recvfrom = 45,
+        sendmsg = 46,
+        recvmsg = 47,
+        shutdown = 48,
+        bind = 49,
+        listen = 50,
+        getsockname = 51,
+        getpeername = 52,
+        socketpair = 53,
+        setsockopt = 54,
+        getsockopt = 55,
+        clone = 56,
+        fork = 57,
+        vfork = 58,
+        execve = 59,
+        exit = 60,
+        wait4 = 61,
+        kill = 62,
+        uname = 63,
+        semget = 64,
+        semop = 65,
+        semctl = 66,
+        shmdt = 67,
+        msgget = 68,
+        msgsnd = 69,
+        msgrcv = 70,
+        msgctl = 71,
+        fcntl = 72,
+        flock = 73,
+        fsync = 74,
+        fdatasync = 75,
+        truncate = 76,
+        ftruncate = 77,
+        getdents = 78,
+        getcwd = 79,
+        chdir = 80,
+        fchdir = 81,
+        rename = 82,
+        mkdir = 83,
+        rmdir = 84,
+        creat = 85,
+        link = 86,
+        unlink = 87,
+        symlink = 88,
+        readlink = 89,
+        chmod = 90,
+        fchmod = 91,
+        chown = 92,
+        fchown = 93,
+        lchown = 94,
+        umask = 95,
+        gettimeofday = 96,
+        getrlimit = 97,
+        getrusage = 98,
+        sysinfo = 99,
+        times = 100,
+        ptrace = 101,
+        getuid = 102,
+        syslog = 103,
+        getgid = 104,
+        setuid = 105,
+        setgid = 106,
+        geteuid = 107,
+        getegid = 108,
+        setpgid = 109,
+        getppid = 110,
+        getpgrp = 111,
+        setsid = 112,
+        setreuid = 113,
+        setregid = 114,
+        getgroups = 115,
+        setgroups = 116,
+        setresuid = 117,
+        getresuid = 118,
+        setresgid = 119,
+        getresgid = 120,
+        getpgid = 121,
+        setfsuid = 122,
+        setfsgid = 123,
+        getsid = 124,
+        capget = 125,
+        capset = 126,
+        rt_sigpending = 127,
+        rt_sigtimedwait = 128,
+        rt_sigqueueinfo = 129,
+        rt_sigsuspend = 130,
+        sigaltstack = 131,
+        utime = 132,
+        mknod = 133,
+        uselib = 134,
+        personality = 135,
+        ustat = 136,
+        statfs = 137,
+        fstatfs = 138,
+        sysfs = 139,
+        getpriority = 140,
+        setpriority = 141,
+        sched_setparam = 142,
+        sched_getparam = 143,
+        sched_setscheduler = 144,
+        sched_getscheduler = 145,
+        sched_get_priority_max = 146,
+        sched_get_priority_min = 147,
+        sched_rr_get_interval = 148,
+        mlock = 149,
+        munlock = 150,
+        mlockall = 151,
+        munlockall = 152,
+        vhangup = 153,
+        modify_ldt = 154,
+        pivot_root = 155,
+        _sysctl = 156,
+        prctl = 157,
+        arch_prctl = 158,
+        adjtimex = 159,
+        setrlimit = 160,
+        chroot = 161,
+        sync = 162,
+        acct = 163,
+        settimeofday = 164,
+        mount = 165,
+        umount2 = 166,
+        swapon = 167,
+        swapoff = 168,
+        reboot = 169,
+        sethostname = 170,
+        setdomainname = 171,
+        iopl = 172,
+        ioperm = 173,
+        create_module = 174,
+        init_module = 175,
+        delete_module = 176,
+        get_kernel_syms = 177,
+        query_module = 178,
+        quotactl = 179,
+        nfsservctl = 180,
+        getpmsg = 181,
+        putpmsg = 182,
+        afs_syscall = 183,
+        tuxcall = 184,
+        security = 185,
+        gettid = 186,
+        readahead = 187,
+        setxattr = 188,
+        lsetxattr = 189,
+        fsetxattr = 190,
+        getxattr = 191,
+        lgetxattr = 192,
+        fgetxattr = 193,
+        listxattr = 194,
+        llistxattr = 195,
+        flistxattr = 196,
+        removexattr = 197,
+        lremovexattr = 198,
+        fremovexattr = 199,
+        tkill = 200,
+        time = 201,
+        futex = 202,
+        sched_setaffinity = 203,
+        sched_getaffinity = 204,
+        set_thread_area = 205,
+        io_setup = 206,
+        io_destroy = 207,
+        io_getevents = 208,
+        io_submit = 209,
+        io_cancel = 210,
+        get_thread_area = 211,
+        lookup_dcookie = 212,
+        epoll_create = 213,
+        epoll_ctl_old = 214,
+        epoll_wait_old = 215,
+        remap_file_pages = 216,
+        getdents64 = 217,
+        set_tid_address = 218,
+        restart_syscall = 219,
+        semtimedop = 220,
+        fadvise64 = 221,
+        timer_create = 222,
+        timer_settime = 223,
+        timer_gettime = 224,
+        timer_getoverrun = 225,
+        timer_delete = 226,
+        clock_settime = 227,
+        clock_gettime = 228,
+        clock_getres = 229,
+        clock_nanosleep = 230,
+        exit_group = 231,
+        epoll_wait = 232,
+        epoll_ctl = 233,
+        tgkill = 234,
+        utimes = 235,
+        vserver = 236,
+        mbind = 237,
+        set_mempolicy = 238,
+        get_mempolicy = 239,
+        mq_open = 240,
+        mq_unlink = 241,
+        mq_timedsend = 242,
+        mq_timedreceive = 243,
+        mq_notify = 244,
+        mq_getsetattr = 245,
+        kexec_load = 246,
+        waitid = 247,
+        add_key = 248,
+        request_key = 249,
+        keyctl = 250,
+        ioprio_set = 251,
+        ioprio_get = 252,
+        inotify_init = 253,
+        inotify_add_watch = 254,
+        inotify_rm_watch = 255,
+        migrate_pages = 256,
+        openat = 257,
+        mkdirat = 258,
+        mknodat = 259,
+        fchownat = 260,
+        futimesat = 261,
+        newfstatat = 262,
+        unlinkat = 263,
+        renameat = 264,
+        linkat = 265,
+        symlinkat = 266,
+        readlinkat = 267,
+        fchmodat = 268,
+        faccessat = 269,
+        pselect6 = 270,
+        ppoll = 271,
+        unshare = 272,
+        set_robust_list = 273,
+        get_robust_list = 274,
+        splice = 275,
+        tee = 276,
+        sync_file_range = 277,
+        vmsplice = 278,
+        move_pages = 279,
+        utimensat = 280,
+        epoll_pwait = 281,
+        signalfd = 282,
+        timerfd_create = 283,
+        eventfd = 284,
+        fallocate = 285,
+        timerfd_settime = 286,
+        timerfd_gettime = 287,
+        accept4 = 288,
+        signalfd4 = 289,
+        eventfd2 = 290,
+        epoll_create1 = 291,
+        dup3 = 292,
+        pipe2 = 293,
+        inotify_init1 = 294,
+        preadv = 295,
+        pwritev = 296,
+        rt_tgsigqueueinfo = 297,
+        perf_event_open = 298,
+        recvmmsg = 299,
+        fanotify_init = 300,
+        fanotify_mark = 301,
+        prlimit64 = 302,
+        name_to_handle_at = 303,
+        open_by_handle_at = 304,
+        clock_adjtime = 305,
+        syncfs = 306,
+        sendmmsg = 307,
+        setns = 308,
+        getcpu = 309,
+        process_vm_readv = 310,
+        process_vm_writev = 311,
+        kcmp = 312,
+        finit_module = 313,
+        sched_setattr = 314,
+        sched_getattr = 315,
+        renameat2 = 316,
+        seccomp = 317,
+        getrandom = 318,
+        memfd_create = 319,
+        kexec_file_load = 320,
+        bpf = 321,
+        execveat = 322,
+        userfaultfd = 323,
+        membarrier = 324,
+        mlock2 = 325,
+        copy_file_range = 326,
+        preadv2 = 327,
+        pwritev2 = 328,
+        pkey_mprotect = 329,
+        pkey_alloc = 330,
+        pkey_free = 331,
+        statx = 332,
+    }
+}
+else version (X86)
+{
+    // https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_32.tbl
+    // https://github.com/torvalds/linux/blob/v4.14/arch/sh/include/uapi/asm/unistd_32.h
+    enum SystemCall : c_long
+    {
+        restart_syscall = 0,
+        exit = 1,
+        fork = 2,
+        read = 3,
+        write = 4,
+        open = 5,
+        close = 6,
+        waitpid = 7,
+        creat = 8,
+        link = 9,
+        unlink = 10,
+        execve = 11,
+        chdir = 12,
+        time = 13,
+        mknod = 14,
+        chmod = 15,
+        lchown = 16,
+        break_ = 17,
+        oldstat = 18,
+        lseek = 19,
+        getpid = 20,
+        mount = 21,
+        umount = 22,
+        setuid = 23,
+        getuid = 24,
+        stime = 25,
+        ptrace = 26,
+        alarm = 27,
+        oldfstat = 28,
+        pause = 29,
+        utime = 30,
+        stty = 31,
+        gtty = 32,
+        access = 33,
+        nice = 34,
+        ftime = 35,
+        sync = 36,
+        kill = 37,
+        rename = 38,
+        mkdir = 39,
+        rmdir = 40,
+        dup = 41,
+        pipe = 42,
+        times = 43,
+        prof = 44,
+        brk = 45,
+        setgid = 46,
+        getgid = 47,
+        signal = 48,
+        geteuid = 49,
+        getegid = 50,
+        acct = 51,
+        umount2 = 52,
+        lock = 53,
+        ioctl = 54,
+        fcntl = 55,
+        mpx = 56,
+        setpgid = 57,
+        ulimit = 58,
+        oldolduname = 59,
+        umask = 60,
+        chroot = 61,
+        ustat = 62,
+        dup2 = 63,
+        getppid = 64,
+        getpgrp = 65,
+        setsid = 66,
+        sigaction = 67,
+        sgetmask = 68,
+        ssetmask = 69,
+        setreuid = 70,
+        setregid = 71,
+        sigsuspend = 72,
+        sigpending = 73,
+        sethostname = 74,
+        setrlimit = 75,
+        getrlimit = 76,
+        getrusage = 77,
+        gettimeofday = 78,
+        settimeofday = 79,
+        getgroups = 80,
+        setgroups = 81,
+        select = 82,
+        symlink = 83,
+        oldlstat = 84,
+        readlink = 85,
+        uselib = 86,
+        swapon = 87,
+        reboot = 88,
+        readdir = 89,
+        mmap = 90,
+        munmap = 91,
+        truncate = 92,
+        ftruncate = 93,
+        fchmod = 94,
+        fchown = 95,
+        getpriority = 96,
+        setpriority = 97,
+        profil = 98,
+        statfs = 99,
+        fstatfs = 100,
+        ioperm = 101,
+        socketcall = 102,
+        syslog = 103,
+        setitimer = 104,
+        getitimer = 105,
+        stat = 106,
+        lstat = 107,
+        fstat = 108,
+        olduname = 109,
+        iopl = 110,
+        vhangup = 111,
+        idle = 112,
+        vm86old = 113,
+        wait4 = 114,
+        swapoff = 115,
+        sysinfo = 116,
+        ipc = 117,
+        fsync = 118,
+        sigreturn = 119,
+        clone = 120,
+        setdomainname = 121,
+        uname = 122,
+        modify_ldt = 123,
+        adjtimex = 124,
+        mprotect = 125,
+        sigprocmask = 126,
+        create_module = 127,
+        init_module = 128,
+        delete_module = 129,
+        get_kernel_syms = 130,
+        quotactl = 131,
+        getpgid = 132,
+        fchdir = 133,
+        bdflush = 134,
+        sysfs = 135,
+        personality = 136,
+        afs_syscall = 137,
+        setfsuid = 138,
+        setfsgid = 139,
+        _llseek = 140,
+        getdents = 141,
+        _newselect = 142,
+        flock = 143,
+        msync = 144,
+        readv = 145,
+        writev = 146,
+        getsid = 147,
+        fdatasync = 148,
+        _sysctl = 149,
+        mlock = 150,
+        munlock = 151,
+        mlockall = 152,
+        munlockall = 153,
+        sched_setparam = 154,
+        sched_getparam = 155,
+        sched_setscheduler = 156,
+        sched_getscheduler = 157,
+        sched_yield = 158,
+        sched_get_priority_max = 159,
+        sched_get_priority_min = 160,
+        sched_rr_get_interval = 161,
+        nanosleep = 162,
+        mremap = 163,
+        setresuid = 164,
+        getresuid = 165,
+        vm86 = 166,
+        query_module = 167,
+        poll = 168,
+        nfsservctl = 169,
+        setresgid = 170,
+        getresgid = 171,
+        prctl = 172,
+        rt_sigreturn = 173,
+        rt_sigaction = 174,
+        rt_sigprocmask = 175,
+        rt_sigpending = 176,
+        rt_sigtimedwait = 177,
+        rt_sigqueueinfo = 178,
+        rt_sigsuspend = 179,
+        pread64 = 180,
+        pwrite64 = 181,
+        chown = 182,
+        getcwd = 183,
+        capget = 184,
+        capset = 185,
+        sigaltstack = 186,
+        sendfile = 187,
+        getpmsg = 188,
+        putpmsg = 189,
+        vfork = 190,
+        ugetrlimit = 191,
+        mmap2 = 192,
+        truncate64 = 193,
+        ftruncate64 = 194,
+        stat64 = 195,
+        lstat64 = 196,
+        fstat64 = 197,
+        lchown32 = 198,
+        getuid32 = 199,
+        getgid32 = 200,
+        geteuid32 = 201,
+        getegid32 = 202,
+        setreuid32 = 203,
+        setregid32 = 204,
+        getgroups32 = 205,
+        setgroups32 = 206,
+        fchown32 = 207,
+        setresuid32 = 208,
+        getresuid32 = 209,
+        setresgid32 = 210,
+        getresgid32 = 211,
+        chown32 = 212,
+        setuid32 = 213,
+        setgid32 = 214,
+        setfsuid32 = 215,
+        setfsgid32 = 216,
+        pivot_root = 217,
+        mincore = 218,
+        madvise = 219,
+        getdents64 = 220,
+        fcntl64 = 221,
+        gettid = 224,
+        readahead = 225,
+        setxattr = 226,
+        lsetxattr = 227,
+        fsetxattr = 228,
+        getxattr = 229,
+        lgetxattr = 230,
+        fgetxattr = 231,
+        listxattr = 232,
+        llistxattr = 233,
+        flistxattr = 234,
+        removexattr = 235,
+        lremovexattr = 236,
+        fremovexattr = 237,
+        tkill = 238,
+        sendfile64 = 239,
+        futex = 240,
+        sched_setaffinity = 241,
+        sched_getaffinity = 242,
+        set_thread_area = 243,
+        get_thread_area = 244,
+        io_setup = 245,
+        io_destroy = 246,
+        io_getevents = 247,
+        io_submit = 248,
+        io_cancel = 249,
+        fadvise64 = 250,
+        exit_group = 252,
+        lookup_dcookie = 253,
+        epoll_create = 254,
+        epoll_ctl = 255,
+        epoll_wait = 256,
+        remap_file_pages = 257,
+        set_tid_address = 258,
+        timer_create = 259,
+        timer_settime = 260,
+        timer_gettime = 261,
+        timer_getoverrun = 262,
+        timer_delete = 263,
+        clock_settime = 264,
+        clock_gettime = 265,
+        clock_getres = 266,
+        clock_nanosleep = 267,
+        statfs64 = 268,
+        fstatfs64 = 269,
+        tgkill = 270,
+        utimes = 271,
+        fadvise64_64 = 272,
+        vserver = 273,
+        mbind = 274,
+        get_mempolicy = 275,
+        set_mempolicy = 276,
+        mq_open = 277,
+        mq_unlink = 278,
+        mq_timedsend = 279,
+        mq_timedreceive = 280,
+        mq_notify = 281,
+        mq_getsetattr = 282,
+        kexec_load = 283,
+        waitid = 284,
+        add_key = 286,
+        request_key = 287,
+        keyctl = 288,
+        ioprio_set = 289,
+        ioprio_get = 290,
+        inotify_init = 291,
+        inotify_add_watch = 292,
+        inotify_rm_watch = 293,
+        migrate_pages = 294,
+        openat = 295,
+        mkdirat = 296,
+        mknodat = 297,
+        fchownat = 298,
+        futimesat = 299,
+        fstatat64 = 300,
+        unlinkat = 301,
+        renameat = 302,
+        linkat = 303,
+        symlinkat = 304,
+        readlinkat = 305,
+        fchmodat = 306,
+        faccessat = 307,
+        pselect6 = 308,
+        ppoll = 309,
+        unshare = 310,
+        set_robust_list = 311,
+        get_robust_list = 312,
+        splice = 313,
+        sync_file_range = 314,
+        tee = 315,
+        vmsplice = 316,
+        move_pages = 317,
+        getcpu = 318,
+        epoll_pwait = 319,
+        utimensat = 320,
+        signalfd = 321,
+        timerfd_create = 322,
+        eventfd = 323,
+        fallocate = 324,
+        timerfd_settime = 325,
+        timerfd_gettime = 326,
+        signalfd4 = 327,
+        eventfd2 = 328,
+        epoll_create1 = 329,
+        dup3 = 330,
+        pipe2 = 331,
+        inotify_init1 = 332,
+        preadv = 333,
+        pwritev = 334,
+        rt_tgsigqueueinfo = 335,
+        perf_event_open = 336,
+        recvmmsg = 337,
+        fanotify_init = 338,
+        fanotify_mark = 339,
+        prlimit64 = 340,
+        name_to_handle_at = 341,
+        open_by_handle_at = 342,
+        clock_adjtime = 343,
+        syncfs = 344,
+        sendmmsg = 345,
+        setns = 346,
+        process_vm_readv = 347,
+        process_vm_writev = 348,
+        kcmp = 349,
+        finit_module = 350,
+        sched_setattr = 351,
+        sched_getattr = 352,
+        renameat2 = 353,
+        seccomp = 354,
+        getrandom = 355,
+        memfd_create = 356,
+        bpf = 357,
+        execveat = 358,
+        socket = 359,
+        socketpair = 360,
+        bind = 361,
+        connect = 362,
+        listen = 363,
+        accept4 = 364,
+        getsockopt = 365,
+        setsockopt = 366,
+        getsockname = 367,
+        getpeername = 368,
+        sendto = 369,
+        sendmsg = 370,
+        recvfrom = 371,
+        recvmsg = 372,
+        shutdown = 373,
+        userfaultfd = 374,
+        membarrier = 375,
+        mlock2 = 376,
+        copy_file_range = 377,
+        preadv2 = 378,
+        pwritev2 = 379,
+        pkey_mprotect = 380,
+        pkey_alloc = 381,
+        pkey_free = 382,
+        statx = 383,
+        arch_prctl = 384,
+    }
+}
index 4845746700558f904eda7cbeff7b93f9687966cb..1ef16c12689c151935a41a7dd02341befe0d52d4 100644 (file)
@@ -1,16 +1,20 @@
 module core.sys.linux.unistd;
 
-public import core.sys.posix.unistd;
-
 version (linux):
-extern(C):
+extern (C):
 nothrow:
 @system:
+@nogc:
+
+public import core.sys.posix.unistd;
+public import core.sys.linux.syscalls : SystemCall;
+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)
-enum {
+enum
+{
     /// Offset is relative to the next location containing data
     SEEK_DATA = 3,
     /// Offset is relative to the next hole (or EOF if file is not sparse)
@@ -22,3 +26,17 @@ char* getpass(const(char)* prompt);
 
 // Exit all threads in a process
 void exit_group(int status);
+
+/**
+Invoke system call specified by number, passing it the remaining arguments.
+This is completely system-dependent, and not often useful.
+
+In Unix, `syscall' sets `errno' for all errors and most calls return -1
+for errors; in many systems you cannot pass arguments or get return
+values for all system calls (`pipe', `fork', and `getppid' typically
+among them).
+
+In Mach, all system calls take normal arguments and always return an
+error code (zero for success).
+*/
+c_long syscall(SystemCall number, ...) @nogc nothrow;
index a8e8565cb48225ed989e00974e49feccb0c2a651..b28dc63d5c72dc302e4b6cccc26a64f4d036f3c6 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * D header file for OpenBSD.
  *
- * $(LINK2 http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/include/link_elf.h?rev=1.6&content-type=text/x-cvsweb-markup, dlfcn.h)
+ * $(LINK2 https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/include/dlfcn.h?rev=1.15&content-type=text/plain, dlfcn.h)
  */
 module core.sys.openbsd.dlfcn;
 
@@ -16,6 +16,7 @@ static assert(RTLD_NOW    == 2);
 static assert(RTLD_GLOBAL == 0x100);
 static assert(RTLD_LOCAL  == 0);
 enum RTLD_TRACE           =  0x200;
+enum RTLD_NODELETE        =  0x400;
 
 enum RTLD_NEXT    = cast(void *)-1;
 enum RTLD_DEFAULT = cast(void *)-2;
@@ -24,6 +25,7 @@ enum RTLD_SELF    = cast(void *)-3;
 enum DL_GETERRNO     = 1;
 enum DL_SETTHREADLCK = 2;
 enum DL_SETBINDLCK   = 3;
+enum DL_REFERENCE    = 4;
 
 enum DL_LAZY         = RTLD_LAZY;
 
diff --git a/libphobos/libdruntime/core/sys/openbsd/pthread_np.d b/libphobos/libdruntime/core/sys/openbsd/pthread_np.d
new file mode 100644 (file)
index 0000000..8344df2
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+  * D header file for OpenBSD pthread_np.h.
+  *
+  * Copyright: Copyright © 2021, The D Language Foundation
+  * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+  * Authors: Brian Callahan
+  */
+module core.sys.openbsd.pthread_np;
+
+version (OpenBSD):
+extern (C):
+nothrow:
+@nogc:
+
+public import core.sys.posix.sys.types;
+import core.sys.posix.signal : stack_t;
+
+int pthread_mutexattr_getkind_np(pthread_mutexattr_t);
+int pthread_mutexattr_setkind_np(pthread_mutexattr_t*, int);
+void pthread_get_name_np(pthread_t, char*, size_t);
+void pthread_set_name_np(pthread_t, const(char)*);
+int pthread_stackseg_np(pthread_t, stack_t*);
+int pthread_main_np();
index 2d4d7a9a4f2017d9bef4316a5c50005e56caed1a..c8c2b1b659fd17680df21f5216f8f6f077c86701 100644 (file)
@@ -13,5 +13,11 @@ extern (C):
 nothrow:
 @nogc:
 
+void freezero(void*, size_t);
+void* calloc_conceal(size_t, size_t);
+void* malloc_conceal(size_t);
+void* reallocarray(void*, size_t, size_t);
+void* recallocarray(void*, size_t, size_t, size_t);
+
 const(char)* getprogname();
-void setprogname(scope const char* name);
+void setprogname(scope const char*);
index cb978c8249ba4a3eb9a91dff83e2f8d3681e17cc..131e67727e8de37fa6c389ee4f92946662d1a96f 100644 (file)
@@ -17,7 +17,13 @@ nothrow:
 
 static if (__BSD_VISIBLE)
 {
+    void explicit_bzero(void*, size_t);
     pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    void* memrchr(scope const void*, int, size_t);
+    size_t strlcat(char*, scope const char*, size_t);
+    size_t strlcpy(char*, scope const char*, size_t);
+    void strmode(int, char*);
+    char* strsep(char**, scope const char*);
     pure int timingsafe_bcmp(scope const void*, scope const void*, size_t);
     pure int timingsafe_memcmp(scope const void*, scope const void*, size_t);
 }
index 0e882072c94f88af7550bb62529c0fc123236c0f..765483436ac55b973d226e9f6a192ebee42c280b 100644 (file)
@@ -19,11 +19,12 @@ import core.sys.posix.sys.types;
 // enum MAP_PRIVATE = 0x0002;
 // enum MAP_FIXED = 0x0010;
 // enum MAP_ANON = 0x1000;
+// enum MAP_STACK = 0x4000;
 
 alias MAP_ANONYMOUS = MAP_ANON;
-enum MAP_STACK = 0x4000;
+enum MAP_CONCEAL = 0x8000;
 
-enum MAP_FLAGMASK = 0x7ff7;
+enum MAP_FLAGMASK = 0xfff7;
 
 alias MAP_COPY = MAP_PRIVATE;
 enum MAP_FILE = 0;
@@ -45,7 +46,6 @@ static if (__BSD_VISIBLE)
     enum MADV_FREE = 6;
 
     int madvise(void *, size_t, int);
-    int mincore(const(void) *, size_t, char *);
     int minherit(void *, size_t, int);
     void* mquery(void *, size_t, int, int, int, off_t);
 }
index c6f98455feff47ca31041dfd3ad052f8c6db2dae..3a4524245aab19410d353f902e9fefd2542aeb5e 100644 (file)
@@ -250,5 +250,4 @@ enum
 }
 
 ///
-int sysctl(const int* name, uint namelen, void* oldp, size_t* oldlenp,
-           const void* newp, size_t newlen);
+int sysctl(const int*, uint, void*, size_t*, void*, size_t);
index ddd102cdeaedc41df9e9c6e46a3edcea780066e3..0b8580fb86090022ea46a701731ee2939521e013 100644 (file)
@@ -6,12 +6,12 @@
   * Authors: Brian Callahan
   */
 module core.sys.openbsd.unistd;
-public import core.sys.posix.unistd;
 
 version (OpenBSD):
 extern (C):
 nothrow:
 @nogc:
 
+int getentropy(void*, size_t);
 int pledge(const scope char*, const scope char*);
 int unveil(const scope char*, const scope char*);
index bede63843d8f5b36784aae92ffc34fc098197fc3..d1411ea8afbaadc4923d1dbc7c30edf808b2b88f 100644 (file)
@@ -567,6 +567,7 @@ else version (OpenBSD)
     enum AI_NUMERICHOST     = 0x4;
     enum AI_EXT             = 0x8;
     enum AI_NUMERICSERV     = 0x10;
+    enum AI_V4MAPPED        = 0; // Not supported
     enum AI_FQDN            = 0x20;
     enum AI_ADDRCONFIG      = 0x40;
     enum AI_MASK            = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_FQDN | AI_ADDRCONFIG;
index afb6f82d978e2c42881d2864164e0d60d14c26f6..a8d837c52b675f814a7805347166f9879da7b4b6 100644 (file)
@@ -34,3 +34,15 @@ version (Darwin)
     enum uint FIOGETOWN = _IOR!(int)('f', 123); // get owner
     enum uint FIODTYPE  = _IOR!(int)('f', 122); // get d_type
 }
+
+version (OpenBSD)
+{
+    // File-descriptor ioctl's
+    enum uint FIOCLEX   = _IO('f', 1);         // set close on exec on fd
+    enum uint FIONCLEX  = _IO('f', 2);         // remove close on exec
+    enum uint FIONREAD  = _IOR!(int)('f', 127); // get # bytes to read
+    enum uint FIONBIO   = _IOW!(int)('f', 126); // set/clear non-blocking i/o
+    enum uint FIOASYNC  = _IOW!(int)('f', 125); // set/clear async i/o
+    enum uint FIOSETOWN = _IOW!(int)('f', 124); // set owner
+    enum uint FIOGETOWN = _IOR!(int)('f', 123); // get owner
+}
index 4c1a820161c128b7180cb7e026a48fb50eaa5689..4a0e96b3ea9af3a1af6d8a2fb497f12583de3a6d 100755 (executable)
@@ -137,3 +137,59 @@ else version (FreeBSD)
         return _IOC(IOC_INOUT, cast(uint)g, cast(uint)n, T.sizeof);
     }
 }
+else version (OpenBSD)
+{
+    /* OpenBSD ioctl's encode the command in the lower 16-bits
+     * and the size of any in/out parameters in the lower 13 bits of the upper
+     * 16-bits of a 32 bit unsigned integer. The high 3 bits of the upper
+     * 16-bits encode the in/out status of the parameter.
+     */
+    enum uint IOCPARM_MASK = 0x1fff; // parameter length mask
+    uint IOCPARM_LEN(uint x) // to extract the encoded parameter length
+    {
+        return ((x >> 16) & IOCPARM_MASK);
+    }
+    uint IOCBASECMD(uint x) // to extract the encoded command
+    {
+        return (x & ~(IOCPARM_MASK << 16));
+    }
+    uint IOCGROUP(uint x) // to extract the encoded group
+    {
+        return ((x >> 8) & 0xff);
+    }
+
+    enum uint IOCPARM_MAX = (1 << 12); // max size of ioctl args
+
+    enum uint IOC_VOID = 0x20000000; // no parameters
+    enum uint IOC_OUT = 0x40000000; // copy parameters back
+    enum uint IOC_IN = 0x80000000; // copy parameters into
+    enum uint IOC_INOUT = (IOC_IN | IOC_OUT);
+    enum uint IOC_DIRMASK = 0xe0000000;
+
+    // encode the ioctl info into 32 bits
+    uint _IOC(uint inorout, uint group, uint num, size_t len)
+    {
+        return (inorout | ((len & IOCPARM_MASK) << 16) | (group << 8) | num);
+    }
+
+    // encode a command with no parameters
+    uint _IO(char g, int n)
+    {
+        return _IOC(IOC_VOID, cast(uint)g, cast(uint)n, cast(size_t)0);
+    }
+    // encode a command that returns info
+    uint _IOR(T)(char g, int n)
+    {
+        return _IOC(IOC_OUT, cast(uint)g, cast(uint)n, T.sizeof);
+    }
+    // encode a command that takes info
+    uint _IOW(T)(char g, int n)
+    {
+        return _IOC(IOC_IN, cast(uint)g, cast(uint)n, T.sizeof);
+    }
+    // encode a command that takes info and returns info
+    uint _IOWR(T)(char g, int n)
+    {
+        return _IOC(IOC_INOUT, cast(uint)g, cast(uint)n, T.sizeof);
+    }
+}
index 0266200c8112c6beadb89fcf7501ad394ec29ae0..c6f21d6cd0a87093b334c388984aafe56b5ab680 100644 (file)
@@ -375,6 +375,11 @@ else version (NetBSD)
 }
 else version (OpenBSD)
 {
+    import core.sys.posix.termios; // termios
+    import core.sys.posix.sys.time; // timeval
+
+    public import core.sys.posix.sys.ttycom; // Terminal related ioctls
+
     struct winsize
     {
         ushort ws_row;
@@ -383,6 +388,8 @@ else version (OpenBSD)
         ushort ws_ypixel;
     }
 
+    public import core.sys.posix.sys.filio; // File related ioctls
+
     int ioctl(int, c_ulong, ...);
 }
 else version (DragonFlyBSD)
index a74a213691cf9eb3075bc7a5d2cbab3d091949da..18da10246e4957b359de5e3080f024cc4d023331 100644 (file)
@@ -460,6 +460,7 @@ else version (OpenBSD)
     enum MAP_PRIVATE    = 0x0002;
     enum MAP_FIXED      = 0x0010;
     enum MAP_ANON       = 0x1000;
+    enum MAP_STACK      = 0x4000;
 
     enum MAP_FAILED     = cast(void*)-1;
 
index 430d0c0d1e3898aaf244baf6697ba2836e1992ce..de51c6a474671f4ae5fb4a34532073aeaabaf41c 100644 (file)
@@ -536,7 +536,8 @@ version (CRuntime_Glibc)
 
     enum
     {
-        SOMAXCONN       = 128
+        // https://sourceware.org/git/?p=glibc.git;a=commit;f=sysdeps/unix/sysv/linux/bits/socket.h;h=96958e2700f5b4f4d1183a0606b2b9848a53ea44
+        SOMAXCONN       = 4096
     }
 
     enum : uint
index 1a6c11be291a8fef7a062f240ebb9f918e594c6b..0cc2d9cdc8424203c2656fe31f0e867ca3f0b049 100755 (executable)
@@ -214,3 +214,104 @@ else version (FreeBSD)
     enum uint NETGRAPHDISC = 6;   // Netgraph tty node discipline
     enum uint H4DISC   = 7;       // Netgraph Blutooth H4 discipline
 }
+else version (OpenBSD)
+{
+    struct winsize {
+        ushort  ws_row;     // rows, in characters
+        ushort  ws_col;     // columns, in characters
+        ushort  ws_xpixel;  // horizontal size, pixels
+        ushort  ws_ypixel;  // vertical size, pixels
+    }
+
+    struct tstamps {
+        int ts_set;         // TIOCM_CAR and/or TIOCM_CTS
+        int ts_clr;
+    }
+
+    // Serial/TTY ioctl's
+                                               // 0-2 compat
+                                               // 3-7 unused
+                                               // 8-10 compat
+                                               // 11-12 unused
+    enum uint TIOCEXCL  = _IO('t', 13);        // set exclusive use of tty
+    enum uint TIOCNXCL  = _IO('t', 14);        // reset exclusive use of tty
+    enum uint TIOCFLUSH = _IOW!(int)('t', 16); // flush buffers
+                            // 17-18 compat
+    enum uint TIOCGETA  = _IOR!(termios)('t', 19); // get termios struct
+    enum uint TIOCSETA  = _IOW!(termios)('t', 20); // set termios struct
+    enum uint TIOCSETAW = _IOW!(termios)('t', 21); // drain output, set
+    enum uint TIOCSETAF = _IOW!(termios)('t', 22); // drn out, fls in, set
+                            // 23-25 unused
+    enum uint TIOCGETD  = _IOR!(int)('t', 26); // get line discipline
+    enum uint TIOCSETD  = _IOW!(int)('t', 27); // set line discipline
+    enum uint TIOCSETVERAUTH = _IOW!(int)('t', 28);     // set verified auth
+    enum uint TIOCCLRVERAUTH = _IO('t', 29);     // clear verified auth
+    enum uint TIOCCHKVERAUTH = _IO('t', 30);     // check verified auth
+                            // 31-89 unused
+    enum uint TIOCSTSTAMP = _IOW!(tstamps)('t', 90); // timestamp reasons
+    enum uint TIOCGTSTAMP = _IOR!(timeval)('t', 91); // get timestamp
+                            // 92-93 device flags
+    enum uint TIOCSFLAGS = _IOW!(int)('t', 92); // set device flags
+    enum uint TIOCGFLAGS = _IOR!(int)('t', 93); // get device flags
+                            // 94-97 conflicts: tun and tap
+    enum uint TIOCDRAIN = _IO('t', 94); // wait till output drained
+    enum uint TIOCSIG   = _IOW!(int)('t', 95); // pty: generate signal
+    enum uint TIOCEXT   = _IOW!(int)('t', 96); // pty: external processing
+    enum uint TIOCSCTTY = _IO('t', 97);        // become controlling tty
+    enum uint TIOCCONS  = _IOW!(int)('t', 98); // become virtual console
+    enum uint TIOCGSID  = _IOR!(int)('t', 99); // get session id
+                            // 100 unused
+    enum uint TIOCSTAT  = _IO('t', 101);       // simulate ^T status message
+    enum uint TIOCUCNTL = _IOW!(int)('t', 102); // pty: set/clr usr cntl mode
+    enum uint   UIOCCMD(n) = _IO('u', n);       // usr cntl op "n"
+    enum uint TIOCSWINSZ = _IOW!(winsize)('t', 103); // set window size
+    enum uint TIOCGWINSZ = _IOR!(winsize)('t', 104); // get window size
+    enum uint TIOCREMOTE = _IOW!(int)('t', 105); // remote input editing
+    enum uint TIOCMGET  = _IOR!(int)('t', 106); // get all modem bits
+    enum uint   TIOCM_LE  = 0x01;               // line enable
+    enum uint   TIOCM_DTR = 0x02;               // data terminal ready
+    enum uint   TIOCM_RTS = 0x04;               // request to send
+    enum uint   TIOCM_ST  = 0x08;               // secondary transmit
+    enum uint   TIOCM_SR  = 0x10;               // secondary receive
+    enum uint   TIOCM_CTS = 0x20;               // clear to send
+    enum uint   TIOCM_CAR = 0x40;               // carrier detect
+    enum uint   TIOCM_RNG = 0x80;               // ring
+    enum uint   TIOCM_DSR = 0x100;              // data set ready
+    enum uint   TIOCM_CD  = TIOCM_CAR;
+    enum uint   TIOCM_RI = TIOCM_RNG;
+    enum uint TIOCMBIC  = _IOW!(int)('t', 107); // bic modem bits
+    enum uint TIOCMBIS  = _IOW!(int)('t', 108); // bis modem bits
+    enum uint TIOCMSET  = _IOW!(int)('t', 109); // set all modem bits
+    enum uint TIOCSTART = _IO('t', 110);        // start output like ^Q
+    enum uint TIOCSTOP  = _IO('t', 111);        // stop output like ^S
+    enum uint TIOCPKT   = _IOW!(int)('t', 112); // pty: set/clr packet mode
+    enum uint TIOCPKT_DATA       = 0x00;        // data packet
+    enum uint TIOCPKT_FLUSHREAD  = 0x01;        // flush packet
+    enum uint TIOCPKT_FLUSHWRITE = 0x02;        // flush packet
+    enum uint TIOCPKT_STOP       = 0x04;        // stop output
+    enum uint TIOCPKT_START      = 0x08;        // start output
+    enum uint TIOCPKT_NOSTOP     = 0x10;        // no more ^S, ^Q
+    enum uint TIOCPKT_DOSTOP     = 0x20;        // now do ^S, ^Q
+    enum uint TIOCPKT_IOCTL      = 0x40;        // state change of pty driver
+    enum uint TIOCNOTTY = _IO('t', 113);        // void tty association
+                             // 114 unused
+    enum uint TIOCOUTQ  = _IOR!(int)('t', 115); // output queue size
+                             // 116-117 compat
+    enum uint TIOCSPGRP = _IOW!(int)('t', 118); // set pgrp of tty
+    enum uint TIOCGPGRP = _IOR!(int)('t', 119); // get pgrp of tty
+
+    enum uint TIOCCDTR  = _IO('t', 120);       // clear data terminal ready
+    enum uint TIOCSDTR  = _IO('t', 121);       // set data terminal ready
+    enum uint TIOCCBRK  = _IO('t', 122);       // clear break bit
+    enum uint TIOCSBRK  = _IO('t', 123);       // set break bit
+                            // 124-127 compat
+
+    enum uint TTYDISC  = 0;       // termios tty line discipline
+    enum uint TABLDISC = 3;       // tablet description
+    enum uint SLIPDISC = 4;       // serial IP discipline
+    enum uint PPPDISC  = 5;       // PPP discipline
+    enum uint STRIPDISC = 6;      // metricom wireless IP discipline
+    enum uint NMEADISC = 7;       // NMEA0183 discipline
+    enum uint MSTSDISC = 8;       // Meinberg time string discipline
+    enum uint ENDRUNDISC = 9;     // Endrun time format discipline
+}
index 52a6f92be0aeb84f8ead17f606d5754ccdfbc7b3..a9be87c859797df64f6d76e01aafbf408d1eeb77 100644 (file)
@@ -341,11 +341,6 @@ else version (OpenBSD)
     int clock_gettime(clockid_t, timespec*);
     int clock_settime(clockid_t, const scope timespec*);
     int nanosleep(const scope timespec*, timespec*);
-    int timer_create(clockid_t, sigevent*, timer_t*);
-    int timer_delete(timer_t);
-    int timer_gettime(timer_t, itimerspec*);
-    int timer_getoverrun(timer_t);
-    int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
 }
 else version (Solaris)
 {
index 77bc184710fcc10a903502fb59b2611ca48e400f..e967da6ed63b8e5252cc7104116710e5182f6e01 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_accctrl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_accctrl.d)
  */
 module core.sys.windows.accctrl;
 version (Windows):
index 1e75d3f52ee183e5bdfa69199678c8565506af53..f145ac26af028d2dc141b7c720b102cb0739961a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_aclapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_aclapi.d)
  */
 module core.sys.windows.aclapi;
 version (Windows):
index 6ae37c6a686e6f0ca6916f77b2b58ca7f5a9de21..c5a28992631728a3642f7318c4bf1129a314b598 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_aclui.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_aclui.d)
  */
 module core.sys.windows.aclui;
 version (Windows):
index 3bcac1208caa196228d5aceeb97d69da482287bf..0c689024aaaeaa71325513a93d6958a2481ad29f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_basetsd.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_basetsd.d)
  */
 module core.sys.windows.basetsd;
 version (Windows):
index abe312e4ddc1647edf15ddf966919d55d8a770f0..086e6ab30e32ba0679462ae40fa117aa05ed372c 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.10
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_basetyps.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_basetyps.d)
  */
 module core.sys.windows.basetyps;
 version (Windows):
index 278a11c5b95a6f3efb041f4a8c95297d8eb84740..afcdf272743533bef8ea4c4b90aaef5ac19b67b9 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_cderr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_cderr.d)
  */
 module core.sys.windows.cderr;
 version (Windows):
index 8d67b881ee1c97227340e25ddf3f1105f2da40af..0afbc42e8b03f394186e7fae63b01b9a4938d078 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_cguid.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_cguid.d)
  */
 module core.sys.windows.cguid;
 version (Windows):
index cb45ff5762ccaa2c80b8e1e53833680e961b215c..3018c64d7f078486d7045afb21bc05951b35f956 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_comcat.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_comcat.d)
  */
 module core.sys.windows.comcat;
 version (Windows):
index f008e75ddeee8f0ea97a249a44c38707bbc16ece..4bc60b1fd8b3a7a5223e54deb1c5f0e5a4d82ca2 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.12
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_commctrl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_commctrl.d)
  */
 module core.sys.windows.commctrl;
 version (Windows):
index 1e8057c5f062f50193160ab61c118550e14cd333..b49d2fba6feb177571b0793e7c2858eb76e5cfc3 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.12
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_commdlg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_commdlg.d)
  */
 module core.sys.windows.commdlg;
 version (Windows):
index 8b355b3e2a6d8dae989dfd5717a376848b24073c..e8bc4a7bcc81a8791274ed4078ab1c9685ceb204 100644 (file)
@@ -2,7 +2,7 @@
  * Helper module for the Windows API
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_core.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_core.d)
  */
 module core.sys.windows.core;
 version (Windows):
index b040aad3eb5f187a50ed2091638e7d1f9cb17aaf..49ebb208c74eaa051ad848d8056ab20fb1a47f85 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_cpl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_cpl.d)
  */
 module core.sys.windows.cpl;
 version (Windows):
index c9452fad77c74247ca57d22ed06f29abb27ff131..e13316bcec959bcd6809e86adb8f5a6692e8e75c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_cplext.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_cplext.d)
  */
 module core.sys.windows.cplext;
 version (Windows):
index ccfc7ca4ffc203b4b5cd67c0225716499fa905c2..c736cb31a9cc51af5a25d81d9f38a21a0b15f365 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_custcntl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_custcntl.d)
  */
 module core.sys.windows.custcntl;
 version (Windows):
index a591152cf88c5b25a828eae3c61f09e0b678f4eb..308c609a9ba20c8d73cee6b31b4f2f5dce458da8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Vladimir Vlasov
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_dbt.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dbt.d)
  */
 module core.sys.windows.dbt;
 version (Windows):
index 0e062274ccfe448341241c189563b9e64aeb2a05..bec339c223c590395c829f46c9636d710b1e50b8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_dde.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dde.d)
  */
 module core.sys.windows.dde;
 version (Windows):
index 209772f6af9464b5d829c388f10bff548655c5c2..22b330cfc47f473ba7611e9db2881f8ecb7ae7e8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ddeml.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ddeml.d)
  */
 module core.sys.windows.ddeml;
 version (Windows):
@@ -16,6 +16,11 @@ pragma(lib, "user32");
 
 import core.sys.windows.basetsd, core.sys.windows.windef, core.sys.windows.winnt;
 
+mixin DECLARE_HANDLE!("HCONVLIST");
+mixin DECLARE_HANDLE!("HCONV");
+mixin DECLARE_HANDLE!("HSZ");
+mixin DECLARE_HANDLE!("HDDEDATA");
+
 enum : int {
     CP_WINANSI    = 1004,
     CP_WINUNICODE = 1200
@@ -76,10 +81,13 @@ enum : UINT {
     XTYP_SHIFT           = 4
 }
 
-/+
-#define TIMEOUT_ASYNC  0xFFFFFFFF
-#define QID_SYNC       0xFFFFFFFF
-+/
+enum : UINT {
+    TIMEOUT_ASYNC = 0xFFFFFFFF
+}
+
+enum : UINT {
+    QID_SYNC      = 0xFFFFFFFF
+}
 
 enum : UINT {
     ST_CONNECTED  =   1,
@@ -93,9 +101,9 @@ enum : UINT {
     ST_ISSELF     = 256
 }
 
-/+
-#define CADV_LATEACK 0xFFFF
-+/
+enum : UINT {
+    CADV_LATEACK  = 0xFFFF
+}
 
 enum : UINT {
     DMLERR_NO_ERROR      = 0,
@@ -121,22 +129,26 @@ enum : UINT {
     DMLERR_LAST          = DMLERR_UNFOUND_QUEUE_ID
 }
 
-/+
-#define DDE_FACK    0x8000
-#define DDE_FBUSY   0x4000
-#define DDE_FDEFERUPD   0x4000
-#define DDE_FACKREQ 0x8000
-#define DDE_FRELEASE    0x2000
-#define DDE_FREQUESTED  0x1000
-#define DDE_FAPPSTATUS  0x00ff
-#define DDE_FNOTPROCESSED   0
-#define DDE_FACKRESERVED    (~(DDE_FACK|DDE_FBUSY|DDE_FAPPSTATUS))
-#define DDE_FADVRESERVED    (~(DDE_FACKREQ|DDE_FDEFERUPD))
-#define DDE_FDATRESERVED    (~(DDE_FACKREQ|DDE_FRELEASE|DDE_FREQUESTED))
-#define DDE_FPOKRESERVED    (~DDE_FRELEASE)
-#define MSGF_DDEMGR 0x8001
-#define CBR_BLOCK   ((HDDEDATA)0xffffffff)
-+/
+enum : UINT {
+    DDE_FACK            = 0x8000,
+    DDE_FBUSY           = 0x4000,
+    DDE_FDEFERUPD       = 0x4000,
+    DDE_FACKREQ         = 0x8000,
+    DDE_FRELEASE        = 0x2000,
+    DDE_FREQUESTED      = 0x1000,
+    DDE_FAPPSTATUS      = 0x00ff,
+    DDE_FNOTPROCESSED   = 0,
+    DDE_FACKRESERVED    = (~(DDE_FACK|DDE_FBUSY|DDE_FAPPSTATUS)),
+    DDE_FADVRESERVED    = (~(DDE_FACKREQ|DDE_FDEFERUPD)),
+    DDE_FDATRESERVED    = (~(DDE_FACKREQ|DDE_FRELEASE|DDE_FREQUESTED)),
+    DDE_FPOKRESERVED    = (~DDE_FRELEASE)
+}
+
+enum : UINT {
+    MSGF_DDEMGR         = 0x8001
+}
+
+enum CBR_BLOCK = cast(HDDEDATA)-1;
 
 enum DWORD
     APPCLASS_STANDARD         = 0,
@@ -180,10 +192,13 @@ enum : UINT {
     DNS_FILTEROFF  = 8
 }
 
-/+
-#define HDATA_APPOWNED  1
-#define MAX_MONITORS    4
-+/
+enum : UINT {
+    HDATA_APPOWNED = 1
+}
+
+enum : UINT {
+    MAX_MONITORS   = 4
+}
 
 enum : int {
     MH_CREATE  = 1,
@@ -192,11 +207,6 @@ enum : int {
     MH_CLEANUP = 4
 }
 
-mixin DECLARE_HANDLE!("HCONVLIST");
-mixin DECLARE_HANDLE!("HCONV");
-mixin DECLARE_HANDLE!("HSZ");
-mixin DECLARE_HANDLE!("HDDEDATA");
-
 extern (Windows) alias HDDEDATA
   function(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, ULONG_PTR, ULONG_PTR) PFNCALLBACK;
 
index 7b412c1e7612ad45cc46b67fbcacd13f422d5462..0d3d71690b8ac0b75141ec52c746f8e18d9f6a78 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_dhcpcsdk.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dhcpcsdk.d)
  */
 module core.sys.windows.dhcpcsdk;
 version (Windows):
index 796f02720ca19f309faeffa62935742d844c51b8..34cab9bea2aec9b30d328a92f07b37d26963699e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_dlgs.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dlgs.d)
  */
 module core.sys.windows.dlgs;
 version (Windows):
index 8e9d7a07fc07b31eff801fb5fb6d63a62d7cad5a..d602347f2a3d0554ecad00fca7cc38022f5d8620 100644 (file)
@@ -6,7 +6,7 @@
  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
  *    (See accompanying file LICENSE)
  * Authors:   Rainer Schuetze
- * Source: $(DRUNTIMESRC src/core/sys/windows/_dll.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dll.d)
  */
 
 /* NOTE: This file has been patched from the original DMD distribution to
@@ -573,10 +573,10 @@ bool dll_thread_detach( bool detach_thread = true, bool exitTls = true )
 /// ---
 mixin template SimpleDllMain()
 {
-    import core.sys.windows.windef : HINSTANCE;
+    import core.sys.windows.windef : HINSTANCE, BOOL, DWORD, LPVOID;
 
     extern(Windows)
-    bool DllMain(HINSTANCE hInstance, uint ulReason, void* reserved)
+    BOOL DllMain(HINSTANCE hInstance, DWORD ulReason, LPVOID reserved)
     {
         import core.sys.windows.winnt;
         import core.sys.windows.dll :
index 89d5936f5811c4e471c67f7ff6455f32cd216ef7..4e45693eb3da4677a36f4ec631aadc0aedc69d69 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_docobj.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_docobj.d)
  */
 module core.sys.windows.docobj;
 version (Windows):
index 2b22e370ce546c8894a86afa27c8c379fd512bbf..63ec8d75746235bd94674da0590ee6cd6926842d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_errorrep.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_errorrep.d)
  */
 module core.sys.windows.errorrep;
 version (Windows):
index 1153112b5d0fd1572d315f1792a0ba9af04d7f92..8ee3c26737172740857e63d977b639773b6fa6e4 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_exdisp.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_exdisp.d)
  */
 module core.sys.windows.exdisp;
 version (Windows):
index fcf04f9945e26eb87aca088d85bfe830e10542fa..8257476cf551c766b3a128dc56e829006dc23f2b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_exdispid.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_exdispid.d)
  */
 module core.sys.windows.exdispid;
 version (Windows):
index 781d7cea74ca12e2b84ae9772df9f9d5fb0640db..4e07c6aa15c71f080f1c6a25bcb4f2c8778682eb 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_httpext.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_httpext.d)
  */
 module core.sys.windows.httpext;
 version (Windows):
index 074c3fa8b8fa8bc6c3e39b439251911738b772a4..c2d5becd8f3b27d00335e9f5ea5adf1e17921dc3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_idispids.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_idispids.d)
  */
 module core.sys.windows.idispids;
 version (Windows):
index f9edba1425f92f73cd630486c7f0058dde89b97e..ed93746d7f6b2ff39cd52baa9158dbb14fdbbe10 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_imagehlp.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_imagehlp.d)
  */
 module core.sys.windows.imagehlp;
 version (Windows):
index 3ebab30037fbd4ae450b7f0055c9ba5c170f5e41..128fd56e87ceff38392d6937b79e2f3f40c90ef2 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_imm.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_imm.d)
  */
 module core.sys.windows.imm;
 version (Windows):
index f2f44e1497d5d29e721c6d4fa16219518e095b1d..eab7a8dafe24c4821fce74c01c442a9c67a4c0d9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_intshcut.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_intshcut.d)
  */
 module core.sys.windows.intshcut;
 version (Windows):
index b66aa26e091a34f85d4360fb7028810b8bb7e2a8..dbb4a0eb5ff65e72c19d903b9d9593f0d66cca5a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ipexport.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ipexport.d)
  */
 module core.sys.windows.ipexport;
 version (Windows):
index 313e40b92c7f786e0c72db30580a68891352671d..f95e79909356714398a9c10c60ab5510ad6ffebd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_iphlpapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_iphlpapi.d)
  */
 module core.sys.windows.iphlpapi;
 version (Windows):
index b1de472f0ba4e1a9e42ea0b5aecd0874311e1982..09606f5d53379f8dbef87296276ce1d41adfca12 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ipifcons.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ipifcons.d)
  */
 module core.sys.windows.ipifcons;
 version (Windows):
index 1d23bc12cd91db392faf57d466d3e3fd8487fbac..3db453908a18da16c01b4b93b6eed11d32384b92 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_iprtrmib.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_iprtrmib.d)
  */
 module core.sys.windows.iprtrmib;
 version (Windows):
index f4f9fe80ad14eabf0b353f73f66dd9883fa5bccf..7cce34b0ebeea2603d5b52b0b11a55d668e40f65 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_iptypes.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_iptypes.d)
  */
 module core.sys.windows.iptypes;
 version (Windows):
index 61e1d1ea1438ec59fd275f722b89a4716920501e..b166c39cabcbffc623dd9e8492961dd7f7d4415a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_isguids.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_isguids.d)
  */
 module core.sys.windows.isguids;
 version (Windows):
index e12f629dceed96e599928a005866cb1cd0372ef3..3d488564e575a6f13dc0b4038fa8501e9966d02b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lm.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lm.d)
  */
 module core.sys.windows.lm;
 version (Windows):
index 3e1370d596b4f3973f891b18d19bb90efab29fa8..b23e52ed6f9bfa2fb60db3a14568c27351f91bdf 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmaccess.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmaccess.d)
  */
 module core.sys.windows.lmaccess;
 version (Windows):
index 675dc896a4af680b8f9c274163e11caf2e832d44..5ddd6d0988c7b12b0da591151cfa2190cc718feb 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmalert.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmalert.d)
  */
 module core.sys.windows.lmalert;
 version (Windows):
index f78271a2062a404912f485febab09d2f97139f0c..e8559543f3eafb51810fabd8b259549800c4a8c7 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmapibuf.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmapibuf.d)
  */
 module core.sys.windows.lmapibuf;
 version (Windows):
index 1862adf36421227b83a05084cce4f7137313a39d..3e1468a0e83f15400129ff0fb7d5a14e748faf91 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmat.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmat.d)
  */
 module core.sys.windows.lmat;
 version (Windows):
index 524332af5e0eadcd846c53b165958468fac6983e..f4a7ca243e843b3ff59ca0bf4fce8c6c61286a36 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmaudit.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmaudit.d)
  */
 // COMMENT: This file may be deprecated.
 module core.sys.windows.lmaudit;
index 971d8cdd416b4ec1fbb144e2a11b072ffbe004e6..ea0e0f38ced3bc59ed35b6bf7ec8018d6f5b4ff1 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmbrowsr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmbrowsr.d)
  */
 module core.sys.windows.lmbrowsr;
 version (Windows):
index 39d9e788ef12f9b4143ace3e32182489f949e313..00aaafcf50dac908f9c1cac5b12e25a2a4f02fbc 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmchdev.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmchdev.d)
  */
 module core.sys.windows.lmchdev;
 version (Windows):
index 6bb2472cdde74c49b5d3b629ce1516a4dabbbd53..57d3ed938fbd683ab80fc220f2fd1add568095cf 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmconfig.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmconfig.d)
  */
 module core.sys.windows.lmconfig;
 version (Windows):
index b115cce4da3831ae411e0b36436ff6e335dc8440..69a63df0f195d1207bdd9e14ccd14d04175c60dd 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmcons.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmcons.d)
  */
 module core.sys.windows.lmcons;
 version (Windows):
index 77e2378de7a45dce55fdb38ed86df7a00a2af4d2..d50ec49dcb87a6c3ef26aca391da36556a49edcd 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmerr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmerr.d)
  */
 module core.sys.windows.lmerr;
 version (Windows):
index 8e15b4df22c6f727f9ee771624c36fecb2489765..a49b49888250055e7aec776886fba92a2f8dbb3b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmerrlog.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmerrlog.d)
  */
 module core.sys.windows.lmerrlog;
 version (Windows):
index 2a2d60ade06cb7b8c6214d237426ccb91412f28b..c87f1e00ed39d999604f18e9885926c7f4606f8f 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmmsg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmmsg.d)
  */
 module core.sys.windows.lmmsg;
 version (Windows):
index ce7d45aa34963503a9775f5699802b4d10d0f2dc..d0f3b41cc38886fd12a30110cc895b3f9db2971b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmremutl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmremutl.d)
  */
 module core.sys.windows.lmremutl;
 version (Windows):
index 02345f81105232389e61abfc7939bba36a7199ef..093588ca84e935526154a6eb8d92ca5609e54a99 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmrepl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmrepl.d)
  */
 module core.sys.windows.lmrepl;
 version (Windows):
index 83a9a84adda5247f1c2f2d7bf558051f0d267869..fad5bc509c4d2a60e81264e179e495670d11ab8a 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmserver.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmserver.d)
  */
 module core.sys.windows.lmserver;
 version (Windows):
index 215fb781e6639a1573b69779e5c35030e9c01536..d81080edda1b7a474dac59f877f366d3c350cd27 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmshare.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmshare.d)
  */
 module core.sys.windows.lmshare;
 version (Windows):
index bdb1a6d3dcca000861441cc474df96ae4c3187e0..09b1b00cb6d5063da0a7ec7d218fd8bac9b03887 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmsname.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmsname.d)
  */
 module core.sys.windows.lmsname;
 version (Windows):
index 0c6e622aab4575135a85b915f7df50b51c101efc..4baa3903b158bc82922cea4882cc5b5f8b772b10 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmstats.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmstats.d)
  */
 module core.sys.windows.lmstats;
 version (Windows):
index 1743458007d6c3f9cb329ebab2a66d1fff919532..c0df69902e02fd7d70c3b48623e98ed892b21383 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmsvc.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmsvc.d)
  */
 module core.sys.windows.lmsvc;
 version (Windows):
index a9dbcd40b637cbe9206385765e4bf8c1fc35ff7b..03e153abea87ea0a090814e23935f66f9d01e028 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmuse.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmuse.d)
  */
 module core.sys.windows.lmuse;
 version (Windows):
index 8157abd04ec3f6822243be34c9d0167d18466bfa..06276c3e44486efebbaacf1809023637f522b1ba 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.10
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmuseflg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmuseflg.d)
  */
 module core.sys.windows.lmuseflg;
 version (Windows):
index f4d85fef47b6a786458623dcc2f0e8be83cebdb3..cdd3a0703658e80f1d0111794282d15a0f6964f0 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lmwksta.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lmwksta.d)
  */
 module core.sys.windows.lmwksta;
 version (Windows):
index 32ab1410b38a0a0e1411ff848a1398dc71e10d9b..a01489bef57ed0cbf1796ce6d2ff7230b79ac20e 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_lzexpand.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_lzexpand.d)
  */
 module core.sys.windows.lzexpand;
 version (Windows):
index 194f63bcc74516a4cd65ebc654f48c62921aea58..06fd955611caa6091301a58f78dc6ae3015dfa07 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mapi.d)
  */
 module core.sys.windows.mapi;
 version (Windows):
index f7367e3caa3cad9077179d097bdbce4dd9ddddb2..4e3d14e0b6a346b82fb8cc47fc1f2bd91541cc45 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mciavi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mciavi.d)
  */
 module core.sys.windows.mciavi;
 version (Windows):
index 01b28ad38558e1bc2a3b7a7bdb733e9bb3d6b82c..0322413013702566c22c8bac99405c7207ffea7f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mcx.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mcx.d)
  */
 module core.sys.windows.mcx;
 version (Windows):
index 673fba8c37e5d0027c15f06a08f0c35b19549ef7..d9fb6b72a9c09fd0a12f82c5a42f55b0f978aa36 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mgmtapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mgmtapi.d)
  */
 module core.sys.windows.mgmtapi;
 version (Windows):
index 9359afd0e0351b14a6969b7ed45fc8572fa59e37..5c3d92071181f15be55733282376c1bd9824e633 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mmsystem.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mmsystem.d)
  */
 module core.sys.windows.mmsystem;
 version (Windows):
index b5d3052d7c656655a1d9b34cf5ab32f7ac0c27b4..47263282fb19793da546177da56ca7ff908ab193 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_msacm.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_msacm.d)
  */
 module core.sys.windows.msacm;
 version (Windows):
index 2c4410d6bf37cb42ff5e0567096dde4a01d71f26..d5cf7cbc012fca836cea7ad5c89ec855f06a3965 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mshtml.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mshtml.d)
  */
 module core.sys.windows.mshtml;
 version (Windows):
index cd6b63c197c3245dfda7b27943311b140383e26e..27c0cdb5bb2f792561d4beff2334efb55478dd80 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Daniel Keep
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_mswsock.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_mswsock.d)
  */
 module core.sys.windows.mswsock;
 version (Windows):
index 0d250cc40af16907217584e39bb7977dc6d36b01..8f92eddba1789b37c5213d25063248e1fec0c081 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_nb30.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_nb30.d)
  */
 module core.sys.windows.nb30;
 version (Windows):
index d4692c9db8adb41b9823e1fb931024ddfa3b1bb5..dc3890c61181780dc45ee338377e24645aec4657 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_nddeapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_nddeapi.d)
  */
 module core.sys.windows.nddeapi;
 version (Windows):
index a2e7fab02f67911a1cbb192bbf0b524e71b739ca..79c9fceb45c9ef0fb72de35a55dff6356b718fcb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_nspapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_nspapi.d)
  */
 module core.sys.windows.nspapi;
 version (Windows):
index 83d668c0eebff6e346d4db50940c371c6168af2d..78e60e77749ddcd09651c97c4427907544e1c0af 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ntdef.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ntdef.d)
  */
 module core.sys.windows.ntdef;
 version (Windows):
index e8aa3a7b4ca5305ab4123b4734251fa4ef8a0724..4ac1bcccbb9888f468b134adfad063ffd4681707 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ntdll.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ntdll.d)
  */
 module core.sys.windows.ntdll;
 version (Windows):
index e7a55dd2f7688754753952e37a3984eb88dcef52..52caddec763434a53458ee3547b028a515de62b4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ntldap.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ntldap.d)
  */
 module core.sys.windows.ntldap;
 version (Windows):
index df9c10a3bb25cab020cc9dc7df8d27217257c8da..1118057b4c9b83f71d76ddd14a0843229ae670e2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ntsecapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ntsecapi.d)
  */
 module core.sys.windows.ntsecapi;
 version (Windows):
index 8625b7ae039f48582edf6f960494b4483c3f0af3..d4c93d7b57366d5d5361168b95c4d73d90633b6a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Ellery Newcomer
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ntsecpkg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ntsecpkg.d)
  */
 module core.sys.windows.ntsecpkg;
 version (Windows):
index 51d6be904df6b93317db1b329c90cf517c82e111..6c9368241f128226ef9a5a57bd21c2ba0968de39 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_oaidl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_oaidl.d)
  */
 module core.sys.windows.oaidl;
 version (Windows):
index 961ebcc833ac15dad9ed285639351f88e8473a7c..3695ea60021192a437b0db7fc653b2c15a7329fa 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_objbase.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_objbase.d)
  */
 module core.sys.windows.objbase;
 version (Windows):
index 76d4f4144c58861c672dbb467441cad25dbd7b76..89d5cad90dbadbc50dfc571a1d633668235a6dab 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_objfwd.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_objfwd.d)
  */
 module core.sys.windows.objfwd;
 version (Windows):
index 5368c296c373e253c77c83b689041d9037ebd3cb..528c58b278988280f0a0a0dfb6a6a3c2fa861967 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_objidl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_objidl.d)
  */
 // TODO (Don):
 // # why is "alias IPSFactoryBuffer* LPPSFACTORYBUFFER;" in this file,
index 0bfd19a0fd523ea1d34a4e8a13018429e859b9b4..449a4c3166dfcd79e72629097bf898de4fe97ea8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_objsafe.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_objsafe.d)
  */
 module core.sys.windows.objsafe;
 version (Windows):
index 4b090b0a005f94305b531d3eea9a02a04f346270..af42beaf159dd2bb5d11e372ab5af217239b2a9f 100644 (file)
@@ -6,7 +6,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ocidl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ocidl.d)
  */
 module core.sys.windows.ocidl;
 version (Windows):
index ee22bc6a86b02a262827e8478e0a176f1f5a5e13..b0ca42adf12410c5d41126f4f2ecb5af79011898 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_odbcinst.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_odbcinst.d)
  */
 module core.sys.windows.odbcinst;
 version (Windows):
index 1a49ea51cd4750b5e674e637cb323c79569950bb..21218f11605e39d695530c59110aad62fb25a2fb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ole.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ole.d)
  */
 module core.sys.windows.ole;
 version (Windows):
index 575a8eb8d611dffbf294823df66466acf043b3a9..0945fcaca260e6d9ade7e10d5a3850d6d412dd5d 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ole2.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ole2.d)
  */
 module core.sys.windows.ole2;
 version (Windows):
index 9e3badcaed9e03046b9b4f2192bec6a662e9c41a..6a549e6df423734d537b0b58919212658f5822c5 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.10
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ole2ver.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ole2ver.d)
  */
 module core.sys.windows.ole2ver;
 version (Windows):
index 77ced02dc0b949816b585c2819cf3b376457bd12..77137c6b6174d80fe58c407014ee0baa94a76059 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_oleacc.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_oleacc.d)
  */
 module core.sys.windows.oleacc;
 version (Windows):
index 20f34aff5a73165f1ab3573a374fca9ca5db458c..f8d76e15bef2cdad5e738ff896474cedb9c583db 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_oleauto.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_oleauto.d)
  */
 module core.sys.windows.oleauto;
 version (Windows):
index e0bc679f9290ad73dc94d07c037cafac9c164290..f671ce44804af7acd3e62dae1e6bdf9212c13e20 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_olectl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_olectl.d)
  */
 module core.sys.windows.olectl;
 version (Windows):
index fd3ea899a2a42ce05dcd9e07779adaf055723d12..8bbe657134b959a82953ce1aec5cd18ea51191bd 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_olectlid.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_olectlid.d)
  */
 module core.sys.windows.olectlid;
 version (Windows):
index e44c02901622184dd733dd1e3968a311e81ca1a4..f1a05104d43a92ebd9c1e83271bcdfdffd29e34c 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_oledlg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_oledlg.d)
  */
 module core.sys.windows.oledlg;
 @system:
index dc0cae85de30c996cc5c8cdc993e6e078280f4a9..4ef564d20a53dd8829f63fe0e1c5ab55193c73e0 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_oleidl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_oleidl.d)
  */
 module core.sys.windows.oleidl;
 version (Windows):
index aec938e9b824aeeafb1a4ed8ac62d0dad3a5a178..3b65ba586494ceb3ddf8743f5976daff72e4d740 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_pbt.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_pbt.d)
  */
 module core.sys.windows.pbt;
 version (Windows):
index 75ec73e8efed06092c78614f34d2a5d60f867b63..275dbeabd0785734ca4c1482b6119165a27285e9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_powrprof.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_powrprof.d)
  */
 module core.sys.windows.powrprof;
 version (Windows):
index efea4f254c43b5bd98248b5de20ea011e00ca59a..ba04b5743c4f5961648af2a419f91db18acb26f8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Vladimir Vlasov
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_prsht.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_prsht.d)
  */
 module core.sys.windows.prsht;
 version (Windows):
index 7e62d9fc1bd1199ca018234c9af034fa138c8a85..585f908881394c5e13daef6a549f70685f1c8e3a 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_psapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_psapi.d)
  */
 /* Comment from MinGW
  *   Process status API (PSAPI)
index 6c48f6bff26521d1a1d4eab6ca70b728eba18e89..086b7a6023b663bc9db8b3536fab23321e49517c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rapi.d)
  */
 module core.sys.windows.rapi;
 version (Windows):
index 1004c6b63f8e6e89fc4745fab226efb8d2f87fe2..1f665461b9ccd22443fcfaad5eba6f4740490d13 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_ras.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_ras.d)
  */
 module core.sys.windows.ras;
 version (Windows):
index 8304a0141294257c5fa980d2fd972b0d1485f977..1add3ae1479b9ced6cb41be7cf93be842c98461d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rasdlg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rasdlg.d)
  */
 module core.sys.windows.rasdlg;
 version (Windows):
index 43bebacd34ef6b1068162acae1ccef9a18cc1b91..c21409b379bc8305dfa7d3fa9e830b960c0d5364 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_raserror.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_raserror.d)
  */
 module core.sys.windows.raserror;
 version (Windows):
index 0eaa5b28f5b27ab38fcb42f97882acfc3e1b47d0..aed14f162f865ff9e641c290e9346d08083ccfba 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rassapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rassapi.d)
  */
 module core.sys.windows.rassapi;
 version (Windows):
index b0c49693e187c5ce1c3def0f34ada0186aaaed9b..4274efa33ed60e8443ce85decc076ecb7a751825 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_reason.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_reason.d)
  */
 module core.sys.windows.reason;
 version (Windows):
index 1fa1c7e0d7f80b2150b9e14d058fa7272054eba2..71a86ef870018ebfe2e85bdaed4ae2dd9afffe4e 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_regstr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_regstr.d)
  */
 module core.sys.windows.regstr;
 version (Windows):
index 1abc8f3fd2ad39cf516b0dffa040af080f942dfd..676076480c4628da73905371d223eae9afc03a3b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_richedit.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_richedit.d)
  */
 module core.sys.windows.richedit;
 version (Windows):
index a4e64e83b7510d95b0813b32ef5d8485f57ce347..288ef220a8533c7b8dc02cad4677cef9f91b597c 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_richole.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_richole.d)
  */
 module core.sys.windows.richole;
 version (Windows):
index 5922123439232f3757b0e67806fcd36698c66dfd..a9640ada476d27dbb438cdc747b5360101879bc2 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpc.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpc.d)
  */
 module core.sys.windows.rpc;
 version (Windows):
index cdffbcf0e5c8d3897cdee2e4aca068e06eae4145..1eccb0dcf23ed0363afe92b024ff4c5c0b292fd0 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcdce.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcdce.d)
  */
 module core.sys.windows.rpcdce;
 version (Windows):
index 10ec910faaea12b7f7a51d2a582a0a4d60d99039..c8223f6cd5b8528cd7b2dbb60a41979b750b3dd5 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcdce2.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcdce2.d)
  */
 module core.sys.windows.rpcdce2;
 version (Windows):
index fe22bf8c7240549c3c22d54a236fb112805f15a1..1abbb78852d07e00d4826ab01c8b0d5faf90f5d9 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcdcep.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcdcep.d)
  */
 module core.sys.windows.rpcdcep;
 version (Windows):
index 6720b94aa9d030b5a2a30b5ccdc60656485784ce..6e9722c984fae22212b39ebff1e5f79733d708e7 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcndr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcndr.d)
  */
 module core.sys.windows.rpcndr;
 version (Windows):
index 2ecae63aefe738ec393faa33885c04abf64f38bd..608b92cead2b0a24a734e4ca3e0d28ece1ee631c 100644 (file)
@@ -6,7 +6,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcnsi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcnsi.d)
  */
 module core.sys.windows.rpcnsi;
 version (Windows):
index 1c0f050df754dc59fc6464111540895bda9557dd..219d7b007d820c0a695e95378f53ada31210794e 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcnsip.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcnsip.d)
  */
 module core.sys.windows.rpcnsip;
 version (Windows):
index dcd63ab454f5a8cfc40be6413b3e1fc8abd440b7..426077aabe544d0eeb34d275f511bd792f864d2b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_rpcnterr.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_rpcnterr.d)
  */
 module core.sys.windows.rpcnterr;
 version (Windows):
index 1d2fbda7ddb9364fdbdc55f57e79aff68f148cbc..98c5cf800232bce7e174834ec29a772e5c489740 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_schannel.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_schannel.d)
  */
 module core.sys.windows.schannel;
 version (Windows):
index 3af3c86d2c03a270ac46aeee2cc2352fec2d27e9..4b5bad52822180a639d3421e4a8188667da8463c 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from Windows SDK API
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/sdkddkver.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/sdkddkver.d)
  */
 module core.sys.windows.sdkddkver;
 
index dd4ec8589a6f84cbae748b9f99a2137a2fd0a1be..6b92fcddf757e6c3947728b285dfc6ed394f31fc 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_secext.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_secext.d)
  */
 // Don't include this file directly, use core.sys.windows.security instead.
 module core.sys.windows.secext;
index 2dc7c19497571d89a81c91b68d4fb15b4e3ce058..b81abb3fe2dd23d28aacdb8d56f293e20105ceb5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Ellery Newcomer, John Colvin
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_security.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_security.d)
  */
 module core.sys.windows.security;
 version (Windows):
index 1c061dd87469f6df3e7a2084a378896cde745d3e..89ab47c97cb77b9b33787fef3efa76e32b3801e9 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.10
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_servprov.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_servprov.d)
  */
 module core.sys.windows.servprov;
 version (Windows):
index 432ff3546427a1cd6e83bcb7275e971ba4d4209f..80e8dbaf9614d28f42ae3e846836335bd5a8f14a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Vladimir Vlasov
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_setupapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_setupapi.d)
  */
 module core.sys.windows.setupapi;
 version (Windows):
index 2b7f1456d22f82462c0393aed0c979e57116d915..f4019979b3cb2ca0bf3f7be8e09cd5e7b837d711 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_shellapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_shellapi.d)
  */
 module core.sys.windows.shellapi;
 version (Windows):
index 70cf88428c76e7399fa11603ff03a8ebfae2ae2c..ecb0edee87601c692b18048e9e8938cb6fb6d289 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_shldisp.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_shldisp.d)
  */
 module core.sys.windows.shldisp;
 version (Windows):
index 15e6138b2f4e1c9b579fa44496885e3146a9ce56..1c0c98fc0700f465f2b21a1720ff468db350d8fd 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_shlguid.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_shlguid.d)
  */
 module core.sys.windows.shlguid;
 version (Windows):
index 5f921b3ca1ab83666992a0bc0adae97429085bb5..75ac6226306b3875cef60da3b002e4b1050ff63e 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 4.0
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_shlobj.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_shlobj.d)
  */
 module core.sys.windows.shlobj;
 version (Windows):
index 8cb21ef4a4a89612d2bdfe49113796b5ba181716..d1a61a3844f0d0dcca6a44206f34c50de35c2110 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_shlwapi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_shlwapi.d)
  */
 module core.sys.windows.shlwapi;
 version (Windows):
index ea64e0d86b58ca48d89e3e345a4d244ff9d4e384..bf56b28c02bbb175e985a131b6c62ad3a16620aa 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_snmp.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_snmp.d)
  */
 module core.sys.windows.snmp;
 version (Windows):
index 177a48dc0c32e0e2851d795d06f7b29226a8fad3..7c8758efccb915528dce83d0e800ff881c292dcd 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_sql.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_sql.d)
  */
 module core.sys.windows.sql;
 version (Windows):
index 1f891056a821a001e0a993b8faa085748c563007..2ddff2012796ee7f2bf13f52b3351ae5c28ab8c2 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_sqlext.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_sqlext.d)
  */
 module core.sys.windows.sqlext;
 version (Windows):
index aaffeb225856311ce8eb9549f2dd1ad3e03f3db0..fd77b819a5e19bf73a0e1ceea0d7205a540e5ec0 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_sqltypes.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_sqltypes.d)
  */
 module core.sys.windows.sqltypes;
 version (Windows):
index 21f47f6f54ee96ed15c9d3c33847974b55278605..85f0d0603c8fefdd2c66abe4775bc911db493bf0 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_sqlucode.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_sqlucode.d)
  */
 module core.sys.windows.sqlucode;
 version (Windows):
index cf41298a631ad4f74a22aa1af3d850df792d83ee..07a259622d26eef81b2285b688b1d324686027ed 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Ellery Newcomer
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_sspi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_sspi.d)
  */
 module core.sys.windows.sspi;
 version (Windows):
index f52ba37f27efdf4245765f59b068622198dfabe7..278c9fe6fc8b34c9ec1c6046b28e8a94a6689e1d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Iain Buclaw
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/stdc/_malloc.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/stdc/_malloc.d)
  */
 module core.sys.windows.stdc.malloc;
 version (CRuntime_Microsoft):
index 42d2fa73cf8cfd25373398c5803d19b29c7bc939..e0d67ffdcee928ee87cc5425ad30044c5ec7cead 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_subauth.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_subauth.d)
  */
 module core.sys.windows.subauth;
 version (Windows):
index 308c5a46cc140a0de2bd28970878ad23fdbd8761..34ed1013ea9e32d6fbcca27fceeec31d4148ddde 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_tlhelp32.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_tlhelp32.d)
  */
 module core.sys.windows.tlhelp32;
 version (Windows):
index ea7863a97b6c945289ad9858d52c099b4c6aa596..b82dc5c84f34688df89a2643dad6dc6a7ed10054 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_tmschema.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_tmschema.d)
  */
 module core.sys.windows.tmschema;
 version (Windows):
index 1c3e4539f0171791059292cf4a9f374cddc4d67a..49d5abf01b64b4414ee90c9734411aa06add2ae9 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_unknwn.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_unknwn.d)
  */
 module core.sys.windows.unknwn;
 version (Windows):
index 3ffff20134735e534778821e07ed2acf4dc76ce1..c67753a42e6e2cdea81fc00ae6562b8edfd38b0c 100644 (file)
@@ -4,7 +4,7 @@
  * written in the D programming language
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_vfw.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_vfw.d)
  */
 
 module core.sys.windows.vfw;
index a392d591a4c8671b9530c9ca852f7d615c49cdfa..2752da1adc8f408e3b7d1624293b90e9f814c976 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_w32api.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_w32api.d)
  */
 module core.sys.windows.w32api;
 version (Windows):
index a9844de450bc3a13cf790fb503999f01f8e36731..1806796b34dfaaf426ab5ec7c2bc04454b83216b 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.10
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winbase.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winbase.d)
  */
 module core.sys.windows.winbase;
 version (Windows):
index 27189038826c22dd8046d7fb276f0324bd811906..d6a79cd3542dcba09f1d4fba183d88fdf33dbe61 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winber.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winber.d)
  */
 module core.sys.windows.winber;
 version (Windows):
index 67bd17e7d09cecd04b39466d93bc19177cd6dded..a404c5c2d696d87e718ffda24da879f79c52019f 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wincon.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wincon.d)
  */
 module core.sys.windows.wincon;
 version (Windows):
index 94951057e688167ffa0fcb803eda88db4b838b23..d6c617d2f147ec4539190417cb4a68bec1dabf7f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wincrypt.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wincrypt.d)
  */
 module core.sys.windows.wincrypt;
 version (Windows):
index f79b593c518ab5f78db9cc4f89c7c2c42c9e3563..31af66a25015c1295122d3de8a1c85783be9615c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_windef.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_windef.d)
  */
 module core.sys.windows.windef;
 version (Windows):
index 8b8c8ab35543441a182f0db48a9fe695b4572ccc..4a1b02f9a86603178069c3e77f9563dabb240742 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 4.0
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_windows.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_windows.d)
  */
 module core.sys.windows.windows;
 version (Windows):
index ab987a3e81a4802b0df66b87ff24da5e759cc54a..a26b05c1d2f191027d0f168399d3b66e4b983663 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winerror.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winerror.d)
  */
 module core.sys.windows.winerror;
 version (Windows):
index 4fc125c62257812648e7c4f0f719e58c0b55645b..279f6be627bf8d61dce7dbff1b2ccad00267e4fc 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wingdi.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wingdi.d)
  */
 module core.sys.windows.wingdi;
 version (Windows):
index e919635e4ed3a5b36d5db5ae797d9bca97693842..f66580508aaab937fd7a9d797ead4d9f5550b9ef 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from Windows SDK Headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winhttp.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winhttp.d)
  */
 module core.sys.windows.winhttp;
 version (Windows):
index 64b95c4c00e1c4e798201be85bda0b02ed2150ab..f4aa997b162229bc5df9391ac50bb7ef2bc2b8b3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wininet.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wininet.d)
  */
 module core.sys.windows.wininet;
 version (Windows):
index 84d498e772fe90248f2ff2c98ac4842bba441484..b91ddda1d9338d20de7b159965d615f8ac90c301 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winioctl.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winioctl.d)
  */
 module core.sys.windows.winioctl;
 version (Windows):
index 78578dd51dd2708b74464ecbda11ccea01362e4a..0ab11d68d5c5285cd0c157af770d345699fc5088 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winldap.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winldap.d)
  */
 module core.sys.windows.winldap;
 version (Windows):
index 7601279005fa8570893279ada769aaa68f53c775..e0c7551096c262d789f736722f0441642c6a1a3a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winnetwk.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winnetwk.d)
  */
 module core.sys.windows.winnetwk;
 version (Windows):
index 6483f4bcc02310c368c16274b0f637107d30adc3..b487a17894fa299c0ff6d63dd929f3b7049a1adc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winnls.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winnls.d)
  */
 module core.sys.windows.winnls;
 version (Windows):
index 2d9a28121e9aa9720aec24881d3592474f50cc5a..bf30072fa8a40c6024607c718421c193e372c46f 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW API for MS-Windows 3.12
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winnt.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winnt.d)
  */
 module core.sys.windows.winnt;
 version (Windows):
index 367c2b095613c784209502431b3459049ab17692..cd31990baef5ad0f168b7d4b31405bbffd9865be 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winperf.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winperf.d)
  */
 module core.sys.windows.winperf;
 version (Windows):
index 078bdf7037e9da226b7075d8d3febd8c384a3feb..c3e58545b3d22e1e9c25912bd1bb820af777504b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winreg.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winreg.d)
  */
 module core.sys.windows.winreg;
 version (Windows):
index db5b23f6eb228089a53564a98c3c63037018c951..2ff621adf1a4ed590333bce844ce7c7ccb09b28f 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winspool.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winspool.d)
  */
 module core.sys.windows.winspool;
 version (Windows):
index 44c4563aab6850172977fa11c8d4ec2657dffc68..14ab6e42159aaa5c809a1acb705301574b8261b7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winsvc.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winsvc.d)
  */
 module core.sys.windows.winsvc;
 version (Windows):
index 07e5efaa33d08f6fceb9c0671aa50225db3c94eb..078e0610b5e068e4d77435b2fdbb879e2edfb01a 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winuser.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winuser.d)
  */
 module core.sys.windows.winuser;
 version (Windows):
index afe53d8f7ccf7a633748038d1971c1eeb208c4ed..5099c3f51f244c85407d31c08c07cd1b068a722f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Authors: Stewart Gordon
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_winver.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_winver.d)
  */
 module core.sys.windows.winver;
 version (Windows):
index 643c049c25c0bbf1dc6b3159a71612d74e22a9cf..13576bdd1128bcb25200a0fd88a4db1f8597edd5 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW-w64 API
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wtsapi32.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wtsapi32.d)
  */
 module core.sys.windows.wtsapi32;
 version (Windows):
index 8af42cf71792749283e45bcddcccca7a0f44332a..c27dd3a3f3adcbd86a12e27bb627f0bd3a556a3c 100644 (file)
@@ -4,7 +4,7 @@
  * Translated from MinGW Windows headers
  *
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(DRUNTIMESRC src/core/sys/windows/_wtypes.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_wtypes.d)
  */
 module core.sys.windows.wtypes;
 version (Windows):
index 56f6d67d5810fc27b5ecd6d422e97a6d4f208949..bd53eed2d1008e3bf2a84d47c86227fa292971f1 100644 (file)
@@ -1043,10 +1043,14 @@ private:
                 // Allocate more for the memory guard
                 sz += guardPageSize;
 
+                int mmap_flags = MAP_PRIVATE | MAP_ANON;
+                version (OpenBSD)
+                    mmap_flags |= MAP_STACK;
+
                 m_pmem = mmap( null,
                                sz,
                                PROT_READ | PROT_WRITE,
-                               MAP_PRIVATE | MAP_ANON,
+                               mmap_flags,
                                -1,
                                0 );
                 if ( m_pmem == MAP_FAILED )
@@ -1894,7 +1898,7 @@ unittest
 
     try
     {
-        (new Fiber({
+        (new Fiber(function() {
             throw new Exception( MSG );
         })).call();
         assert( false, "Expected rethrown exception." );
index c9bc1305ad06a1e52675b05b61cb67ac2ceccdd3..b7dde9387afd44844782b53d1b6081de9bdf679c 100644 (file)
@@ -1109,6 +1109,7 @@ unittest
     try
     {
         new Thread(
+        function()
         {
             throw new Exception( MSG );
         }).start().join();
index 26e515bc8b4533c51446fd7d550cbf8ea7d1906c..0ddf62f478c5a80bf0b200d53765117d3c6af67e 100644 (file)
@@ -1196,8 +1196,8 @@ public:
       +/
     template split(units...)
         if (allAreAcceptedUnits!("weeks", "days", "hours", "minutes", "seconds",
-                                "msecs", "usecs", "hnsecs", "nsecs")(units) &&
-           unitsAreInDescendingOrder(units))
+                                "msecs", "usecs", "hnsecs", "nsecs")([units]) &&
+           unitsAreInDescendingOrder([units]))
     {
         /++ Ditto +/
         void split(Args...)(out Args args) const nothrow @nogc
@@ -3709,7 +3709,7 @@ unittest
 /+
     Whether all of the given strings are among the accepted strings.
   +/
-bool allAreAcceptedUnits(acceptedUnits...)(string[] units...)
+bool allAreAcceptedUnits(acceptedUnits...)(scope string[] units)
 {
     foreach (unit; units)
     {
@@ -3730,12 +3730,12 @@ bool allAreAcceptedUnits(acceptedUnits...)(string[] units...)
 
 unittest
 {
-    assert(allAreAcceptedUnits!("hours", "seconds")("seconds", "hours"));
-    assert(!allAreAcceptedUnits!("hours", "seconds")("minutes", "hours"));
-    assert(!allAreAcceptedUnits!("hours", "seconds")("seconds", "minutes"));
-    assert(allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")("minutes"));
-    assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")("usecs"));
-    assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")("secs"));
+    assert(allAreAcceptedUnits!("hours", "seconds")(["seconds", "hours"]));
+    assert(!allAreAcceptedUnits!("hours", "seconds")(["minutes", "hours"]));
+    assert(!allAreAcceptedUnits!("hours", "seconds")(["seconds", "minutes"]));
+    assert(allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["minutes"]));
+    assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["usecs"]));
+    assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["secs"]));
 }
 
 
@@ -3743,7 +3743,7 @@ unittest
     Whether the given time unit strings are arranged in order from largest to
     smallest.
   +/
-bool unitsAreInDescendingOrder(string[] units...)
+bool unitsAreInDescendingOrder(scope string[] units)
 {
     if (units.length <= 1)
         return true;
@@ -3783,13 +3783,13 @@ bool unitsAreInDescendingOrder(string[] units...)
 
 unittest
 {
-    assert(unitsAreInDescendingOrder("years", "months", "weeks", "days", "hours", "minutes",
-                                     "seconds", "msecs", "usecs", "hnsecs", "nsecs"));
-    assert(unitsAreInDescendingOrder("weeks", "hours", "msecs"));
-    assert(unitsAreInDescendingOrder("days", "hours", "minutes"));
-    assert(unitsAreInDescendingOrder("hnsecs"));
-    assert(!unitsAreInDescendingOrder("days", "hours", "hours"));
-    assert(!unitsAreInDescendingOrder("days", "hours", "days"));
+    assert(unitsAreInDescendingOrder(["years", "months", "weeks", "days", "hours", "minutes",
+                                     "seconds", "msecs", "usecs", "hnsecs", "nsecs"]));
+    assert(unitsAreInDescendingOrder(["weeks", "hours", "msecs"]));
+    assert(unitsAreInDescendingOrder(["days", "hours", "minutes"]));
+    assert(unitsAreInDescendingOrder(["hnsecs"]));
+    assert(!unitsAreInDescendingOrder(["days", "hours", "hours"]));
+    assert(!unitsAreInDescendingOrder(["days", "hours", "days"]));
 }
 
 version (Darwin)
index 151755feed093be4183be0d0cb8065ddc3e23f7b..a079e0e73e998cb5a844bba00a0f72a4ed37d1e3 100644 (file)
@@ -2446,7 +2446,7 @@ class Throwable : Object
     override string toString()
     {
         string s;
-        toString((buf) { s ~= buf; });
+        toString((in buf) { s ~= buf; });
         return s;
     }
 
@@ -4752,3 +4752,79 @@ template _arrayOp(Args...)
 }
 
 public import core.builtins : __ctfeWrite;
+
+/**
+
+Provides an "inline import", i.e. an `import` that is only available for a
+limited lookup. For example:
+
+---
+void fun(imported!"std.stdio".File input)
+{
+    ... use File from std.stdio normally ...
+}
+---
+
+There is no need to import `std.stdio` at top level, so `fun` carries its own
+dependencies. The same approach can be used for template constraints:
+
+---
+void fun(T)(imported!"std.stdio".File input, T value)
+if (imported!"std.traits".isIntegral!T)
+{
+    ...
+}
+---
+
+An inline import may be used in conjunction with the `with` statement as well.
+Inside the scope controlled by `with`, all symbols in the imported module are
+made available:
+
+---
+void fun()
+{
+    with (imported!"std.datetime")
+    with (imported!"std.stdio")
+    {
+        Clock.currTime.writeln;
+    }
+}
+---
+
+The advantages of inline imports over top-level uses of the `import` declaration
+are the following:
+
+$(UL
+$(LI The `imported` template specifies dependencies at declaration level, not at
+module level. This allows reasoning about the dependency cost of declarations in
+separation instead of aggregated at module level.)
+$(LI Declarations using `imported` are easier to move around because they don't
+require top-level context, making for simpler and quicker refactorings.)
+$(LI Declarations using `imported` scale better with templates. This is because
+templates that are not instantiated do not have their parameters and constraints
+instantiated, so additional modules are not imported without necessity. This
+makes the cost of unused templates negligible. Dependencies are pulled on a need
+basis depending on the declarations used by client code.)
+)
+
+The use of `imported` also has drawbacks:
+
+$(UL
+$(LI If most declarations in a module need the same imports, then factoring them
+at top level, outside the declarations, is simpler than repeating them.)
+$(LI Traditional dependency-tracking tools such as make and other build systems
+assume file-level dependencies and need special tooling (such as rdmd) in order
+to work efficiently.)
+$(LI Dependencies at the top of a module are easier to inspect quickly than
+dependencies spread throughout the module.)
+)
+
+See_Also: The $(HTTP forum.dlang.org/post/tzqzmqhankrkbrfsrmbo@forum.dlang.org,
+forum discussion) that led to the creation of the `imported` facility. Credit is
+due to Daniel Nielsen and Dominikus Dittes Scherkl.
+
+*/
+template imported(string moduleName)
+{
+    mixin("import imported = " ~ moduleName ~ ";");
+}
index 6db653047d360a241d8458171d88b0a021d88711..7f19fa81528752710d9c623d3f268018f5da3a97 100644 (file)
@@ -8,19 +8,8 @@
  * Authors:   Walter Bright, Sean Kelly
  * Source: $(DRUNTIMESRC rt/_aApplyR.d)
  */
-
-/*          Copyright Digital Mars 2004 - 2010.
- * Distributed under the Boost Software License, Version 1.0.
- *    (See accompanying file LICENSE or copy at
- *          http://www.boost.org/LICENSE_1_0.txt)
- */
 module rt.aApplyR;
 
-/* This code handles decoding UTF strings for foreach_reverse loops.
- * There are 6 combinations of conversions between char, wchar,
- * and dchar, and 2 of each of those.
- */
-
 import core.internal.utf;
 
 /**********************************************/
index 01810536a495e03e283c0d25510b76225bb053a3..6ff93f76da432dfbd16b6c2338924170d03ba351 100644 (file)
@@ -833,11 +833,9 @@ extern (C) hash_t _aaGetHash(scope const AA* paa, scope const TypeInfo tiRaw) no
     size_t h;
     foreach (b; aa.buckets)
     {
-        if (!b.filled)
-            continue;
-        size_t[2] h2 = [keyHash(b.entry), valHash(b.entry + off)];
         // use addition here, so that hash is independent of element order
-        h += hashOf(h2);
+        if (b.filled)
+            h += hashOf(valHash(b.entry + off), keyHash(b.entry));
     }
 
     return h;
index 328452e2431b60a392631d22313da5ac6cdeffab..b363e3fea4fc55d9f6941030dc808e5129bd38c2 100644 (file)
@@ -538,7 +538,7 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF
     return result;
 }
 
-private void formatThrowable(Throwable t, scope void delegate(const scope char[] s) nothrow sink)
+private void formatThrowable(Throwable t, scope void delegate(in char[] s) nothrow sink)
 {
     foreach (u; t)
     {
@@ -667,7 +667,7 @@ extern (C) void _d_print_throwable(Throwable t)
         }
     }
 
-    void sink(const scope char[] buf) scope nothrow
+    void sink(in char[] buf) scope nothrow
     {
         fprintf(stderr, "%.*s", cast(int)buf.length, buf.ptr);
     }
index 927d3ee874a648058438229b9c815b7ad4378cec..29bcf33c01f2713945edf739aca96c9619fbfc30 100644 (file)
@@ -1,4 +1,4 @@
-5ab9ad2561cea35ac33ebc0452c0e6a8d762f27d
+574bf883b790340fb753d6542ec48a3ba3e6cb82
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
index ba1579da8d7f2cf915a947291666ecef65bba17c..c584b5aec0d99099a8500a093c8a78cff619887c 100644 (file)
@@ -19,8 +19,9 @@
 include $(top_srcdir)/d_rules.am
 
 # Make sure GDC can find libdruntime and libphobos include files
-D_EXTRA_DFLAGS=-fpreview=dip1000 -fpreview=dtorfields -nostdinc -I $(srcdir) \
-       -I $(top_srcdir)/libdruntime -I ../libdruntime -I .
+D_EXTRA_DFLAGS=-fpreview=dip1000 -fpreview=dtorfields -fpreview=fieldwise \
+       -nostdinc -I $(srcdir) -I $(top_srcdir)/libdruntime \
+       -I ../libdruntime -I .
 
 # D flags for compilation
 AM_DFLAGS= \
index 9e61bb309f83944c2ba5889fbf7b26e22e95306a..a4101ebf0289e26e2acfe9565275b434233e927f 100644 (file)
@@ -500,8 +500,9 @@ LTDCOMPILE = $(LIBTOOL) --tag=D $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 # Include D build rules
 
 # Make sure GDC can find libdruntime and libphobos include files
-D_EXTRA_DFLAGS = -fpreview=dip1000 -fpreview=dtorfields -nostdinc -I $(srcdir) \
-       -I $(top_srcdir)/libdruntime -I ../libdruntime -I .
+D_EXTRA_DFLAGS = -fpreview=dip1000 -fpreview=dtorfields -fpreview=fieldwise \
+       -nostdinc -I $(srcdir) -I $(top_srcdir)/libdruntime \
+       -I ../libdruntime -I .
 
 
 # D flags for compilation
index 98fe74af32159fe38f71667eea547dd514cd6432..0c5b727944ce54850493ec859498d663add2054c 100644 (file)
@@ -548,29 +548,36 @@ enum CurlProxy {
 alias curl_proxytype = int;
 
 ///
-enum CurlAuth : long {
-  none =         0,
-  basic =        1,  /** Basic (default) */
-  digest =       2,  /** Digest */
-  gssnegotiate = 4,  /** GSS-Negotiate */
-  ntlm =         8,  /** NTLM */
-  digest_ie =    16, /** Digest with IE flavour */
-  only =         2_147_483_648, /** used together with a single other
-                                type to force no auth or just that
-                                single type */
-  any = -17,     /* (~CURLAUTH_DIGEST_IE) */  /** all fine types set */
-  anysafe = -18  /* (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) */ ///
+enum CurlAuth : ulong {
+  none =         0UL,        /** None */
+  basic =        1UL << 0,   /** Basic (default) */
+  digest =       1UL << 1,   /** Digest */
+  negotiate =    1UL << 2,   /** Negotiate (SPNEGO) */
+  gssnegotiate = negotiate,  /** GSS-Negotiate */
+  gssapi =       negotiate,  /** GSS-Negoatiate */
+  ntlm =         1UL << 3,   /** NTLM */
+  digest_ie =    1UL << 4,   /** Digest with IE flavour */
+  ntlm_WB =      1UL << 5,   /** NTML delegated to winbind helper */
+  bearer =       1UL << 6,   /** Bearer token authentication */
+  only =         1UL << 31,  /** used together with a single other
+                                 type to force no auth or just that
+                                 single type */
+  any =          ~digest_ie, /** any allows */
+  anysafe =      ~(basic | digest_ie) /** any except basic */
 }
 
 ///
 enum CurlSshAuth {
-  any       = -1,     /** all types supported by the server */
+  any       = ~0,     /** all types supported by the server */
   none      = 0,      /** none allowed, silly but complete */
-  publickey = 1, /** public/private key files */
-  password  = 2, /** password */
-  host      = 4, /** host key files */
-  keyboard  = 8, /** keyboard interactive */
-  default_  = -1 // CURLSSH_AUTH_ANY;
+  publickey = 1 << 0, /** public/private key files */
+  password  = 1 << 1, /** password */
+  host      = 1 << 2, /** host key files */
+  keyboard  = 1 << 3, /** keyboard interactive */
+  agent     = 1 << 4, /** agent (ssh-agent, pageant...) */
+  gssapi    = 1 << 5, /** gssapi (kerberos, ...) */
+
+  default_  = any // CURLSSH_AUTH_ANY;
 }
 ///
 enum CURL_ERROR_SIZE = 256;
similarity index 100%
rename from libphobos/src/index.d
rename to libphobos/src/index.dd
index c9525445cebe07732d43974ee3ddfc1d41e9a8cd..2fcc2bacd5ce926f8bfb18c864e05a3a2083b99e 100644 (file)
@@ -58,10 +58,10 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
  */
 module std.algorithm.comparison;
 
-import std.functional : unaryFun, binaryFun;
+import std.functional : unaryFun, binaryFun, lessThan, greaterThan;
 import std.range.primitives;
 import std.traits;
-import std.meta : allSatisfy;
+import std.meta : allSatisfy, anySatisfy;
 import std.typecons : tuple, Tuple, Flag, Yes;
 
 import std.internal.attributes : betterC;
@@ -247,7 +247,7 @@ auto castSwitch(choices...)(Object switchObject)
         bool result = true;
         foreach (index, choice; choices)
         {
-            result &= is(ReturnType!choice == void);
+            result &= is(ReturnType!choice : void); // void or noreturn
         }
         return result;
     }();
@@ -514,9 +514,54 @@ auto castSwitch(choices...)(Object switchObject)
     ) == "derived from I");
 }
 
-/** Clamps a value into the given bounds.
+// https://issues.dlang.org/show_bug.cgi?id=22384
+@system unittest
+{
+    // Use explicit methods to enforce return types
+    static void objectSkip(Object) {}
+    static void defaultSkip() {}
+
+    static noreturn objectError(Object) { assert(false); }
+    static noreturn defaultError() { assert(false); }
+
+    {
+        alias test = castSwitch!(objectSkip, defaultError);
+        static assert(is(ReturnType!test == void));
+    }{
+        alias test = castSwitch!(objectError, defaultSkip);
+        static assert(is(ReturnType!test == void));
+    }{
+        alias test = castSwitch!(objectError, defaultError);
+        static assert(is(ReturnType!test == noreturn));
+    }
+
+    // Also works with non-void handlers
+    static int objectValue(Object) { return 1;}
+    static int defaultValue() { return 2; }
+
+    {
+        alias test = castSwitch!(objectValue, defaultError);
+        static assert(is(ReturnType!test == int));
+    }{
+        alias test = castSwitch!(objectError, defaultValue);
+        static assert(is(ReturnType!test == int));
+    }
+
+    // No confusion w.r.t. void callbacks
+    alias FP = void function();
+    static FP objectFunc(Object) { return &defaultSkip; }
+    static FP defaultFunc() { return &defaultSkip; }
+
+    {
+        alias test = castSwitch!(objectFunc, defaultError);
+        static assert(is(ReturnType!test == FP));
+    }{
+        alias test = castSwitch!(objectError, defaultFunc);
+        static assert(is(ReturnType!test == FP));
+    }
+}
 
-This function is equivalent to `max(lower, min(upper, val))`.
+/** Clamps `val` into the given bounds. Result has the same type as `val`.
 
 Params:
     val = The value to _clamp.
@@ -524,20 +569,22 @@ Params:
     upper = The _upper bound of the _clamp.
 
 Returns:
-    Returns `val`, if it is between `lower` and `upper`.
-    Otherwise returns the nearest of the two.
-
+    `lower` if `val` is less than `lower`, `upper` if `val` is greater than
+    `upper`, and `val` in all other cases. Comparisons are made
+    correctly (using $(REF lessThan, std,functional) and the return value
+    is converted to the return type using the standard integer coversion rules
+    $(REF greaterThan, std,functional)) even if the signedness of `T1`, `T2`,
+    and `T3` are different.
 */
-auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
-if (is(typeof(max(min(val, upper), lower))))
+T1 clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
+if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
 in
 {
-    import std.functional : greaterThan;
     assert(!lower.greaterThan(upper), "Lower can't be greater than upper.");
 }
 do
 {
-    return max(min(val, upper), lower);
+    return val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val;
 }
 
 ///
@@ -550,6 +597,10 @@ do
     assert(clamp(1, 1, 1) == 1);
 
     assert(clamp(5, -1, 2u) == 2);
+
+    auto x = clamp(42, uint.max, uint.max);
+    static assert(is(typeof(x) == int));
+    assert(x == -1);
 }
 
 @safe unittest
@@ -564,7 +615,7 @@ do
     // mixed sign
     a = -5;
     uint f = 5;
-    static assert(is(typeof(clamp(f, a, b)) == int));
+    static assert(is(typeof(clamp(f, a, b)) == uint));
     assert(clamp(f, a, b) == f);
     // similar type deduction for (u)long
     static assert(is(typeof(clamp(-1L, -2L, 2UL)) == long));
@@ -874,101 +925,121 @@ nothrow pure @safe unittest
 
 // equal
 /**
-Compares two ranges for equality, as defined by predicate `pred`
+Compares two or more ranges for equality, as defined by predicate `pred`
 (which is `==` by default).
 */
 template equal(alias pred = "a == b")
 {
     /++
-    Compares two ranges for equality. The ranges may have
-    different element types, as long as `pred(r1.front, r2.front)`
-    evaluates to `bool`.
-    Performs $(BIGOH min(r1.length, r2.length)) evaluations of `pred`.
+    Compares two or more ranges for equality. The ranges may have
+    different element types, as long as all are comparable by means of
+    the `pred`.
+    Performs $(BIGOH min(rs[0].length, rs[1].length, ...)) evaluations of `pred`. However, if
+    `equal` is invoked with the default predicate, the implementation may take the liberty
+    to use faster implementations that have the theoretical worst-case
+    $(BIGOH max(rs[0].length, rs[1].length, ...)).
 
     At least one of the ranges must be finite. If one range involved is infinite, the result is
     (statically known to be) `false`.
 
-    If the two ranges are different kinds of UTF code unit (`char`, `wchar`, or
-    `dchar`), then the arrays are compared using UTF decoding to avoid
+    If the ranges have different kinds of UTF code unit (`char`, `wchar`, or
+    `dchar`), then they are compared using UTF decoding to avoid
     accidentally integer-promoting units.
 
     Params:
-        r1 = The first range to be compared.
-        r2 = The second range to be compared.
+        rs = The ranges to be compared.
 
     Returns:
-        `true` if and only if the two ranges compare _equal element
+        `true` if and only if all ranges compare _equal element
         for element, according to binary predicate `pred`.
     +/
-    bool equal(Range1, Range2)(Range1 r1, Range2 r2)
-    if (isInputRange!Range1 && isInputRange!Range2 &&
-        !(isInfinite!Range1 && isInfinite!Range2) &&
-        is(typeof(binaryFun!pred(r1.front, r2.front))))
+    bool equal(Ranges...)(Ranges rs)
+    if (rs.length > 1
+        && allSatisfy!(isInputRange, Ranges)
+        && !allSatisfy!(isInfinite, Ranges)
+        && is(typeof(binaryFun!pred(rs[0].front, rs[1].front)))
+        && (rs.length == 2 || is(typeof(equal!pred(rs[1 .. $])) == bool))
+        )
     {
-        // Use code points when comparing two ranges of UTF code units that aren't
-        // the same type. This is for backwards compatibility with autodecode
-        // strings.
-        enum useCodePoint =
-            isSomeChar!(ElementEncodingType!Range1) && isSomeChar!(ElementEncodingType!Range2) &&
-            ElementEncodingType!Range1.sizeof != ElementEncodingType!Range2.sizeof;
-
-        static if (useCodePoint)
+        alias ElementEncodingTypes = staticMap!(ElementEncodingType, Ranges);
+        enum differentSize(T) = T.sizeof != ElementEncodingTypes[0].sizeof;
+        enum useCodePoint = allSatisfy!(isSomeChar, ElementEncodingTypes) &&
+            anySatisfy!(differentSize, ElementEncodingTypes);
+        enum bool comparableWithEq(alias r) = is(typeof(rs[0] == r));
+
+        static if (anySatisfy!(isInfinite, Ranges))
         {
-            import std.utf : byDchar;
-            return equal(r1.byDchar, r2.byDchar);
+            return false;
         }
-        else
+        else static if (useCodePoint)
         {
-            static if (isInfinite!Range1 || isInfinite!Range2)
-            {
-                // No finite range can be ever equal to an infinite range.
-                return false;
-            }
-            // Detect default pred and compatible dynamic arrays.
-            else static if (is(typeof(pred) == string) && pred == "a == b" &&
-                isArray!Range1 && isArray!Range2 && is(typeof(r1 == r2)))
-            {
-                return r1 == r2;
-            }
-            // If one of the arguments is a string and the other isn't, then auto-decoding
-            // can be avoided if they have the same ElementEncodingType.
-            else static if (is(typeof(pred) == string) && pred == "a == b" &&
-                isAutodecodableString!Range1 != isAutodecodableString!Range2 &&
-                is(immutable ElementEncodingType!Range1 == immutable ElementEncodingType!Range2))
+            import std.utf : byDchar;
+            static bool allByDchar(size_t done, Ranges...)(auto ref Ranges rs)
             {
-                import std.utf : byCodeUnit;
-
-                static if (isAutodecodableString!Range1)
-                    return equal(r1.byCodeUnit, r2);
+                static if (done == rs.length)
+                    return equalLoop(rs);
                 else
-                    return equal(r2.byCodeUnit, r1);
-            }
-            // Try a fast implementation when the ranges have comparable lengths.
-            else static if (hasLength!Range1 && hasLength!Range2 && is(typeof(r1.length == r2.length)))
-            {
-                immutable len1 = r1.length;
-                immutable len2 = r2.length;
-                if (len1 != len2) return false; //Short circuit return
-
-                // Lengths are the same, so we need to do an actual comparison.
-                // Good news is we can squeeze out a bit of performance by not checking if r2 is empty.
-                for (; !r1.empty; r1.popFront(), r2.popFront())
-                {
-                    if (!binaryFun!(pred)(r1.front, r2.front)) return false;
-                }
-                return true;
+                    return allByDchar!(done + 1)(rs[0 .. done], rs[done].byDchar, rs[done + 1 .. $]);
             }
+            return allByDchar!0(rs);
+        }
+        else static if (is(typeof(pred) == string) && pred == "a == b" &&
+                allSatisfy!(isArray, Ranges) && allSatisfy!(comparableWithEq, rs))
+        {
+            static foreach (r; rs[1 .. $])
+                if (rs[0] != r)
+                    return false;
+            return true;
+        }
+        // if one of the arguments is a string and the other isn't, then auto-decoding
+        // can be avoided if they have the same ElementEncodingType
+        // TODO: generalize this
+        else static if (rs.length == 2 && is(typeof(pred) == string) && pred == "a == b" &&
+                isAutodecodableString!(Ranges[0]) != isAutodecodableString!(Ranges[1]) &&
+                is(immutable ElementEncodingType!(Ranges[0]) == immutable ElementEncodingType!(Ranges[1])))
+        {
+            import std.utf : byCodeUnit;
+            static if (isAutodecodableString!(Ranges[0]))
+                return equal(rs[0].byCodeUnit, rs[1]);
             else
+                return equal(rs[1].byCodeUnit, rs[0]);
+        }
+        else
+        {
+            static foreach (i, R; Ranges)
             {
-                //Generic case, we have to walk both ranges making sure neither is empty
-                for (; !r1.empty; r1.popFront(), r2.popFront())
+                static if (hasLength!R)
                 {
-                    if (r2.empty || !binaryFun!(pred)(r1.front, r2.front)) return false;
+                    static if (!is(typeof(firstLength)))
+                    {
+                        // Found the first range that has length
+                        auto firstLength = rs[i].length;
+                    }
+                    else
+                    {
+                        // Compare the length of the current range against the first with length
+                        if (firstLength != rs[i].length)
+                            return false;
+                    }
                 }
-                return r2.empty;
             }
+            return equalLoop(rs);
         }
     }
+
+    private bool equalLoop(Rs...)(Rs rs)
+    {
+        for (; !rs[0].empty; rs[0].popFront)
+            static foreach (r; rs[1 .. $])
+                if (r.empty || !binaryFun!pred(rs[0].front, r.front))
+                    return false;
+                else
+                    r.popFront;
+        static foreach (r; rs[1 .. $])
+            if (!r.empty)
+                return false;
+        return true;
+    }
 }
 
 ///
@@ -992,6 +1063,31 @@ template equal(alias pred = "a == b")
     assert(equal!isClose(b[], c[]));
 }
 
+@safe @nogc unittest
+{
+    import std.algorithm.comparison : equal;
+    import std.math.operations : isClose;
+
+    auto s1 = "abc", s2 = "abc"w;
+    assert(equal(s1, s2, s2));
+    assert(equal(s1, s2, s2, s1));
+    assert(!equal(s1, s2, s2[1 .. $]));
+
+    int[4] a = [ 1, 2, 4, 3 ];
+    assert(!equal(a[], a[1..$], a[]));
+    assert(equal(a[], a[], a[]));
+    assert(equal!((a, b) => a == b)(a[], a[], a[]));
+
+    // different types
+    double[4] b = [ 1.0, 2, 4, 3];
+    assert(!equal(a[], b[1..$], b[]));
+    assert(equal(a[], b[], a[], b[]));
+
+    // predicated: ensure that two vectors are approximately equal
+    double[4] c = [ 1.0000000005, 2, 4, 3];
+    assert(equal!isClose(b[], c[], b[]));
+}
+
 /++
 Tip: `equal` can itself be used as a predicate to other functions.
 This can be very useful when the element type of a range is itself a
@@ -1748,21 +1844,26 @@ store the lowest values.
 
 // mismatch
 /**
-Sequentially compares elements in `r1` and `r2` in lockstep, and
+Sequentially compares elements in `rs` in lockstep, and
 stops at the first mismatch (according to `pred`, by default
 equality). Returns a tuple with the reduced ranges that start with the
-two mismatched values. Performs $(BIGOH min(r1.length, r2.length))
+two mismatched values. Performs $(BIGOH min(r[0].length, r[1].length, ...))
 evaluations of `pred`.
 */
-Tuple!(Range1, Range2)
-mismatch(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2)
-if (isInputRange!(Range1) && isInputRange!(Range2))
+Tuple!(Ranges)
+mismatch(alias pred = (a, b) => a == b, Ranges...)(Ranges rs)
+if (rs.length >= 2 && allSatisfy!(isInputRange, Ranges))
 {
-    for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
+    loop: for (; !rs[0].empty; rs[0].popFront)
     {
-        if (!binaryFun!(pred)(r1.front, r2.front)) break;
+        static foreach (r; rs[1 .. $])
+        {
+            if (r.empty || !binaryFun!pred(rs[0].front, r.front))
+                break loop;
+            r.popFront;
+        }
     }
-    return tuple(r1, r2);
+    return tuple(rs);
 }
 
 ///
@@ -1773,6 +1874,12 @@ if (isInputRange!(Range1) && isInputRange!(Range2))
     auto m = mismatch(x[], y[]);
     assert(m[0] == x[3 .. $]);
     assert(m[1] == y[3 .. $]);
+
+    auto m2 = mismatch(x[], y[], x[], y[]);
+    assert(m2[0] == x[3 .. $]);
+    assert(m2[1] == y[3 .. $]);
+    assert(m2[2] == x[3 .. $]);
+    assert(m2[3] == y[3 .. $]);
 }
 
 @safe @nogc unittest
@@ -1925,50 +2032,91 @@ auto predSwitch(alias pred = "a == b", T, R ...)(T switchExpression, lazy R choi
 }
 
 /**
-Checks if the two ranges have the same number of elements. This function is
+Checks if two or more ranges have the same number of elements. This function is
 optimized to always take advantage of the `length` member of either range
 if it exists.
 
-If both ranges have a length member, this function is $(BIGOH 1). Otherwise,
-this function is $(BIGOH min(r1.length, r2.length)).
+If all ranges have a `length` member or at least one is infinite,
+`_isSameLength`'s complexity is $(BIGOH 1). Otherwise, complexity is
+$(BIGOH n), where `n` is the smallest of the lengths of ranges with unknown
+length.
 
-Infinite ranges are considered of the same length. An infinite range has never the same length as a
-finite range.
+Infinite ranges are considered of the same length. An infinite range has never
+the same length as a finite range.
 
 Params:
-    r1 = a finite $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
-    r2 = a finite $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+    rs = two or more $(REF_ALTTEXT input ranges, isInputRange, std,range,primitives)
 
 Returns:
     `true` if both ranges have the same length, `false` otherwise.
 */
-bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
-if (isInputRange!Range1 && isInputRange!Range2)
+bool isSameLength(Ranges...)(Ranges rs)
+if (allSatisfy!(isInputRange, Ranges))
 {
-    static if (isInfinite!Range1 || isInfinite!Range2)
-    {
-        return isInfinite!Range1 && isInfinite!Range2;
-    }
-    else static if (hasLength!(Range1) && hasLength!(Range2))
+    static if (anySatisfy!(isInfinite, Ranges))
     {
-        return r1.length == r2.length;
+        return allSatisfy!(isInfinite, Ranges);
     }
-    else static if (hasLength!(Range1) && !hasLength!(Range2))
+    else static if (anySatisfy!(hasLength, Ranges))
     {
-        return r2.walkLength(r1.length + 1) == r1.length;
-    }
-    else static if (!hasLength!(Range1) && hasLength!(Range2))
-    {
-        return r1.walkLength(r2.length + 1) == r2.length;
+        // Compute the O(1) length
+        auto baselineLength = size_t.max;
+        static foreach (i, R; Ranges)
+        {
+            static if (hasLength!R)
+            {
+                if (baselineLength == size_t.max)
+                    baselineLength = rs[i].length;
+                else if (rs[i].length != baselineLength)
+                    return false;
+            }
+        }
+        // Iterate all ranges without known length
+        foreach (_; 0 .. baselineLength)
+            static foreach (i, R; Ranges)
+            {
+                static if (!hasLength!R)
+                {
+                    // All must be non-empty
+                    if (rs[i].empty)
+                        return false;
+                    rs[i].popFront;
+                }
+            }
+        static foreach (i, R; Ranges)
+        {
+            static if (!hasLength!R)
+            {
+                // All must be now empty
+                if (!rs[i].empty)
+                    return false;
+            }
+        }
+        return true;
     }
     else
     {
-        for (; !r1.empty; r1.popFront, r2.popFront)
-        {
-           if (r2.empty)
-              return false;
-        }
-        return r2.empty;
+        // All have unknown length, iterate in lockstep
+        for (;;)
+            static foreach (i, r; rs)
+            {
+                if (r.empty)
+                {
+                    // One is empty, so all must be empty
+                    static if (i != 0)
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        static foreach (j, r1; rs[1 .. $])
+                            if (!r1.empty)
+                                return false;
+                        return true;
+                    }
+                }
+                r.popFront;
+            }
     }
 }
 
@@ -1976,34 +2124,42 @@ if (isInputRange!Range1 && isInputRange!Range2)
 @safe nothrow pure unittest
 {
     assert(isSameLength([1, 2, 3], [4, 5, 6]));
+    assert(isSameLength([1, 2, 3], [4, 5, 6], [7, 8, 9]));
     assert(isSameLength([0.3, 90.4, 23.7, 119.2], [42.6, 23.6, 95.5, 6.3]));
     assert(isSameLength("abc", "xyz"));
+    assert(isSameLength("abc", "xyz", [1, 2, 3]));
 
     int[] a;
     int[] b;
     assert(isSameLength(a, b));
+    assert(isSameLength(a, b, a, a, b, b, b));
 
     assert(!isSameLength([1, 2, 3], [4, 5]));
+    assert(!isSameLength([1, 2, 3], [4, 5, 6], [7, 8]));
     assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
     assert(!isSameLength("abcd", "xyz"));
+    assert(!isSameLength("abcd", "xyz", "123"));
+    assert(!isSameLength("abcd", "xyz", "1234"));
 }
 
 // Test CTFE
 @safe @nogc pure @betterC unittest
 {
-    enum result1 = isSameLength([1, 2, 3], [4, 5, 6]);
-    static assert(result1);
-
-    enum result2 = isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]);
-    static assert(!result2);
+    static assert(isSameLength([1, 2, 3], [4, 5, 6]));
+    static assert(isSameLength([1, 2, 3], [4, 5, 6], [7, 8, 9]));
+    static assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
+    static assert(!isSameLength([1], [0.3, 90.4], [42]));
 }
 
 @safe @nogc pure unittest
 {
     import std.range : only;
     assert(isSameLength(only(1, 2, 3), only(4, 5, 6)));
+    assert(isSameLength(only(1, 2, 3), only(4, 5, 6), only(7, 8, 9)));
     assert(isSameLength(only(0.3, 90.4, 23.7, 119.2), only(42.6, 23.6, 95.5, 6.3)));
     assert(!isSameLength(only(1, 3, 3), only(4, 5)));
+    assert(!isSameLength(only(1, 3, 3), only(1, 3, 3), only(4, 5)));
+    assert(!isSameLength(only(1, 3, 3), only(4, 5), only(1, 3, 3)));
 }
 
 @safe nothrow pure unittest
@@ -2033,6 +2189,15 @@ if (isInputRange!Range1 && isInputRange!Range2)
     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r11;
     auto r12 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8]);
     assert(!isSameLength(r11, r12));
+
+    import std.algorithm.iteration : filter;
+
+    assert(isSameLength(filter!"a >= 1"([1, 2, 3]), [4, 5, 6]));
+    assert(!isSameLength(filter!"a > 1"([1, 2, 3]), [4, 5, 6]));
+
+    assert(isSameLength(filter!"a > 1"([1, 2, 3]), filter!"a > 4"([4, 5, 6])));
+    assert(isSameLength(filter!"a > 1"([1, 2, 3]),
+        filter!"a > 4"([4, 5, 6]), filter!"a >= 5"([4, 5, 6])));
 }
 
 // Still functional but not documented anymore.
index c3e848760ed6c89b1126b2307812bb6ab2a36b03..9e728e4622f4f9d52653be62fde9fe3752e1619f 100644 (file)
@@ -77,51 +77,6 @@ import std.range.primitives;
 import std.traits;
 import std.typecons : Flag, Yes, No;
 
-private template aggregate(fun...)
-if (fun.length >= 1)
-{
-    /* --Intentionally not ddoc--
-     * Aggregates elements in each subrange of the given range of ranges using
-     * the given aggregating function(s).
-     * Params:
-     *  fun = One or more aggregating functions (binary functions that return a
-     *      single _aggregate value of their arguments).
-     *  ror = A range of ranges to be aggregated.
-     *
-     * Returns:
-     * A range representing the aggregated value(s) of each subrange
-     * of the original range. If only one aggregating function is specified,
-     * each element will be the aggregated value itself; if multiple functions
-     * are specified, each element will be a tuple of the aggregated values of
-     * each respective function.
-     */
-    auto aggregate(RoR)(RoR ror)
-        if (isInputRange!RoR && isIterable!(ElementType!RoR))
-    {
-        return ror.map!(reduce!fun);
-    }
-
-    @safe unittest
-    {
-        import std.algorithm.comparison : equal, max, min;
-
-        auto data = [[4, 2, 1, 3], [4, 9, -1, 3, 2], [3]];
-
-        // Single aggregating function
-        auto agg1 = data.aggregate!max;
-        assert(agg1.equal([4, 9, 3]));
-
-        // Multiple aggregating functions
-        import std.typecons : tuple;
-        auto agg2 = data.aggregate!(max, min);
-        assert(agg2.equal([
-            tuple(4, 1),
-            tuple(9, -1),
-            tuple(3, 3)
-        ]));
-    }
-}
-
 /++
 `cache` eagerly evaluates $(REF_ALTTEXT front, front, std,range,primitives) of `range`
 on each construction or call to $(REF_ALTTEXT popFront, popFront, std,range,primitives),
@@ -2029,23 +1984,39 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
     }
     private Range  current;
 
-    private RefCounted!(OuterRange) mothership;
+    // using union prevents RefCounted destructor from propagating @system to
+    // user code
+    union { private RefCounted!(OuterRange) mothership; }
+    private @trusted ref cargo() { return mothership.refCountedPayload; }
 
-    this(RefCounted!(OuterRange) origin)
+    private this(ref RefCounted!(OuterRange) origin)
     {
-        groupNum = origin.groupNum;
-        current = origin.current.save;
+        () @trusted { mothership = origin; }();
+        groupNum = cargo.groupNum;
+        current = cargo.current.save;
         assert(!current.empty, "Passed range 'r' must not be empty");
+
         static if (eqEquivalenceAssured)
         {
-            start = origin.current.save;
+            start = cargo.current.save;
 
             // Check for reflexivity.
             assert(eq(start.front, current.front),
                 "predicate is not reflexive");
         }
+    }
+
+    // Cannot be a copy constructor due to issue 22239
+    this(this) @trusted
+    {
+        import core.lifetime : emplace;
+        // since mothership has to be in a union, we have to manually trigger
+        // an increment to the reference count.
+        auto temp = mothership;
+        mothership = temp;
 
-        mothership = origin;
+        // prevents the reference count from falling back with brute force
+        emplace(&temp);
     }
 
     @property bool empty() { return groupNum == size_t.max; }
@@ -2073,14 +2044,14 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
 
         if (nowEmpty)
         {
-            if (groupNum == mothership.groupNum)
+            if (groupNum == cargo.groupNum)
             {
                 // If parent range hasn't moved on yet, help it along by
                 // saving location of start of next Group.
-                mothership.next = current.save;
+                cargo.next = current.save;
                 static if (!eqEquivalenceAssured)
                 {
-                    mothership.nextUpdated = true;
+                    cargo.nextUpdated = true;
                 }
             }
 
@@ -2094,6 +2065,11 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
         copy.current = current.save;
         return copy;
     }
+
+    @trusted ~this()
+    {
+        mothership.destroy;
+    }
 }
 
 private enum GroupingOpType{binaryEquivalent, binaryAny, unary}
@@ -2110,23 +2086,48 @@ if (isForwardRange!Range)
 
     static assert(isForwardRange!InnerRange);
 
-    private RefCounted!OuterRange impl;
+    // using union prevents RefCounted destructor from propagating @system to
+    // user code
+    union { private RefCounted!OuterRange _impl; }
+    private @trusted ref impl() { return _impl; }
+    private @trusted ref implPL() { return _impl.refCountedPayload; }
 
     this(Range r)
     {
-        static if (eqEquivalenceAssured)
+        import core.lifetime : move;
+
+        auto savedR = r.save;
+
+        static if (eqEquivalenceAssured) () @trusted
         {
-            impl = RefCounted!OuterRange(0, r, r.save);
-        }
-        else impl = RefCounted!OuterRange(0, r, r.save, false);
+            _impl = RefCounted!OuterRange(0, r, savedR.move);
+        }();
+        else () @trusted
+        {
+            _impl = RefCounted!OuterRange(0, r, savedR.move, false);
+        }();
+    }
+
+    // Cannot be a copy constructor due to issue 22239
+    this(this) @trusted
+    {
+        import core.lifetime : emplace;
+        // since _impl has to be in a union, we have to manually trigger
+        // an increment to the reference count.
+        auto temp = _impl;
+        _impl = temp;
+
+        // prevents the reference count from falling back with brute force
+        emplace(&temp);
     }
 
-    @property bool empty() { return impl.current.empty; }
+    @property bool empty() { return implPL.current.empty; }
 
     static if (opType == GroupingOpType.unary) @property auto front()
     {
         import std.typecons : tuple;
-        return tuple(unaryFun!pred(impl.current.front), InnerRange(impl));
+
+        return tuple(unaryFun!pred(implPL.current.front), InnerRange(impl));
     }
     else @property auto front()
     {
@@ -2138,48 +2139,53 @@ if (isForwardRange!Range)
         // Scan for next group. If we're lucky, one of our Groups would have
         // already set .next to the start of the next group, in which case the
         // loop is skipped.
-        while (!impl.next.empty && eq(impl.current.front, impl.next.front))
+        while (!implPL.next.empty && eq(implPL.current.front, implPL.next.front))
         {
-            impl.next.popFront();
+            implPL.next.popFront();
         }
 
-        impl.current = impl.next.save;
+        implPL.current = implPL.next.save;
 
         // Indicate to any remaining Groups that we have moved on.
-        impl.groupNum++;
+        implPL.groupNum++;
     }
     else void popFront()
     {
-        if (impl.nextUpdated)
+        if (implPL.nextUpdated)
         {
-            impl.current = impl.next.save;
+            implPL.current = implPL.next.save;
         }
         else while (true)
         {
-            auto prevElement = impl.current.front;
-            impl.current.popFront();
-            if (impl.current.empty) break;
-            if (!eq(prevElement, impl.current.front)) break;
+            auto prevElement = implPL.current.front;
+            implPL.current.popFront();
+            if (implPL.current.empty) break;
+            if (!eq(prevElement, implPL.current.front)) break;
         }
 
-        impl.nextUpdated = false;
+        implPL.nextUpdated = false;
         // Indicate to any remaining Groups that we have moved on.
-        impl.groupNum++;
+        implPL.groupNum++;
     }
 
     @property auto save()
     {
         // Note: the new copy of the range will be detached from any existing
         // satellite Groups, and will not benefit from the .next acceleration.
-        return typeof(this)(impl.current.save);
+        return typeof(this)(implPL.current.save);
     }
 
     static assert(isForwardRange!(typeof(this)), typeof(this).stringof
             ~ " must be a forward range");
+
+    @trusted ~this()
+    {
+        _impl.destroy;
+    }
 }
 
 //Test for https://issues.dlang.org/show_bug.cgi?id=14909
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.typecons : tuple;
@@ -2192,8 +2198,36 @@ if (isForwardRange!Range)
     assert(u.equal!equal([[1],[2],[3]]));
 }
 
+//Testing inferring @system correctly
+@safe unittest
+{
+    struct DeadlySave
+    {
+        int front;
+        @safe void popFront(){front++;}
+        @safe bool empty(){return front >= 5;}
+        @system auto save(){return this;}
+    }
+
+    auto test1()
+    {
+        DeadlySave src;
+        return src.walkLength;
+
+    }
+
+    auto test2()
+    {
+        DeadlySave src;
+        return src.chunkBy!((a,b) => a % 2 == b % 2).walkLength;
+    }
+
+    static assert(isSafe!test1);
+    static assert(!isSafe!test2);
+}
+
 //Test for https://issues.dlang.org/show_bug.cgi?id=18751
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
 
@@ -2205,7 +2239,7 @@ if (isForwardRange!Range)
 }
 
 //Additional test for fix for issues 14909 and 18751
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     auto v = [2,4,8,3,6,9,1,5,7];
@@ -2329,7 +2363,7 @@ if (isInputRange!Range)
 }
 
 /// Showing usage with binary predicate:
-/*FIXME: @safe*/ @system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
 
@@ -2356,7 +2390,7 @@ if (isInputRange!Range)
 }
 
 /// Showing usage with unary predicate:
-/* FIXME: pure @safe nothrow*/ @system unittest
+/* FIXME: pure nothrow*/ @safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.range.primitives;
@@ -2755,7 +2789,7 @@ if (isInputRange!Range)
 
 
 // https://issues.dlang.org/show_bug.cgi?id=13805
-@system unittest
+@safe unittest
 {
     [""].map!((s) => s).chunkBy!((x, y) => true);
 }
@@ -2790,9 +2824,8 @@ if (isForwardRange!Range)
     return ChunkByImpl!(not!pred, not!pred, GroupingOpType.binaryAny, Range)(r);
 }
 
-//FIXME: these should be @safe
 ///
-nothrow pure @system unittest
+nothrow pure @safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.range : dropExactly;
@@ -2816,7 +2849,7 @@ nothrow pure @system unittest
 }
 
 //ensure we don't iterate the underlying range twice
-nothrow @system unittest
+nothrow @safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.math.algebraic : abs;
@@ -2827,7 +2860,7 @@ nothrow @system unittest
         static int popfrontsSoFar;
 
         auto front(){return elements[0];}
-        nothrow void popFront()
+        nothrow @safe void popFront()
         {   popfrontsSoFar++;
             elements = elements[1 .. $];
         }
@@ -2851,7 +2884,7 @@ nothrow @system unittest
 }
 
 // Issue 13595
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     auto r = [1, 2, 3, 4, 5, 6, 7, 8, 9].splitWhen!((x, y) => ((x*y) % 3) > 0);
@@ -2863,7 +2896,7 @@ nothrow @system unittest
     ]));
 }
 
-nothrow pure @system unittest
+nothrow pure @safe unittest
 {
     // Grouping by maximum adjacent difference:
     import std.math.algebraic : abs;
@@ -3654,10 +3687,18 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
         {
             @property auto save()
             {
-                auto r = Result(_items.save, _current.save);
+                // the null check is important if it is a class range, since null.save will segfault; issue #22359
+                // could not just compare x is y here without static if due to a compiler assertion failure
+                static if (is(typeof(null) : typeof(_current)))
+                    auto r = Result(_items.save, _current is null ? null : _current.save);
+                else
+                    auto r = Result(_items.save, _current.save);
                 static if (isBidirectional)
                 {
-                    r._currentBack = _currentBack.save;
+                    static if (is(typeof(null) : typeof(_currentBack)))
+                        r._currentBack = _currentBack is null ? null : _currentBack.save;
+                    else
+                        r._currentBack = _currentBack.save;
                     r.reachedFinalElement = reachedFinalElement;
                 }
                 return r;
@@ -3838,6 +3879,26 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
     static assert(isForwardRange!(typeof(joiner([""]))));
 }
 
+@system unittest
+{
+    // this test is system because the virtual interface call to save
+    // is flexible and thus cannot be inferred safe automatically
+
+    // https://issues.dlang.org/show_bug.cgi?id=22359
+    import std.range;
+    ForwardRange!int bug(int[][] r)
+    {
+        import std.range : inputRangeObject;
+        import std.algorithm.iteration : map, joiner;
+
+        auto range = inputRangeObject(r);
+
+        return range.map!(a =>inputRangeObject(a)).joiner.inputRangeObject;
+    }
+    auto f = bug([[]]);
+    f.save(); // should not segfault
+}
+
 @safe unittest
 {
     // Initial version of PR #6115 caused a compilation failure for
index 88191bbf3f73a4a78dad99315fa5eb18a0f00505..07cbb9b98238dc8b8b3af3038f8a30dbe955a3eb 100644 (file)
@@ -1427,7 +1427,7 @@ private void moveEmplaceImpl(T)(ref scope T target, ref return scope T source)
     {
         import std.exception : doesPointTo;
         assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
-            "Cannot move object with internal pointer unless `opPostMove` is defined.");
+            "Cannot move object of type " ~ T.stringof ~ " with internal pointer unless `opPostMove` is defined.");
     }
 
     static if (is(T == struct))
index d6d02bad3bb9554c6ececc85778e1b34dc9aaef5..96352064c5556ac4f5fad309058abe80b000fcf2 100644 (file)
@@ -122,7 +122,9 @@ template all(alias pred = "a")
     if (isInputRange!Range)
     {
         static assert(is(typeof(unaryFun!pred(range.front))),
-                "`" ~ pred.stringof[1..$-1] ~ "` isn't a unary predicate function for range.front");
+                "`" ~ (isSomeString!(typeof(pred))
+                    ? pred.stringof[1..$-1] : pred.stringof)
+                ~ "` isn't a unary predicate function for range.front");
         import std.functional : not;
 
         return find!(not!(unaryFun!pred))(range).empty;
@@ -3572,6 +3574,8 @@ Params:
     r = range from which the minimal element will be selected
     seed = custom seed to use as initial element
 
+Precondition: If a seed is not given, `r` must not be empty.
+
 Returns: The minimal element of the passed-in range.
 
 Note:
@@ -3723,6 +3727,8 @@ Params:
     r = range from which the maximum element will be selected
     seed = custom seed to use as initial element
 
+Precondition: If a seed is not given, `r` must not be empty.
+
 Returns: The maximal element of the passed-in range.
 
 Note:
index dbfe37f2fb011d79b4dd19a5cd455d0652065414..f2877ccbdf43d1f006fbaca7dc84ca6a56ddfe99 100644 (file)
@@ -2209,7 +2209,7 @@ package(std) template HeapOps(alias less, Range)
         ~ " RandomAccessRange");
     static assert(hasLength!Range, Range.stringof ~ " must have length");
     static assert(hasSwappableElements!Range || hasAssignableElements!Range,
-        Range.stringof ~ " must have swappable of assignable Elements");
+        Range.stringof ~ " must have swappable or assignable Elements");
 
     alias lessFun = binaryFun!less;
 
@@ -2329,8 +2329,8 @@ private template TimSortImpl(alias pred, R)
         ~ " RandomAccessRange");
     static assert(hasLength!R, R.stringof ~ " must have a length");
     static assert(hasSlicing!R, R.stringof ~ " must support slicing");
-    static assert(hasAssignableElements!R, R.stringof ~ " must support"
-        ~ " assigning elements");
+    static assert(hasAssignableElements!R, R.stringof ~ " must have"
+        ~ " assignable elements");
 
     alias T = ElementType!R;
 
@@ -3571,7 +3571,7 @@ void topNImpl(alias less, R)(R r, size_t n, ref bool useSampling)
 private size_t topNPartition(alias lp, R)(R r, size_t n, bool useSampling)
 {
     import std.format : format;
-    assert(r.length >= 9 && n < r.length, "length must be longer than 9"
+    assert(r.length >= 9 && n < r.length, "length must be longer than 8"
         ~ " and n must be less than r.length");
     immutable ninth = r.length / 9;
     auto pivot = ninth / 2;
@@ -4220,8 +4220,8 @@ if (isRandomAccessRange!Range && hasLength!Range &&
     Indexes.length >= 2 && Indexes.length <= 5 &&
     allSatisfy!(isUnsigned, Indexes))
 {
-    assert(r.length >= Indexes.length, "r.length must be greater equal to"
-        ~ " Indexes.length");
+    assert(r.length >= Indexes.length, "r.length must be greater than or"
+        ~ " equal to Indexes.length");
     import std.functional : binaryFun;
     alias lt = binaryFun!less;
     enum k = Indexes.length;
index ded1196da52be1d2df512823be6add0e6b499646..ffdda8e1d4c1a4029cba4019d56412a466d4443e 100644 (file)
@@ -259,6 +259,19 @@ if (isPointer!Range && isIterable!(PointerTarget!Range) && !isAutodecodableStrin
     )));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=20937
+@safe pure nothrow unittest
+{
+    struct S {int* x;}
+    struct R
+    {
+        immutable(S) front;
+        bool empty;
+        @safe pure nothrow void popFront(){empty = true;}
+    }
+    R().array;
+}
+
 /**
 Convert a narrow autodecoding string to an array type that fully supports
 random access.  This is handled as a special case and always returns an array
@@ -1609,7 +1622,7 @@ private template isInputRangeOrConvertible(E)
         `true` if $(D lhs.ptr == rhs.ptr), `false` otherwise.
   +/
 @safe
-pure nothrow bool sameHead(T)(in T[] lhs, in T[] rhs)
+pure nothrow @nogc bool sameHead(T)(in T[] lhs, in T[] rhs)
 {
     return lhs.ptr == rhs.ptr;
 }
@@ -1637,7 +1650,7 @@ pure nothrow bool sameHead(T)(in T[] lhs, in T[] rhs)
         `false` otherwise.
   +/
 @trusted
-pure nothrow bool sameTail(T)(in T[] lhs, in T[] rhs)
+pure nothrow @nogc bool sameTail(T)(in T[] lhs, in T[] rhs)
 {
     return lhs.ptr + lhs.length == rhs.ptr + rhs.length;
 }
@@ -3492,13 +3505,14 @@ if (isDynamicArray!A)
         }
         else
         {
-            import core.internal.lifetime : emplaceRef;
+            import core.lifetime : emplace;
 
             ensureAddable(1);
             immutable len = _data.arr.length;
 
             auto bigData = (() @trusted => _data.arr.ptr[0 .. len + 1])();
-            emplaceRef!(Unqual!T)(bigData[len], cast() item);
+            auto itemUnqual = (() @trusted => & cast() item)();
+            emplace(&bigData[len], *itemUnqual);
             //We do this at the end, in case of exceptions
             _data.arr = bigData;
         }
index 2dd6211aa7c91762207dea665e12469bcfb3e749..9af9d721230ab3d0f7e0119894d59f18219c354f 100644 (file)
@@ -2948,12 +2948,12 @@ if (isIntegral!T || isSomeChar!T || isBoolean!T)
 private union EndianSwapper(T)
 if (canSwapEndianness!T)
 {
-    Unqual!T value;
+    T value;
     ubyte[T.sizeof] array;
 
-    static if (is(FloatingPointTypeOf!(Unqual!T) == float))
+    static if (is(immutable FloatingPointTypeOf!(T) == immutable float))
         uint  intValue;
-    else static if (is(FloatingPointTypeOf!(Unqual!T) == double))
+    else static if (is(immutable FloatingPointTypeOf!(T) == immutable double))
         ulong intValue;
 
 }
index d101ce4abf474f519002972d5a119bb7b9c8bf17..a9830af61a27741f2bd329aa7a341608aa5b5f45 100644 (file)
@@ -484,7 +484,7 @@ private template isSpawnable(F, T...)
             enum isParamsImplicitlyConvertible = false;
     }
 
-    enum isSpawnable = isCallable!F && is(ReturnType!F == void)
+    enum isSpawnable = isCallable!F && is(ReturnType!F : void)
             && isParamsImplicitlyConvertible!(F, void function(T))
             && (isFunctionPointer!F || !hasUnsharedAliasing!F);
 }
@@ -1573,10 +1573,9 @@ private:
             this.outer.yield();
         }
 
-        private bool notified;
+        bool notified;
     }
 
-private:
     void dispatch()
     {
         import std.algorithm.mutation : remove;
@@ -1600,7 +1599,6 @@ private:
         }
     }
 
-private:
     Fiber[] m_fibers;
     size_t m_pos;
 }
@@ -1919,48 +1917,53 @@ void yield(T)(T value)
     import core.exception;
     import std.exception;
 
-    static void testScheduler(Scheduler s)
-    {
-        scheduler = s;
-        scheduler.start({
-            auto tid = spawn({
-                int i;
-
-                try
+    auto mainTid = thisTid;
+    alias testdg = () {
+        auto tid = spawn(
+        (Tid mainTid) {
+            int i;
+            scope (failure) mainTid.send(false);
+            try
+            {
+                for (i = 1; i < 10; i++)
                 {
-                    for (i = 1; i < 10; i++)
+                    if (receiveOnly!int() != i)
                     {
-                        assertNotThrown!AssertError(assert(receiveOnly!int() == i));
+                        mainTid.send(false);
+                        break;
                     }
                 }
-                catch (OwnerTerminated e)
-                {
-
-                }
-
-                // i will advance 1 past the last value expected
-                assert(i == 4);
-            });
-
-            auto r = new Generator!int({
-                assertThrown!Exception(yield(2.0));
-                yield(); // ensure this is a no-op
-                yield(1);
-                yield(); // also once something has been yielded
-                yield(2);
-                yield(3);
-            });
-
-            foreach (e; r)
+            }
+            catch (OwnerTerminated e)
             {
-                tid.send(e);
+                // i will advance 1 past the last value expected
+                mainTid.send(i == 4);
             }
+        }, mainTid);
+        auto r = new Generator!int(
+        {
+            assertThrown!Exception(yield(2.0));
+            yield(); // ensure this is a no-op
+            yield(1);
+            yield(); // also once something has been yielded
+            yield(2);
+            yield(3);
         });
-        scheduler = null;
-    }
 
-    testScheduler(new ThreadScheduler);
-    testScheduler(new FiberScheduler);
+        foreach (e; r)
+        {
+            tid.send(e);
+        }
+    };
+
+    scheduler = new ThreadScheduler;
+    scheduler.spawn(testdg);
+    assert(receiveOnly!bool());
+
+    scheduler = new FiberScheduler;
+    scheduler.start(testdg);
+    assert(receiveOnly!bool());
+    scheduler = null;
 }
 ///
 @system unittest
index 58de5b7e8b4e2de46579d46d59f39031074cbcc6..63dc86403ecbb9484e92b83f50f4b42f47a55836 100644 (file)
@@ -24,6 +24,61 @@ import std.traits;
 
 public import std.container.util;
 
+pure @system unittest
+{
+    // We test multiple array lengths in order to ensure that the "a1.capacity == a0.length" test is meaningful
+    // for the version in which the constructor uses insertBack
+    // (because for some lengths, the test passes even without reserve).
+    for (size_t n = 0; n < 100; ++n)
+    {
+        float[] a0;
+        {
+            import std.range : iota;
+            import std.array;
+            import std.algorithm.iteration : map;
+            a0 = iota (0, n).map!(i => i * 1.1f).array;
+        }
+
+        auto a1 = Array!float(a0);
+
+        // We check that a1 has the same length and contents as a0:
+        {
+            assert(a1.length == a0.length);
+
+            // I wish that I could write "assert(a1[] == a0[]);",
+            // but the compiler complains: "Error: incompatible types for `(a1.opSlice()) == (a0[])`: `RangeT!(Array!float)` and `float[]`".
+            import std.algorithm.comparison : equal;
+            assert(equal(a1[], a0[]));
+        }
+
+        // We check that a1's constructor has called reserve (to maintain good performance):
+        assert(a1.capacity == a0.length);
+    }
+}
+
+pure @system unittest
+{
+    // To avoid bad performance, we check that an Array constructed from an empty range
+    // does not initialize its RefCountedStore object, even after a call to "reserve(0)".
+
+    {
+        Array!float a1;
+        assert(! a1._data.refCountedStore.isInitialized);
+        a1.reserve(0);
+        assert(! a1._data.refCountedStore.isInitialized);
+    }
+
+    {
+        float[] a0 = [];
+        Array!float a1 = a0;
+        // [2021-09-26] TODO: Investigate RefCounted.
+        //assert(! a1._data.refCountedStore.isInitialized);
+        a1.reserve(0);
+        // [2021-09-26] TODO: Investigate RefCounted.
+        //assert(! a1._data.refCountedStore.isInitialized);
+    }
+}
+
 ///
 pure @system unittest
 {
@@ -246,6 +301,70 @@ private struct RangeT(A)
     }
 }
 
+@system unittest
+{
+    enum : bool { display = false }
+    static if (display)
+    {
+        import std.stdio;
+        enum { nDigitsForPointer = 2 * size_t.sizeof, nDigitsForNObjects = 4 }
+    }
+
+    static struct S
+    {
+        static size_t s_nConstructed;
+        static size_t s_nDestroyed;
+        static void throwIfTooMany()
+        {
+            if (s_nConstructed >= 7) throw new Exception ("Ka-boom !");
+        }
+
+        uint _i;
+
+        ~this()
+        {
+            static if (display) writefln("@%*Xh: Destroying.", nDigitsForPointer, &this);
+            ++s_nDestroyed;
+        }
+
+        this(uint i)
+        {
+            static if (display) writefln("@%*Xh: Constructing.", nDigitsForPointer, &this);
+            _i = i;
+            ++s_nConstructed;
+            throwIfTooMany();
+        }
+
+        this(this)
+        {
+            static if (display) writefln("@%*Xh: Copying.", nDigitsForPointer, &this);
+            ++s_nConstructed;
+            throwIfTooMany();
+        }
+    }
+
+    try
+    {
+        auto a = Array!S (S(0), S(1), S(2), S(3));
+        static if (display) writefln("@%*Xh: This is where the array elements are.", nDigitsForPointer, &a [0]);
+    }
+    catch (Exception e)
+    {
+        static if (display) writefln("Exception caught !");
+    }
+
+    static if (display)
+    {
+        writefln("s_nConstructed %*Xh.", nDigitsForNObjects, S.s_nConstructed);
+        writefln("s_nDestroyed   %*Xh.", nDigitsForNObjects, S.s_nDestroyed);
+        writefln("s_nConstructed should be equal to s_nDestroyed.");
+        writefln("");
+    }
+
+    assert(S.s_nDestroyed == S.s_nConstructed);
+}
+
+
 /**
  * _Array type with deterministic control of memory. The memory allocated
  * for the array is reclaimed as soon as possible; there is no reliance
@@ -441,32 +560,28 @@ if (!is(immutable T == immutable bool))
     this(U)(U[] values...)
     if (isImplicitlyConvertible!(U, T))
     {
-        import core.lifetime : emplace;
-
-        static if (T.sizeof == 1)
+        // [2021-07-17] Checking to see whether *always* calling ensureInitialized works-around-and/or-is-related-to https://issues.dlang.org/show_bug.cgihttps://issues.dlang.org/show_bug.cgi...
+        //if (values.length)
         {
-            const nbytes = values.length;
-        }
-        else
-        {
-            import core.checkedint : mulu;
-            bool overflow;
-            const nbytes = mulu(values.length, T.sizeof, overflow);
-            if (overflow)
-                assert(false, "Overflow");
-        }
-        auto p = cast(T*) enforceMalloc(nbytes);
-        // Before it is added to the gc, initialize the newly allocated memory
-        foreach (i, e; values)
-        {
-            emplace(p + i, e);
-        }
-        static if (hasIndirections!T)
-        {
-            if (p)
-                GC.addRange(p, T.sizeof * values.length);
+            _data.refCountedStore.ensureInitialized();
+            _data.reserve(values.length);
+            foreach (ref value; values)
+            {
+                // We do not simply write "_data.insertBack(value);"
+                // because that might perform, on each iteration, a now-redundant check of length vs capacity.
+                // Thanks to @dkorpel (https://github.com/dlang/phobos/pull/8162#discussion_r667479090).
+
+                import core.lifetime : emplace;
+                emplace(_data._payload.ptr + _data._payload.length, value);
+
+                // We increment the length after each iteration (as opposed to adjusting it just once, after the loop)
+                // in order to improve error-safety (in case one of the calls to emplace throws).
+                _data._payload = _data._payload.ptr[0 .. _data._payload.length + 1];
+            }
         }
-        _data = Data(p[0 .. values.length]);
+
+        assert(length == values.length);   // We check that all values have been inserted.
+        assert(capacity == values.length); // We check that reserve has been called before the loop.
     }
 
     /**
@@ -563,9 +678,9 @@ if (!is(immutable T == immutable bool))
      * Complexity: $(BIGOH 1).
      */
 
-    T[] data() @system
+    inout(T)[] data() inout @system
     {
-        return _data._payload;
+        return _data.refCountedStore.isInitialized ? _data._payload : [];
     }
 
     /**
@@ -581,34 +696,11 @@ if (!is(immutable T == immutable bool))
      */
     void reserve(size_t elements)
     {
-        if (!_data.refCountedStore.isInitialized)
-        {
-            if (!elements) return;
-            static if (T.sizeof == 1)
-            {
-                const sz = elements;
-            }
-            else
-            {
-                import core.checkedint : mulu;
-                bool overflow;
-                const sz = mulu(elements, T.sizeof, overflow);
-                if (overflow)
-                    assert(false, "Overflow");
-            }
-            auto p = enforceMalloc(sz);
-            static if (hasIndirections!T)
-            {
-                // Zero out unused capacity to prevent gc from seeing false pointers
-                memset(p, 0, sz);
-                GC.addRange(p, sz);
-            }
-            _data = Data(cast(T[]) p[0 .. 0]);
-            _data._capacity = elements;
-        }
-        else
+        if (elements > capacity)
         {
+            _data.refCountedStore.ensureInitialized();
             _data.reserve(elements);
+            assert(capacity == elements); // Might need changing to ">=" if implementation of Payload.reserve is changed.
         }
     }
 
@@ -2628,9 +2720,19 @@ if (is(immutable T == immutable bool))
 
 @system unittest
 {
+
     Array!int arr = [1, 2, 4, 5];
     int[] data = arr.data();
 
+    const Array!int arr2 = [8, 9];
+    assert(arr2.data() == [8, 9]);
+
     data[0] = 0;
     assert(arr[0] == 0);
+
+    arr.length = 0;
+    assert(arr.data == []);
+
+    Array!int empty;
+    assert(empty.data == []);
 }
index 18b8524d7add3a44bdbf239b47a7b775b4702002..4da1281f98a0faec05f1bb9aa738e5bcc2865341 100644 (file)
@@ -8308,12 +8308,17 @@ public:
         YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
         is the time zone).
 
+        Default behaviour:
         Note that the number of digits in the fractional seconds varies with the
         number of fractional seconds. It's a maximum of 7 (which would be
         hnsecs), but only has as many as are necessary to hold the correct value
         (so no trailing zeroes), and if there are no fractional seconds, then
         there is no decimal point.
 
+        The optional parameter "prec" allows to change the default behavior by
+        specifying the precision of the fractional seconds. The accepted values
+        are in the range [-1, 7], where -1 represents the default behavior.
+
         If this $(LREF SysTime)'s time zone is
         $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
         zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
@@ -8325,25 +8330,30 @@ public:
         Params:
             writer = A `char` accepting
             $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
+            prec = An `int` representing the desired precision. Acceptable values range from -1 to 7, where -1 represents the default behavior.
         Returns:
             A `string` when not using an output range; `void` otherwise.
       +/
-    string toISOExtString() @safe const nothrow scope
+    string toISOExtString(int prec = -1) @safe const nothrow scope
     {
+        assert(prec >= -1 && prec <= 7, "Precision must be in the range [-1, 7]");
+
         import std.array : appender;
         auto app = appender!string();
         app.reserve(35);
         try
-            toISOExtString(app);
+            toISOExtString(app, prec);
         catch (Exception e)
             assert(0, "toISOExtString() threw.");
         return app.data;
     }
 
     /// ditto
-    void toISOExtString(W)(ref W writer) const scope
+    void toISOExtString(W)(ref W writer, int prec = -1) const scope
     if (isOutputRange!(W, char))
     {
+        assert(prec >= -1 && prec <= 7, "Precision must be in the range [-1, 7]");
+
         immutable adjustedTime = adjTime;
         long hnsecs = adjustedTime;
 
@@ -8365,14 +8375,14 @@ public:
         if (_timezone is LocalTime())
         {
             dateTime.toISOExtString(writer);
-            fracSecsToISOString(writer, cast(int) hnsecs);
+            fracSecsToISOString(writer, cast(int) hnsecs, prec);
             return;
         }
 
         if (_timezone is UTC())
         {
             dateTime.toISOExtString(writer);
-            fracSecsToISOString(writer, cast(int) hnsecs);
+            fracSecsToISOString(writer, cast(int) hnsecs, prec);
             put(writer, 'Z');
             return;
         }
@@ -8380,7 +8390,7 @@ public:
         immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
 
         dateTime.toISOExtString(writer);
-        fracSecsToISOString(writer, cast(int) hnsecs);
+        fracSecsToISOString(writer, cast(int) hnsecs, prec);
         SimpleTimeZone.toISOExtString(writer, utcOffset);
     }
 
@@ -8401,6 +8411,15 @@ public:
 
         assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
                "-0004-01-05T00:00:02.052092");
+
+        assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(4) ==
+               "-0004-01-05T00:00:02.0520");
+
+        assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(2) ==
+               "-0004-01-05T00:00:02.05");
+
+        assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(7) ==
+               "-0004-01-05T00:00:02.0520920");
     }
 
     @safe unittest
@@ -11025,32 +11044,41 @@ private:
 /+
     Returns the given hnsecs as an ISO string of fractional seconds.
   +/
-string fracSecsToISOString(int hnsecs) @safe pure nothrow
+string fracSecsToISOString(int hnsecs, int prec = -1) @safe pure nothrow
 {
     import std.array : appender;
     auto w = appender!string();
     try
-        fracSecsToISOString(w, hnsecs);
+        fracSecsToISOString(w, hnsecs, prec);
     catch (Exception e)
         assert(0, "fracSecsToISOString() threw.");
     return w.data;
 }
 
-void fracSecsToISOString(W)(ref W writer, int hnsecs)
+void fracSecsToISOString(W)(ref W writer, int hnsecs, int prec = -1)
 {
     import std.conv : toChars;
     import std.range : padLeft;
 
     assert(hnsecs >= 0);
 
+    if (prec == 0)
+        return;
+
     if (hnsecs == 0)
         return;
 
     put(writer, '.');
     auto chars = hnsecs.toChars.padLeft('0', 7);
-    while (chars.back == '0')
-        chars.popBack();
-    put(writer, chars);
+
+    if (prec == -1)
+    {
+        while (chars.back == '0')
+            chars.popBack();
+        put(writer, chars);
+    }
+    else
+        put(writer, chars[0 .. prec]);
 }
 
 @safe unittest
index 5df42e728c3de1c8e6ff71aa95a01d87fe6ede11..052758097a92b621caff6d4606f0b0fe657b74dd 100644 (file)
@@ -332,6 +332,7 @@ public:
         version (Posix)
         {
             version (FreeBSD)            enum utcZone = "Etc/UTC";
+            else version (OpenBSD)       enum utcZone = "UTC";
             else version (NetBSD)        enum utcZone = "UTC";
             else version (DragonFlyBSD)  enum utcZone = "UTC";
             else version (linux)         enum utcZone = "UTC";
index 4a5deca6884a81ff6358954690ab4029e2c2073f..0fdc2519b18c4c4096b76aebb03f03d418ff55c5 100644 (file)
@@ -210,7 +210,7 @@ struct RIPEMD160
          * RIPEMD160 basic transformation. Transforms state based on block.
          */
 
-        private void transform(const(ubyte[64])* block)
+        void transform(const(ubyte[64])* block)
             pure nothrow @nogc
         {
             uint aa = _state[0],
index 5fcee2ab598a15dc1b4f35145462a0fef79f1353..4f7f3c3915323849c93617bdf198f123e021b49e 100644 (file)
@@ -191,7 +191,7 @@ auto assertNotThrown(T : Throwable = Exception, E)
 {
     import core.exception : AssertError;
 
-    void throwEx(Throwable t) { throw t; }
+    static noreturn throwEx(Throwable t) { throw t; }
     bool nothrowEx() { return true; }
 
     try
@@ -294,7 +294,9 @@ void assertThrown(T : Throwable = Exception, E)
         expression();
     catch (T)
         return;
-    throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"
+
+    static if (!is(immutable E == immutable noreturn))
+        throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"
                                  ~ (msg.length == 0 ? "." : ": ") ~ msg,
                           file, line);
 }
@@ -318,7 +320,7 @@ void assertThrown(T : Throwable = Exception, E)
 {
     import core.exception : AssertError;
 
-    void throwEx(Throwable t) { throw t; }
+    static noreturn throwEx(Throwable t) { throw t; }
     void nothrowEx() { }
 
     try
@@ -666,7 +668,9 @@ T collectException(T = Exception, E)(lazy E expression, ref E result)
     {
         return e;
     }
-    return null;
+    // Avoid "statement not reachable" warning
+    static if (!is(immutable E == immutable noreturn))
+        return null;
 }
 ///
 @system unittest
@@ -675,9 +679,14 @@ T collectException(T = Exception, E)(lazy E expression, ref E result)
     int foo() { throw new Exception("blah"); }
     assert(collectException(foo(), b));
 
-    int[] a = new int[3];
-    import core.exception : RangeError;
-    assert(collectException!RangeError(a[4], b));
+    version (D_NoBoundsChecks) {}
+    else
+    {
+        // check for out of bounds error
+        int[] a = new int[3];
+        import core.exception : RangeError;
+        assert(collectException!RangeError(a[4], b));
+    }
 }
 
 /++
@@ -706,7 +715,9 @@ T collectException(T : Throwable = Exception, E)(lazy E expression)
     {
         return t;
     }
-    return null;
+    // Avoid "statement not reachable" warning
+    static if (!is(immutable E == immutable noreturn))
+        return null;
 }
 
 ///
@@ -742,7 +753,9 @@ string collectExceptionMsg(T = Exception, E)(lazy E expression)
     {
         expression();
 
-        return cast(string) null;
+        // Avoid "statement not reachable" warning
+        static if (!is(immutable E == immutable noreturn))
+            return cast(string) null;
     }
     catch (T e)
         return e.msg.empty ? emptyExceptionMsg : e.msg;
@@ -766,6 +779,25 @@ string collectExceptionMsg(T = Exception, E)(lazy E expression)
  +/
 enum emptyExceptionMsg = "<Empty Exception Message>";
 
+// https://issues.dlang.org/show_bug.cgi?id=22364
+@system unittest
+{
+    static noreturn foo() { throw new Exception(""); }
+
+    const ex = collectException!(Exception, noreturn)(foo());
+    assert(ex);
+
+    const msg = collectExceptionMsg!(Exception, noreturn)(foo());
+    assert(msg);
+
+    noreturn n;
+
+    // Triggers a backend assertion failure
+    // collectException!(Exception, noreturn)(foo(), n);
+
+    static assert(__traits(compiles, collectException!(Exception, noreturn)(foo(), n)));
+}
+
 /**
  * Casts a mutable array to an immutable array in an idiomatic
  * manner. Technically, `assumeUnique` just inserts a cast,
index b33c2ed354d06e884aea1c5b02ff45f877e554ce..354851bfc84f76cf58ccfc7b77ed84ed8fd9a4a6 100644 (file)
@@ -1614,9 +1614,9 @@ static:
     been evaluated
     bound = The bound being violated
 
-    Returns: `cast(Lhs) rhs`
+    Returns: `cast(T) rhs`
     */
-    Lhs onLowerBound(Rhs, T)(Rhs rhs, T bound)
+    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
     {
         trustedStderr.writefln("Lower bound error: %s(%s) < %s(%s)",
             Rhs.stringof, rhs, T.stringof, bound);
@@ -1793,6 +1793,12 @@ static:
     assert(witness == expected, "'" ~ witness ~ "'");
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=22249
+@safe unittest
+{
+    alias _ = Warn.onLowerBound!(int, int);
+}
+
 // ProperCompare
 /**
 
index 741656d74a7bcd8233c1aa2fd9a0668d471aa2fc..1bfed64eae544cf18381113cde449b4593c6298d 100644 (file)
@@ -400,25 +400,23 @@ version (Posix) private void[] readImpl(scope const(char)[] name, scope const(FS
         : result[0 .. size.get];
 }
 
+version (Windows)
+private extern (Windows) @nogc nothrow
+{
+    pragma(mangle, CreateFileW.mangleof)
+    HANDLE trustedCreateFileW(scope const(wchar)* namez, DWORD dwDesiredAccess,
+        DWORD dwShareMode, SECURITY_ATTRIBUTES* lpSecurityAttributes,
+        DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
+        HANDLE hTemplateFile)  @trusted;
+
+    pragma(mangle, CloseHandle.mangleof) BOOL trustedCloseHandle(HANDLE) @trusted;
+}
 
 version (Windows) private void[] readImpl(scope const(char)[] name, scope const(FSChar)* namez,
                                           size_t upTo = size_t.max) @trusted
 {
     import core.memory : GC;
     import std.algorithm.comparison : min;
-    static trustedCreateFileW(scope const(wchar)* namez, DWORD dwDesiredAccess, DWORD dwShareMode,
-                              SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
-                              DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
-    {
-        return CreateFileW(namez, dwDesiredAccess, dwShareMode,
-                           lpSecurityAttributes, dwCreationDisposition,
-                           dwFlagsAndAttributes, hTemplateFile);
-
-    }
-    static trustedCloseHandle(HANDLE hObject)
-    {
-        return CloseHandle(hObject);
-    }
     static trustedGetFileSize(HANDLE hFile, out ulong fileSize)
     {
         DWORD sizeHigh;
@@ -1125,6 +1123,9 @@ version (Windows) private ulong makeUlong(DWORD dwLow, DWORD dwHigh) @safe pure
     return li.QuadPart;
 }
 
+version (Posix) private extern (C) pragma(mangle, stat.mangleof)
+int trustedStat(const(FSChar)* namez, ref stat_t buf) @nogc nothrow @trusted;
+
 /**
 Get size of file `name` in bytes.
 
@@ -1148,10 +1149,6 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
     {
         auto namez = name.tempCString();
 
-        static trustedStat(const(FSChar)* namez, out stat_t buf) @trusted
-        {
-            return stat(namez, &buf);
-        }
         static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
             alias names = name;
         else
@@ -1253,10 +1250,6 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
     {
         auto namez = name.tempCString();
 
-        static auto trustedStat(const(FSChar)* namez, ref stat_t buf) @trusted
-        {
-            return stat(namez, &buf);
-        }
         stat_t statbuf = void;
 
         static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
@@ -1679,10 +1672,6 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
     else version (Posix)
     {
         auto namez = name.tempCString!FSChar();
-        static auto trustedStat(const(FSChar)* namez, ref stat_t buf) @trusted
-        {
-            return stat(namez, &buf);
-        }
         stat_t statbuf = void;
 
         static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
@@ -1770,10 +1759,6 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R))
     else version (Posix)
     {
         auto namez = name.tempCString!FSChar();
-        static auto trustedStat(const(FSChar)* namez, ref stat_t buf) @trusted
-        {
-            return stat(namez, &buf);
-        }
         stat_t statbuf = void;
 
         return trustedStat(namez, statbuf) != 0 ?
@@ -2042,10 +2027,6 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
     else version (Posix)
     {
         auto namez = name.tempCString!FSChar();
-        static auto trustedStat(const(FSChar)* namez, ref stat_t buf) @trusted
-        {
-            return stat(namez, &buf);
-        }
         stat_t statbuf = void;
 
         static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
@@ -5275,9 +5256,20 @@ slurp(Types...)(string filename, scope const(char)[] format)
     assert(slurp!(int)(deleteme, "%d") == [10, 20]);
 }
 
-
 /**
 Returns the path to a directory for temporary files.
+On POSIX platforms, it searches through the following list of directories
+and returns the first one which is found to exist:
+$(OL
+    $(LI The directory given by the `TMPDIR` environment variable.)
+    $(LI The directory given by the `TEMP` environment variable.)
+    $(LI The directory given by the `TMP` environment variable.)
+    $(LI `/tmp/`)
+    $(LI `/var/tmp/`)
+    $(LI `/usr/tmp/`)
+)
+
+On all platforms, `tempDir` returns the current working directory on failure.
 
 The return value of the function is cached, so the procedures described
 below will only be performed the first time the function is called.  All
@@ -5308,6 +5300,7 @@ Returns:
 */
 string tempDir() @trusted
 {
+    import std.path : dirSeparator;
     static string cache;
     if (cache is null)
     {
@@ -5327,7 +5320,7 @@ string tempDir() @trusted
             static string findExistingDir(T...)(lazy T alternatives)
             {
                 foreach (dir; alternatives)
-                    if (!dir.empty && exists(dir)) return dir;
+                    if (!dir.empty && exists(dir)) return dir ~ dirSeparator;
                 return null;
             }
 
@@ -5340,7 +5333,10 @@ string tempDir() @trusted
         }
         else static assert(false, "Unsupported platform");
 
-        if (cache is null) cache = getcwd();
+        if (cache is null)
+        {
+            cache = getcwd() ~ dirSeparator;
+        }
     }
     return cache;
 }
@@ -5363,6 +5359,13 @@ string tempDir() @trusted
     assert(myFile.readText == "hello");
 }
 
+@safe unittest
+{
+    import std.algorithm.searching : endsWith;
+    import std.path : dirSeparator;
+    assert(tempDir.endsWith(dirSeparator));
+}
+
 /**
 Returns the available disk space based on a given path.
 On Windows, `path` must be a directory; on POSIX systems, it can be a file or directory.
index 81b21dc4995e7502cb8234eecfde66d26eb1edf8..632bf7674a67202845efb32b3e2dc2165da018c0 100644 (file)
@@ -17,7 +17,7 @@ module std.format.internal.floats;
 import std.format.spec : FormatSpec;
 
 // wrapper for unittests
-private auto printFloat(T, Char)(T val, FormatSpec!Char f)
+private auto printFloat(T, Char)(const(T) val, FormatSpec!Char f)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
 {
@@ -28,7 +28,7 @@ if (is(T == float) || is(T == double)
     return w.data;
 }
 
-package(std.format) void printFloat(Writer, T, Char)(auto ref Writer w, T val, FormatSpec!Char f)
+package(std.format) void printFloat(Writer, T, Char)(auto ref Writer w, const(T) val, FormatSpec!Char f)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
 {
@@ -76,7 +76,7 @@ if (is(T == float) || is(T == double)
     }
 }
 
-private void printFloatA(Writer, T, Char)(auto ref Writer w, T val,
+private void printFloatA(Writer, T, Char)(auto ref Writer w, const(T) val,
     FormatSpec!Char f, string sgn, int exp, ulong mnt, bool is_upper)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
@@ -586,7 +586,7 @@ if (is(T == float) || is(T == double)
     assert(printFloat(0x1.19f01p0, f) == "0X1.19FP+0");
 }
 
-private void printFloatE(bool g, Writer, T, Char)(auto ref Writer w, T val,
+private void printFloatE(bool g, Writer, T, Char)(auto ref Writer w, const(T) val,
     FormatSpec!Char f, string sgn, int exp, ulong mnt, bool is_upper)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
@@ -1505,7 +1505,7 @@ if (is(T == float) || is(T == double)
     });
 }
 
-private void printFloatF(bool g, Writer, T, Char)(auto ref Writer w, T val,
+private void printFloatF(bool g, Writer, T, Char)(auto ref Writer w, const(T) val,
     FormatSpec!Char f, string sgn, int exp, ulong mnt, bool is_upper)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
@@ -2268,7 +2268,7 @@ if (is(T == float) || is(T == double)
            ~"7175706828388979108268586060148663818836212158203125");
 }
 
-private void printFloatG(Writer, T, Char)(auto ref Writer w, T val,
+private void printFloatG(Writer, T, Char)(auto ref Writer w, const(T) val,
     FormatSpec!Char f, string sgn, int exp, ulong mnt, bool is_upper)
 if (is(T == float) || is(T == double)
     || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64)))
index 5883d8d3259ea53e8bc53fd52ab3d9583ad2774b..68b9e4dacccf5141bc1af6ca6216023ac3752270 100644 (file)
@@ -28,7 +28,7 @@ package(std.format):
     `bool`s are formatted as `"true"` or `"false"` with `%s` and as `1` or
     `0` with integral-specific format specs.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     BooleanTypeOf!T val = obj;
@@ -123,7 +123,7 @@ if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 /*
     `null` literal is formatted as `"null"`
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(immutable T == immutable typeof(null)) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.format : enforceFmt;
@@ -157,11 +157,9 @@ if (is(immutable T == immutable typeof(null)) && !is(T == enum) && !hasToString!
 /*
     Integrals are formatted like $(REF printf, core, stdc, stdio).
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
-    import std.range.primitives : put;
-
     alias U = IntegralTypeOf!T;
     U val = obj;    // Extracting alias this may be impure/system/may-throw
 
@@ -171,56 +169,46 @@ if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
         auto raw = (ref val) @trusted {
             return (cast(const char*) &val)[0 .. val.sizeof];
         }(val);
-
+        import std.range.primitives : put;
         if (needToSwapEndianess(f))
-        {
             foreach_reverse (c; raw)
                 put(w, c);
-        }
         else
-        {
             foreach (c; raw)
                 put(w, c);
-        }
         return;
     }
 
-    immutable uint base =
-        f.spec == 'x' || f.spec == 'X' || f.spec == 'a' || f.spec == 'A' ? 16 :
-        f.spec == 'o' ? 8 :
-        f.spec == 'b' ? 2 :
-        f.spec == 's' || f.spec == 'd' || f.spec == 'u'
-        || f.spec == 'e' || f.spec == 'E' || f.spec == 'f' || f.spec == 'F'
-        || f.spec == 'g' || f.spec == 'G' ? 10 :
-        0;
-
-    import std.format : enforceFmt;
-    enforceFmt(base > 0,
-        "incompatible format character for integral argument: %" ~ f.spec);
-
-    import std.math.algebraic : abs;
-
-    bool negative = false;
-    ulong arg = val;
     static if (isSigned!U)
     {
-        if (f.spec != 'x' && f.spec != 'X' && f.spec != 'b' && f.spec != 'o' && f.spec != 'u')
-        {
-            if (val < 0)
-            {
-                negative = true;
-                arg = cast(ulong) abs(val);
-            }
-        }
+        const negative = val < 0 && f.spec != 'x' && f.spec != 'X' && f.spec != 'b' && f.spec != 'o' && f.spec != 'u';
+        ulong arg = negative ? -cast(ulong) val : val;
+    }
+    else
+    {
+        const negative = false;
+        ulong arg = val;
     }
-
     arg &= Unsigned!U.max;
 
+    formatValueImplUlong!(Writer, Char)(w, arg, negative, f);
+}
+
+// Helper function for `formatValueImpl` that avoids template bloat
+private void formatValueImplUlong(Writer, Char)(auto ref Writer w, ulong arg, in bool negative,
+                                                scope const ref FormatSpec!Char f)
+{
+    immutable uint base = baseOfSpec(f.spec);
+
+    const bool zero = arg == 0;
     char[64] digits = void;
     size_t pos = digits.length - 1;
     do
     {
-        digits[pos--] = '0' + arg % base;
+        /* `cast(char)` is needed because value range propagation (VRP) cannot
+         * analyze `base` because it’s computed in a separate function
+         * (`baseOfSpec`). */
+        digits[pos--] = cast(char) ('0' + arg % base);
         if (base > 10 && digits[pos + 1] > '9')
             digits[pos + 1] += ((f.spec == 'x' || f.spec == 'a') ? 'a' : 'A') - '0' - 10;
         arg /= base;
@@ -245,12 +233,12 @@ if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
     if (f.spec == 'x' || f.spec == 'X' || f.spec == 'b' || f.spec == 'o' || f.spec == 'u'
         || f.spec == 'd' || f.spec == 's')
     {
-        if (f.flHash && (base == 16) && obj != 0)
+        if (f.flHash && (base == 16) && !zero)
         {
             prefix[--left] = f.spec;
             prefix[--left] = '0';
         }
-        if (f.flHash && (base == 8) && obj != 0
+        if (f.flHash && (base == 8) && !zero
             && (digits.length - (pos + 1) >= f.precision || f.precision == f.UNSPECIFIED))
             prefix[--left] = '0';
 
@@ -358,6 +346,48 @@ if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
                  (f.spec == 'g' || f.spec == 'G') ? PrecisionType.allDigits : PrecisionType.fractionalDigits);
 }
 
+private uint baseOfSpec(in char spec) @safe pure
+{
+    typeof(return) base =
+        spec == 'x' || spec == 'X' || spec == 'a' || spec == 'A' ? 16 :
+        spec == 'o' ? 8 :
+        spec == 'b' ? 2 :
+        spec == 's' || spec == 'd' || spec == 'u'
+        || spec == 'e' || spec == 'E' || spec == 'f' || spec == 'F'
+        || spec == 'g' || spec == 'G' ? 10 :
+        0;
+
+    import std.format : enforceFmt;
+    enforceFmt(base > 0,
+        "incompatible format character for integral argument: %" ~ spec);
+
+    return base;
+}
+
+@safe pure unittest
+{
+    assertCTFEable!(
+    {
+        formatTest(byte.min, "-128");
+        formatTest(byte.max, "127");
+        formatTest(short.min, "-32768");
+        formatTest(short.max, "32767");
+        formatTest(int.min, "-2147483648");
+        formatTest(int.max, "2147483647");
+        formatTest(long.min, "-9223372036854775808");
+        formatTest(long.max, "9223372036854775807");
+
+        formatTest(ubyte.min, "0");
+        formatTest(ubyte.max, "255");
+        formatTest(ushort.min, "0");
+        formatTest(ushort.max, "65535");
+        formatTest(uint.min, "0");
+        formatTest(uint.max, "4294967295");
+        formatTest(ulong.min, "0");
+        formatTest(ulong.max, "18446744073709551615");
+    });
+}
+
 // https://issues.dlang.org/show_bug.cgi?id=18838
 @safe pure unittest
 {
@@ -577,7 +607,8 @@ if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 /*
     Floating-point values are formatted like $(REF printf, core, stdc, stdio)
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj,
+                                      scope const ref FormatSpec!Char f)
 if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.algorithm.searching : find;
@@ -986,7 +1017,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
     Formatting a `creal` is deprecated but still kept around for a while.
  */
 deprecated("Use of complex types is deprecated. Use std.complex")
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(immutable T : immutable creal) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.range.primitives : put;
@@ -1006,7 +1037,7 @@ if (is(immutable T : immutable creal) && !is(T == enum) && !hasToString!(T, Char
     Formatting an `ireal` is deprecated but still kept around for a while.
  */
 deprecated("Use of imaginary types is deprecated. Use std.complex")
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(immutable T : immutable ireal) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.range.primitives : put;
@@ -1021,7 +1052,7 @@ if (is(immutable T : immutable ireal) && !is(T == enum) && !hasToString!(T, Char
     Individual characters are formatted as Unicode characters with `%s`
     and as integers with integral-specific format specs
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.meta : AliasSeq;
@@ -1111,11 +1142,11 @@ if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 /*
     Strings are formatted like $(REF printf, core, stdc, stdio)
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope T obj,
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope const(T) obj,
     scope const ref FormatSpec!Char f)
 if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
-    Unqual!(StringTypeOf!T) val = obj;  // for `alias this`, see bug5371
+    Unqual!(const(StringTypeOf!T)) val = obj;  // for `alias this`, see bug5371
     formatRange(w, val, f);
 }
 
@@ -1306,7 +1337,7 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
 /*
     Static-size arrays are formatted as dynamic arrays.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref T obj,
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref const(T) obj,
     scope const ref FormatSpec!Char f)
 if (is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
@@ -1751,13 +1782,13 @@ void formatChar(Writer)(ref Writer w, in dchar c, in char quote)
     Associative arrays are formatted by using `':'` and $(D ", ") as
     separators, and enclosed by `'['` and `']'`.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
 if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.format : enforceFmt, formatValue;
     import std.range.primitives : put;
 
-    AssocArrayTypeOf!T val = obj;
+    AssocArrayTypeOf!(const(T)) val = obj;
     const spec = f.spec;
 
     enforceFmt(spec == 's' || spec == '(',
@@ -2540,12 +2571,21 @@ if ((is(T == struct) || is(T == union)) && (hasToString!(T, Char) || !is(Builtin
             else static if (0 < i && val.tupleof[i-1].offsetof == val.tupleof[i].offsetof)
             {
                 static if (i == val.tupleof.length - 1 || val.tupleof[i].offsetof != val.tupleof[i+1].offsetof)
-                    put(w, separator~val.tupleof[i].stringof[4 .. $]~"}");
+                {
+                    enum el = separator ~ val.tupleof[i].stringof[4 .. $] ~ "}";
+                    put(w, el);
+                }
                 else
-                    put(w, separator~val.tupleof[i].stringof[4 .. $]);
+                {
+                    enum el = separator ~ val.tupleof[i].stringof[4 .. $];
+                    put(w, el);
+                }
             }
             else static if (i+1 < val.tupleof.length && val.tupleof[i].offsetof == val.tupleof[i+1].offsetof)
-                put(w, (i > 0 ? separator : "")~"#{overlap "~val.tupleof[i].stringof[4 .. $]);
+            {
+                enum el = (i > 0 ? separator : "") ~ "#{overlap " ~ val.tupleof[i].stringof[4 .. $];
+                put(w, el);
+            }
             else
             {
                 static if (i > 0)
@@ -2846,7 +2886,7 @@ void enforceValidFormatSpec(T, Char)(scope const ref FormatSpec!Char f)
 /*
     `enum`s are formatted like their base value
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, T val, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) val, scope const ref FormatSpec!Char f)
 if (is(T == enum))
 {
     import std.array : appender;
@@ -2866,7 +2906,9 @@ if (is(T == enum))
         auto w2 = appender!string();
 
         // val is not a member of T, output cast(T) rawValue instead.
-        put(w2, "cast(" ~ T.stringof ~ ")");
+        put(w2, "cast(");
+        put(w2, T.stringof);
+        put(w2, ")");
         static assert(!is(OriginalType!T == T), "OriginalType!" ~ T.stringof ~
             "must not be equal to " ~ T.stringof);
 
@@ -2934,7 +2976,7 @@ if (is(T == enum))
 /*
     Pointers are formatted as hex integers.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope T val, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope const(T) val, scope const ref FormatSpec!Char f)
 if (isPointer!T && !is(T == enum) && !hasToString!(T, Char))
 {
     static if (is(typeof({ shared const void* p = val; })))
@@ -3048,7 +3090,7 @@ if (isPointer!T && !is(T == enum) && !hasToString!(T, Char))
 /*
     SIMD vectors are formatted as arrays.
  */
-void formatValueImpl(Writer, V, Char)(auto ref Writer w, V val, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, V, Char)(auto ref Writer w, const(V) val, scope const ref FormatSpec!Char f)
 if (isSIMDVector!V)
 {
     formatValueImpl(w, val.array, f);
@@ -3082,7 +3124,7 @@ if (isSIMDVector!V)
     Known bug: Because of issue https://issues.dlang.org/show_bug.cgi?id=18269
                the FunctionAttributes might be wrong.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope T, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, scope const(T), scope const ref FormatSpec!Char f)
 if (isDelegate!T)
 {
     formatValueImpl(w, T.stringof, f);
index cec61fef57585c421b8a8e9b5433f59f7132b34c..b251e4006eceff4746eb971a883ee8d3e2e99770 100644 (file)
@@ -1056,26 +1056,23 @@ Note: In the special case where only a single function is provided
 (`F[0]`).
 */
 template adjoin(F...)
-if (F.length == 1)
+if (F.length >= 1)
 {
-    alias adjoin = F[0];
-}
-/// ditto
-template adjoin(F...)
-if (F.length > 1)
-{
-    auto adjoin(V...)(auto ref V a)
-    {
-        import std.typecons : tuple;
-        import std.meta : staticMap;
-
-        auto resultElement(size_t i)()
+    static if (F.length == 1)
+        alias adjoin = F[0];
+    else
+        auto adjoin(V...)(auto ref V a)
         {
-            return F[i](a);
-        }
+            import std.typecons : tuple;
+            import std.meta : staticMap;
 
-        return tuple(staticMap!(resultElement, Iota!(F.length)));
-    }
+            auto resultElement(size_t i)()
+            {
+                return F[i](a);
+            }
+
+            return tuple(staticMap!(resultElement, Iota!(F.length)));
+        }
 }
 
 ///
index d516012ac4a4afebc469811e1d5454c95c7938f9..482aae6306a3aa5de5a8904b86f2dfcf37145bd8 100644 (file)
@@ -771,7 +771,7 @@ private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
                     args = args.remove(i);
                 break;
             }
-            if (!a.length || a[0] != optionChar)
+            if (a.length < 2 || a[0] != optionChar)
             {
                 // not an option
                 if (cfg.stopOnFirstNonOption) break;
@@ -1890,6 +1890,17 @@ void defaultGetoptFormatter(Output)(Output output, string text, Option[] opt, st
     assert(f == "-");
 }
 
+// Hyphen at the option value;
+// https://issues.dlang.org/show_bug.cgi?id=22394
+@safe unittest
+{
+    auto args = ["program", "-"];
+
+    getopt(args);
+
+    assert(args == ["program", "-"]);
+}
+
 @safe unittest
 {
     import std.conv;
index 59d784265c137d4b75b3b2068d9681913870096f..79446756fa6c4273b846aadfa959b867432492d4 100644 (file)
@@ -1910,7 +1910,6 @@ pure @safe unittest
 }
 
 
-private:
 // Converts a big uint to a hexadecimal string.
 //
 // Optionally, a separator character (eg, an underscore) may be added between
@@ -2185,7 +2184,6 @@ do
 }
 
 
-private:
 // ------------------------
 // These in-place functions are only for internal use; they are incompatible
 // with COW.
@@ -2628,8 +2626,6 @@ again:
     }
 }
 
-private:
-
 // TODO: Replace with a library call
 void itoaZeroPadded(char[] output, uint value)
     pure nothrow @safe @nogc
@@ -2669,8 +2665,6 @@ void toHexZeroPadded(char[] output, uint value,
     }
 }
 
-private:
-
 // Returns the highest value of i for which left[i]!=right[i],
 // or 0 if left[] == right[]
 size_t highestDifferentDigit(const BigDigit [] left, const BigDigit [] right)
index 2220eec63ece6533ce690d61d750cdb6afbded8f..6f999ba80196a4fb856cd9966abf3150d70df3cc 100644 (file)
@@ -16,17 +16,21 @@ import core.sys.windows.winbase, core.sys.windows.winnt, core.sys.windows.winreg
 
 pragma(lib, "advapi32.lib");
 
-immutable bool isWow64;
-
-shared static this()
+@property bool isWow64()
 {
     // WOW64 is the x86 emulator that allows 32-bit Windows-based applications to run seamlessly on 64-bit Windows
     // IsWow64Process Function - Minimum supported client - Windows Vista, Windows XP with SP2
+    static int result = -1; // <0 if uninitialized, >0 if yes, ==0 if no
+    if (result >= 0)
+        return result > 0;  // short path
+    // Will do this work once per thread to avoid importing std.concurrency
+    // or doing gnarly initonce work.
     alias fptr_t = extern(Windows) BOOL function(HANDLE, PBOOL);
     auto hKernel = GetModuleHandleA("kernel32");
     auto IsWow64Process = cast(fptr_t) GetProcAddress(hKernel, "IsWow64Process");
     BOOL bIsWow64;
-    isWow64 = IsWow64Process && IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64;
+    result = IsWow64Process && IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64;
+    return result > 0;
 }
 
 HMODULE hAdvapi32 = null;
index 39f89a60c04c7b79702563b8f39d0e436dd30ed5..af7aa383d8e4882a20398b60173f0ab169209610 100644 (file)
@@ -735,13 +735,13 @@ struct JSONValue
      * Tests wether a key can be found in an object.
      *
      * Returns:
-     *      when found, the `const(JSONValue)*` that matches to the key,
+     *      when found, the `inout(JSONValue)*` that matches to the key,
      *      otherwise `null`.
      *
      * Throws: `JSONException` if the right hand side argument `JSONType`
      * is not `object`.
      */
-    auto opBinaryRight(string op : "in")(string k) const @safe
+    inout(JSONValue)* opBinaryRight(string op : "in")(string k) inout @safe
     {
         return k in this.objectNoRef;
     }
@@ -750,6 +750,8 @@ struct JSONValue
     {
         JSONValue j = [ "language": "D", "author": "walter" ];
         string a = ("author" in j).str;
+        *("author" in j) = "Walter";
+        assert(j["author"].str == "Walter");
     }
 
     bool opEquals(const JSONValue rhs) const @nogc nothrow pure @safe
index ae7cbf941b4f724b89103da2e599b63d9db9e05f..db70b7a555268c6de27cf6e2afa653c313568ded 100644 (file)
@@ -595,6 +595,12 @@ if (isFloatingPoint!T1 && isFloatingPoint!T2)
     return r;
 }
 
+version (linux)             version = GenericPosixVersion;
+else version (FreeBSD)      version = GenericPosixVersion;
+else version (OpenBSD)      version = GenericPosixVersion;
+else version (Solaris)      version = GenericPosixVersion;
+else version (DragonFlyBSD) version = GenericPosixVersion;
+
 private real polyImpl(real x, in real[] A) @trusted pure nothrow @nogc
 {
     version (D_InlineAsm_X86)
@@ -631,7 +637,7 @@ private real polyImpl(real x, in real[] A) @trusted pure nothrow @nogc
         return_ST:                              ;
             }
         }
-        else version (linux)
+        else version (GenericPosixVersion)
         {
             asm pure nothrow @nogc // assembler by W. Bright
             {
@@ -685,87 +691,6 @@ private real polyImpl(real x, in real[] A) @trusted pure nothrow @nogc
         return_ST:                              ;
             }
         }
-        else version (FreeBSD)
-        {
-            asm pure nothrow @nogc // assembler by W. Bright
-            {
-                // EDX = (A.length - 1) * real.sizeof
-                mov     ECX,A[EBP]              ; // ECX = A.length
-                dec     ECX                     ;
-                lea     EDX,[ECX*8]             ;
-                lea     EDX,[EDX][ECX*4]        ;
-                add     EDX,A+4[EBP]            ;
-                fld     real ptr [EDX]          ; // ST0 = coeff[ECX]
-                jecxz   return_ST               ;
-                fld     x[EBP]                  ; // ST0 = x
-                fxch    ST(1)                   ; // ST1 = x, ST0 = r
-                align   4                       ;
-        L2:     fmul    ST,ST(1)                ; // r *= x
-                fld     real ptr -12[EDX]       ;
-                sub     EDX,12                  ; // deg--
-                faddp   ST(1),ST                ;
-                dec     ECX                     ;
-                jne     L2                      ;
-                fxch    ST(1)                   ; // ST1 = r, ST0 = x
-                fstp    ST(0)                   ; // dump x
-                align   4                       ;
-        return_ST:                              ;
-            }
-        }
-        else version (Solaris)
-        {
-            asm pure nothrow @nogc // assembler by W. Bright
-            {
-                // EDX = (A.length - 1) * real.sizeof
-                mov     ECX,A[EBP]              ; // ECX = A.length
-                dec     ECX                     ;
-                lea     EDX,[ECX*8]             ;
-                lea     EDX,[EDX][ECX*4]        ;
-                add     EDX,A+4[EBP]            ;
-                fld     real ptr [EDX]          ; // ST0 = coeff[ECX]
-                jecxz   return_ST               ;
-                fld     x[EBP]                  ; // ST0 = x
-                fxch    ST(1)                   ; // ST1 = x, ST0 = r
-                align   4                       ;
-        L2:     fmul    ST,ST(1)                ; // r *= x
-                fld     real ptr -12[EDX]       ;
-                sub     EDX,12                  ; // deg--
-                faddp   ST(1),ST                ;
-                dec     ECX                     ;
-                jne     L2                      ;
-                fxch    ST(1)                   ; // ST1 = r, ST0 = x
-                fstp    ST(0)                   ; // dump x
-                align   4                       ;
-        return_ST:                              ;
-            }
-        }
-        else version (DragonFlyBSD)
-        {
-            asm pure nothrow @nogc // assembler by W. Bright
-            {
-                // EDX = (A.length - 1) * real.sizeof
-                mov     ECX,A[EBP]              ; // ECX = A.length
-                dec     ECX                     ;
-                lea     EDX,[ECX*8]             ;
-                lea     EDX,[EDX][ECX*4]        ;
-                add     EDX,A+4[EBP]            ;
-                fld     real ptr [EDX]          ; // ST0 = coeff[ECX]
-                jecxz   return_ST               ;
-                fld     x[EBP]                  ; // ST0 = x
-                fxch    ST(1)                   ; // ST1 = x, ST0 = r
-                align   4                       ;
-        L2:     fmul    ST,ST(1)                ; // r *= x
-                fld     real ptr -12[EDX]       ;
-                sub     EDX,12                  ; // deg--
-                faddp   ST(1),ST                ;
-                dec     ECX                     ;
-                jne     L2                      ;
-                fxch    ST(1)                   ; // ST1 = r, ST0 = x
-                fstp    ST(0)                   ; // dump x
-                align   4                       ;
-        return_ST:                              ;
-            }
-        }
         else
         {
             static assert(0);
index dfb1aeea587df4e766c979282ac75b7f930dc872..cb3c805f76f06e79430c2bf00fd53dff9d586b0b 100644 (file)
@@ -1717,11 +1717,12 @@ if (isFloatingPoint!T)
     bool negative;
 }
 
-FloatingPointBitpattern!T extractBitpattern(T)(T val) @trusted
+FloatingPointBitpattern!T extractBitpattern(T)(const(T) value) @trusted
 if (isFloatingPoint!T)
 {
     import std.math : floatTraits, RealFormat;
 
+    T val = value;
     FloatingPointBitpattern!T ret;
 
     alias F = floatTraits!T;
index 1209987eabd8d2c08bc5537d7a605889fa0f8cf7..0075ed7edf7d94a1bf622b53959d05b9e4e98285 100644 (file)
@@ -511,30 +511,19 @@ if (args.length >= 2)
 }
 
 /**
- * Returns an `AliasSeq` created from TList with all occurrences
- * of T, if found, replaced with U.
+ * Returns an `AliasSeq` created from `args[2 .. $]` with all occurrences
+ * of `args[0]`, if any, replaced with `args[1]`.
  */
-template ReplaceAll(T, U, TList...)
-{
-    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
-}
-
-/// Ditto
-template ReplaceAll(alias T, U, TList...)
+template ReplaceAll(args...)
 {
-    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
-}
-
-/// Ditto
-template ReplaceAll(T, alias U, TList...)
-{
-    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
-}
-
-/// Ditto
-template ReplaceAll(alias T, alias U, TList...)
-{
-    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
+    alias ReplaceAll = AliasSeq!();
+    static foreach (arg; args[2 .. $])
+    {
+        static if (isSame!(args[0], arg))
+            ReplaceAll = AliasSeq!(ReplaceAll, args[1]);
+        else
+            ReplaceAll = AliasSeq!(ReplaceAll, arg);
+    }
 }
 
 ///
@@ -546,31 +535,6 @@ template ReplaceAll(alias T, alias U, TList...)
     static assert(is(TL == AliasSeq!(int, char, char, int, float)));
 }
 
-// [internal]
-private template GenericReplaceAll(args...)
-if (args.length >= 2)
-{
-    alias from  = OldAlias!(args[0]);
-    alias to    = OldAlias!(args[1]);
-    alias tuple = args[2 .. $];
-
-    static if (tuple.length)
-    {
-        alias head = OldAlias!(tuple[0]);
-        alias tail = tuple[1 .. $];
-        alias next = GenericReplaceAll!(from, to, tail).result;
-
-        static if (isSame!(from, head))
-            alias result = AliasSeq!(to, next);
-        else
-            alias result = AliasSeq!(head, next);
-    }
-    else
-    {
-        alias result = AliasSeq!();
-    }
-}
-
 @safe unittest
 {
     static assert(Pack!(ReplaceAll!(byte, ubyte,
@@ -658,29 +622,40 @@ template DerivedToFront(TList...)
     static assert(is(TL2 == AliasSeq!(C, C, C, B, B, B, A, A, A)));
 }
 
-private enum staticMapExpandFactor = 150;
-private string generateCases()
-{
-    string[staticMapExpandFactor] chunks;
-    chunks[0] = q{};
-    static foreach (enum i; 0 .. staticMapExpandFactor - 1)
-        chunks[i + 1] = chunks[i] ~ `F!(Args[` ~ i.stringof ~ `]),`;
-    string ret = `AliasSeq!(`;
-    foreach (chunk; chunks)
-        ret ~= `q{alias staticMap = AliasSeq!(` ~ chunk ~ `);},`;
-    return ret ~ `)`;
-}
-private alias staticMapBasicCases = AliasSeq!(mixin(generateCases()));
-
 /**
-Evaluates to $(D AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
+Evaluates to `AliasSeq!(fun!(args[0]), fun!(args[1]), ..., fun!(args[$ - 1]))`.
  */
-template staticMap(alias F, Args ...)
+template staticMap(alias fun, args...)
 {
-    static if (Args.length < staticMapExpandFactor)
-        mixin(staticMapBasicCases[Args.length]);
-    else
-        alias staticMap = AliasSeq!(staticMap!(F, Args[0 .. $/2]), staticMap!(F, Args[$/2 .. $]));
+    version (__staticMap_simplest_but_buggy)
+    {
+        // @@@ BUG @@@
+        // The following straightforward implementation exposes a bug.
+        // See issue https://issues.dlang.org/show_bug.cgi?id=22421 and unittest below.
+        alias staticMap = AliasSeq!();
+        static foreach (arg; args)
+             staticMap = AliasSeq!(staticMap, fun!arg);
+    }
+    else version (__staticMap_simple_but_slow)
+    {
+        // This has a performance bug. Appending to the staticMap seems to be quadratic.
+        alias staticMap = AliasSeq!();
+        static foreach (i; 0 .. args.length)
+            staticMap = AliasSeq!(staticMap, fun!(args[i]));
+    }
+    else // Current best-of-breed implementation imitates quicksort
+    {
+        static if (args.length <= 8)
+        {
+            alias staticMap = AliasSeq!();
+            static foreach (i; 0 .. args.length)
+                staticMap = AliasSeq!(staticMap, fun!(args[i]));
+        }
+        else
+        {
+            alias staticMap = AliasSeq!(staticMap!(fun, args[0 .. $ / 2]), staticMap!(fun, args[$ / 2 .. $]));
+        }
+    }
 }
 
 ///
@@ -705,6 +680,14 @@ template staticMap(alias F, Args ...)
 
     alias T = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort, long);
     static assert(is(T == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort, long)));
+
+    // @@@ BUG @@@ The test below exposes failure of the straightforward use.
+    // See @adamdruppe's comment to https://github.com/dlang/phobos/pull/8039
+    template id(alias what) {
+            enum id = __traits(identifier, what);
+    }
+    enum A { a }
+    static assert(staticMap!(id, A.a) == AliasSeq!("a"));
 }
 
 // regression test for https://issues.dlang.org/show_bug.cgi?id=21088
@@ -716,17 +699,25 @@ template staticMap(alias F, Args ...)
     assert(A == typeid(int));
 }
 
-/**
-Tests whether all given items satisfy a template predicate, i.e. evaluates to
-$(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
+version (StdDdoc)
+{
+    /**
+       Tests whether all given items satisfy a template predicate, i.e. evaluates to
+       $(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
 
-Evaluation is $(I not) short-circuited if a false result is encountered; the
-template predicate must be instantiable with all the given items.
- */
-template allSatisfy(alias F, T...)
+       Evaluation is $(I not) short-circuited if a false result is encountered; the
+       template predicate must be instantiable with all the given items.
+    */
+    template allSatisfy(alias F, T...)
+    {
+        import core.internal.traits : allSat = allSatisfy;
+        alias allSatisfy = allSat!(F, T);
+    }
+}
+else
 {
     import core.internal.traits : allSat = allSatisfy;
-    alias allSatisfy = allSat!(F, T);
+    alias allSatisfy = allSat;
 }
 
 ///
@@ -738,17 +729,25 @@ template allSatisfy(alias F, T...)
     static assert( allSatisfy!(isIntegral, int, long));
 }
 
-/**
-Tests whether any given items satisfy a template predicate, i.e. evaluates to
-$(D F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1])).
+version (StdDdoc)
+{
+    /**
+       Tests whether any given items satisfy a template predicate, i.e. evaluates to
+       $(D F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1])).
 
-Evaluation is short-circuited if a true result is encountered; the
-template predicate must be instantiable with one of the given items.
- */
-template anySatisfy(alias F, T...)
+       Evaluation is short-circuited if a true result is encountered; the
+       template predicate must be instantiable with one of the given items.
+    */
+    template anySatisfy(alias F, T...)
+    {
+        import core.internal.traits : anySat = anySatisfy;
+        alias anySatisfy = anySat!(F, T);
+    }
+}
+else
 {
     import core.internal.traits : anySat = anySatisfy;
-    alias anySatisfy = anySat!(F, T);
+    alias anySatisfy = anySat;
 }
 
 ///
@@ -760,170 +759,16 @@ template anySatisfy(alias F, T...)
     static assert( anySatisfy!(isIntegral, int, double));
 }
 
-private alias FilterShortCode = AliasSeq!(
-    q{
-        alias Filter = Nothing;
-    },
-    q{
-        static if (pred!(TList[0]))
-            alias Filter = AliasSeq!(TList[0]);
-        else
-            alias Filter = Nothing;
-    },
-    q{
-        static if (pred!(TList[0]))
-        {
-            static if (pred!(TList[1]))
-                alias Filter = AliasSeq!(TList[0], TList[1]);
-            else
-                alias Filter = AliasSeq!(TList[0]);
-        }
-        else
-        {
-            static if (pred!(TList[1]))
-                alias Filter = AliasSeq!(TList[1]);
-            else
-                alias Filter = Nothing;
-        }
-    },
-    q{
-        static if (pred!(TList[0]))
-        {
-            static if (pred!(TList[1]))
-            {
-                static if (pred!(TList[2]))
-                    alias Filter = AliasSeq!(TList[0], TList[1], TList[2]);
-                else
-                    alias Filter = AliasSeq!(TList[0], TList[1]);
-            }
-            else
-            {
-                static if (pred!(TList[2]))
-                    alias Filter = AliasSeq!(TList[0], TList[2]);
-                else
-                    alias Filter = AliasSeq!(TList[0]);
-            }
-        }
-        else
-        {
-            static if (pred!(TList[1]))
-            {
-                static if (pred!(TList[2]))
-                    alias Filter = AliasSeq!(TList[1], TList[2]);
-                else
-                    alias Filter = AliasSeq!(TList[1]);
-            }
-            else
-            {
-                static if (pred!(TList[2]))
-                    alias Filter = AliasSeq!(TList[2]);
-                else
-                    alias Filter = Nothing;
-            }
-        }
-    },
-    q{
-        static if (pred!(TList[0]))
-        {
-            static if (pred!(TList[1]))
-            {
-                static if (pred!(TList[2]))
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[0], TList[1], TList[2], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[0], TList[1], TList[2]);
-                }
-                else
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[0], TList[1], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[0], TList[1]);
-                }
-            }
-            else
-            {
-                static if (pred!(TList[2]))
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[0], TList[2], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[0], TList[2]);
-                }
-                else
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[0], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[0]);
-                }
-            }
-        }
-        else
-        {
-            static if (pred!(TList[1]))
-            {
-                static if (pred!(TList[2]))
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[1], TList[2], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[1], TList[2]);
-                }
-                else
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[1], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[1]);
-                }
-            }
-            else
-            {
-                static if (pred!(TList[2]))
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[2], TList[3]);
-                    else
-                        alias Filter = AliasSeq!(TList[2]);
-                }
-                else
-                {
-                    static if (pred!(TList[3]))
-                        alias Filter = AliasSeq!(TList[3]);
-                    else
-                        alias Filter = Nothing;
-                }
-            }
-        }
-    }
-);
-
-private enum filterExpandFactor = FilterShortCode.length;
-
-package alias Nothing = AliasSeq!(); // yes, this really does speed up compilation!
 /**
  * Filters an `AliasSeq` using a template predicate. Returns an
  * `AliasSeq` of the elements which satisfy the predicate.
  */
-template Filter(alias pred, TList ...)
+template Filter(alias pred, args...)
 {
-    static if (TList.length < filterExpandFactor)
-    {
-        mixin(FilterShortCode[TList.length]);
-    }
-    else
-    {
-        template MaybeNothing(Q ...)
-        {
-            static if (pred!(Q[0]))
-                alias MaybeNothing = AliasSeq!(Q[0]);
-            else
-                alias MaybeNothing = Nothing;
-        }
-        alias Filter = staticMap!(MaybeNothing, TList);
-    }
+    alias Filter = AliasSeq!();
+    static foreach (arg; args)
+        static if (pred!arg)
+            Filter = AliasSeq!(Filter, arg);
 }
 
 ///
@@ -993,6 +838,7 @@ template templateNot(alias pred)
     static assert(allSatisfy!(isNoPointer, string, char, float));
 }
 
+version (StdUnittest)
 @safe unittest
 {
     static foreach (T; AliasSeq!(int, staticMap, 42))
@@ -1044,6 +890,7 @@ template templateAnd(Preds...)
     static assert(alwaysTrue!int);
 }
 
+version (StdUnittest)
 @safe unittest
 {
     static foreach (T; AliasSeq!(int, staticMap, 42))
@@ -1102,6 +949,7 @@ template templateOr(Preds...)
     static assert(!alwaysFalse!int);
 }
 
+version (StdUnittest)
 @safe unittest
 {
     static foreach (T; AliasSeq!(int, staticMap, 42))
@@ -1427,28 +1275,18 @@ template Repeat(size_t n, items...)
  *     cmp = A template that returns a `bool` (if its first argument is less than the second one)
  *         or an `int` (-1 means less than, 0 means equal, 1 means greater than)
  *
- *     Seq = The  $(LREF AliasSeq) to sort
+ *     items = The  $(LREF AliasSeq) to sort
  *
  * Returns: The sorted alias sequence
  */
-template staticSort(alias cmp, Seq...)
+template staticSort(alias cmp, items...)
 {
-    static if (Seq.length < 2)
-    {
-        alias staticSort = Seq;
-    }
+    static if (items.length < 2)
+        alias staticSort = items;
     else
-    {
-        private alias btm = staticSort!(cmp, Seq[0 .. $ / 2]);
-        private alias top = staticSort!(cmp, Seq[$ / 2 .. $]);
-
-        static if (isLessEq!(cmp, btm[$ - 1], top[0]))
-            alias staticSort = AliasSeq!(btm, top); // already ascending
-        else static if (isLessEq!(cmp, top[$ - 1], btm[0]))
-            alias staticSort = AliasSeq!(top, btm); // already descending
-        else
-            alias staticSort = staticMerge!(cmp, Seq.length / 2, btm, top);
-    }
+        alias staticSort = staticMerge!(cmp, items.length / 2,
+            staticSort!(cmp, items[0 .. $ / 2]),
+            staticSort!(cmp, items[$ / 2 .. $]));
 }
 
 ///
@@ -1468,25 +1306,21 @@ template staticSort(alias cmp, Seq...)
         Types)));
 }
 
-private template staticMerge(alias cmp, int half, Seq...)
+private template staticMerge(alias cmp, uint mid, items...)
 {
-    static if (half == 0 || half == Seq.length)
+    enum run =
     {
-        alias staticMerge = Seq;
-    }
+        static if (mid < items.length)
+            static foreach (i, item; items[0 .. mid])
+                static if (!isLessEq!(cmp, item, items[mid]))
+                    if (__ctfe) return i;
+        return mid;
+    }();
+    static if (run == mid)
+        alias staticMerge = items;
     else
-    {
-        static if (isLessEq!(cmp, Seq[0], Seq[half]))
-        {
-            alias staticMerge = AliasSeq!(Seq[0],
-                staticMerge!(cmp, half - 1, Seq[1 .. $]));
-        }
-        else
-        {
-            alias staticMerge = AliasSeq!(Seq[half],
-                staticMerge!(cmp, half, Seq[0 .. half], Seq[half + 1 .. $]));
-        }
-    }
+        alias staticMerge = AliasSeq!(items[0 .. run], items[mid],
+            staticMerge!(cmp, mid - run, items[run .. mid], items[mid + 1 .. $]));
 }
 
 private template isLessEq(alias cmp, Seq...)
index 664330a3c2b0ba3d965129a0d47c7b0610db7f13..bd467d21c3fe1a000c5187a05d28c8db494016ec 100644 (file)
@@ -955,16 +955,46 @@ uint totalCPUsImpl() @nogc nothrow @trusted
     }
     else version (linux)
     {
-        import core.sys.linux.sched : CPU_COUNT, cpu_set_t, sched_getaffinity;
+        import core.stdc.stdlib : calloc;
+        import core.stdc.string : memset;
+        import core.sys.linux.sched : CPU_ALLOC_SIZE, CPU_FREE, CPU_COUNT, CPU_COUNT_S, cpu_set_t, sched_getaffinity;
         import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
 
-        cpu_set_t set = void;
-        if (sched_getaffinity(0, cpu_set_t.sizeof, &set) == 0)
+        int count = 0;
+
+        /**
+         * According to ruby's source code, CPU_ALLOC() doesn't work as expected.
+         *  see: https://github.com/ruby/ruby/commit/7d9e04de496915dd9e4544ee18b1a0026dc79242
+         *
+         *  The hardcode number also comes from ruby's source code.
+         *  see: https://github.com/ruby/ruby/commit/0fa75e813ecf0f5f3dd01f89aa76d0e25ab4fcd4
+         */
+        for (int n = 64; n <= 16384; n *= 2)
         {
-            int count = CPU_COUNT(&set);
+            size_t size = CPU_ALLOC_SIZE(count);
+            if (size >= 0x400)
+            {
+                auto cpuset = cast(cpu_set_t*) calloc(1, size);
+                if (cpuset is null) break;
+                if (sched_getaffinity(0, size, cpuset) == 0)
+                {
+                    count = CPU_COUNT_S(size, cpuset);
+                }
+                CPU_FREE(cpuset);
+            }
+            else
+            {
+                cpu_set_t cpuset;
+                if (sched_getaffinity(0, cpu_set_t.sizeof, &cpuset) == 0)
+                {
+                    count = CPU_COUNT(&cpuset);
+                }
+            }
+
             if (count > 0)
                 return cast(uint) count;
         }
+
         return cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
     }
     else version (Darwin)
@@ -2733,9 +2763,6 @@ public:
                 }
             }
 
-            foreach (ref t; tasks[])
-                emplaceRef(t, RTask());
-
             // Hack to take the address of a nested function w/o
             // making a closure.
             static auto scopedAddress(D)(scope D del) @system
@@ -2748,12 +2775,19 @@ public:
             void useTask(ref RTask task)
             {
                 import std.algorithm.comparison : min;
+                import core.lifetime : emplace;
+
+                // Private constructor, so can't feed it's arguments directly
+                // to emplace
+                emplace(&task, RTask
+                (
+                    scopedAddress(&reduceOnRange),
+                    range,
+                    curPos, // lower bound.
+                    cast() min(len, curPos + workUnitSize)  // upper bound.
+                ));
 
                 task.pool = this;
-                task._args[0] = scopedAddress(&reduceOnRange);
-                task._args[3] = min(len, curPos + workUnitSize);  // upper bound.
-                task._args[1] = range;  // range
-                task._args[2] = curPos; // lower bound.
 
                 curPos += workUnitSize;
             }
@@ -3505,6 +3539,21 @@ public:
     assert(taskPool.fold!("a + b", "a + b")(r, 0, 0, 42) == tuple(expected, expected));
 }
 
+// Issue 16705
+@system unittest
+{
+    struct MyIota
+    {
+        size_t front;
+        void popFront()(){front++;}
+        auto empty(){return front >= 25;}
+        auto opIndex(size_t i){return front+i;}
+        auto length(){return 25-front;}
+    }
+
+    auto mySum = taskPool.reduce!"a + b"(MyIota());
+}
+
 /**
 Returns a lazily initialized global instantiation of `TaskPool`.
 This function can safely be called concurrently from multiple non-worker
index 7ec8fa1dc59395ce60c6bc07b44a605689647da6..98c5b9467485ebcf787609a5496203cc3558f954 100644 (file)
@@ -1498,10 +1498,10 @@ package(std) string searchPathFor(scope const(char)[] executable)
     @safe
 {
     import std.algorithm.iteration : splitter;
-    import std.conv : text;
+    import std.conv : to;
     import std.path : chainPath;
 
-    string result;
+    typeof(return) result;
 
     environment.getImpl("PATH",
         (scope const(char)[] path)
@@ -1514,7 +1514,7 @@ package(std) string searchPathFor(scope const(char)[] executable)
                 auto execPath = chainPath(dir, executable);
                 if (isExecutable(execPath))
                 {
-                    result = text(execPath);
+                    result = execPath.to!(typeof(result));
                     return;
                 }
             }
@@ -1580,6 +1580,7 @@ private void setCLOEXEC(int fd, bool on) nothrow @nogc
 // calls, but we make do...
 version (Posix) @system unittest
 {
+    import core.stdc.errno : errno;
     import core.sys.posix.fcntl : open, O_RDONLY;
     import core.sys.posix.unistd : close;
     import std.algorithm.searching : canFind, findSplitBefore;
@@ -1594,7 +1595,20 @@ version (Posix) @system unittest
     scope(exit) std.file.rmdirRecurse(directory);
     auto path = buildPath(directory, "tmp");
     std.file.write(path, null);
+    errno = 0;
     auto fd = open(path.tempCString, O_RDONLY);
+    if (fd == -1)
+    {
+        import core.stdc.string : strerror;
+        import std.stdio : stderr;
+        import std.string : fromStringz;
+
+        // For the CI logs
+        stderr.writefln("%s: could not open '%s': %s",
+            __FUNCTION__, path, strerror(errno).fromStringz);
+        // TODO: should we retry here instead?
+        return;
+    }
     scope(exit) close(fd);
 
     // command >&2 (or any other number) checks whethether that number
@@ -1642,7 +1656,12 @@ version (Posix) @system unittest
         if (lsofRes.status == 0)
         {
             assert(!lsofRes.output.canFind(path));
-            assert(execute(lsof.path, null, Config.inheritFDs).output.canFind(path));
+            auto lsofOut = execute(lsof.path, null, Config.inheritFDs).output;
+            if (!lsofOut.canFind(path))
+            {
+                std.stdio.stderr.writeln(__FILE__, ':', __LINE__,
+                    ": Warning: unexpected lsof output:", lsofOut);
+            }
             return;
         }
 
index 441bc5d55339638ef25bb9602b12c6c632428e59..a3483561134944f75ba6b8f1d096ee782103332e 100644 (file)
@@ -1799,13 +1799,19 @@ how excellent the source of entropy is.
                 {
                     db 0x0f, 0xc7, 0xf0; // rdrand EAX
                     jnc LnotUsingRdrand;
+                    mov result, EAX;
                     // Some AMD CPUs shipped with bugs where RDRAND could fail
                     // but still set the carry flag to 1. In those cases the
                     // output will be -1.
                     cmp EAX, 0xffff_ffff;
+                    jne LusingRdrand;
+                    // If result was -1 verify RDAND isn't constantly returning -1.
+                    db 0x0f, 0xc7, 0xf0;
+                    jnc LusingRdrand;
+                    cmp EAX, 0xffff_ffff;
                     je LnotUsingRdrand;
-                    mov result, EAX;
                 }
+            LusingRdrand:
                 return result;
             }
         LnotUsingRdrand:
@@ -1853,13 +1859,19 @@ if (isUnsigned!UIntType)
                             {
                                 db 0x0f, 0xc7, 0xf0; // rdrand EAX
                                 jnc LnotUsingRdrand;
+                                mov result, EAX;
                                 // Some AMD CPUs shipped with bugs where RDRAND could fail
                                 // but still set the carry flag to 1. In those cases the
                                 // output will be -1.
                                 cmp EAX, 0xffff_ffff;
+                                jne LusingRdrand;
+                                // If result was -1 verify RDAND isn't constantly returning -1.
+                                db 0x0f, 0xc7, 0xf0;
+                                jnc LusingRdrand;
+                                cmp EAX, 0xffff_ffff;
                                 je LnotUsingRdrand;
-                                mov result, EAX;
                             }
+                        LusingRdrand:
                             return cast(UIntType) result;
                         }
                         else version (D_InlineAsm_X86_64)
@@ -1869,13 +1881,19 @@ if (isUnsigned!UIntType)
                             {
                                 db 0x48, 0x0f, 0xc7, 0xf0; // rdrand RAX
                                 jnc LnotUsingRdrand;
+                                mov result, RAX;
                                 // Some AMD CPUs shipped with bugs where RDRAND could fail
                                 // but still set the carry flag to 1. In those cases the
                                 // output will be -1.
                                 cmp RAX, 0xffff_ffff_ffff_ffff;
+                                jne LusingRdrand;
+                                // If result was -1 verify RDAND isn't constantly returning -1.
+                                db 0x48, 0x0f, 0xc7, 0xf0;
+                                jnc LusingRdrand;
+                                cmp RAX, 0xffff_ffff_ffff_ffff;
                                 je LnotUsingRdrand;
-                                mov result, RAX;
                             }
+                        LusingRdrand:
                             return result;
                         }
                         else
index 4f8eba73278858532b288388bb4873894b15603b..475f35b51da31b183b0ef322870a1dbe183624e6 100644 (file)
@@ -100,7 +100,9 @@ interface InputRange(E) {
     ///
     @property E front();
 
-    ///
+    /**Calls $(REF moveFront, std, range, primitives) on the wrapped range, if
+     * possible. Otherwise, throws an $(LREF UnsupportedRangeMethod) exception.
+     */
     E moveFront();
 
     ///
@@ -162,7 +164,9 @@ interface BidirectionalRange(E) : ForwardRange!(E) {
     ///
     @property E back();
 
-    ///
+    /**Calls $(REF moveBack, std, range, primitives) on the wrapped range, if
+     * possible. Otherwise, throws an $(LREF UnsupportedRangeMethod) exception
+     */
     E moveBack();
 
     ///
@@ -197,7 +201,9 @@ interface RandomAccessFinite(E) : BidirectionalRange!(E) {
 
 /**Interface for an infinite random access range of type `E`.*/
 interface RandomAccessInfinite(E) : ForwardRange!E {
-    ///
+    /**Calls $(REF moveAt, std, range, primitives) on the wrapped range, if
+     * possible. Otherwise, throws an $(LREF UnsupportedRangeMethod) exception.
+     */
     E moveAt(size_t);
 
     ///
@@ -377,7 +383,11 @@ if (isInputRange!(Unqual!R))
             @property E front() { return _range.front; }
 
             E moveFront() {
-                return _range.moveFront();
+                static if (__traits(compiles, _range.moveFront()))
+                    return _range.moveFront();
+                else
+                    throw new UnsupportedRangeMethod(
+                        "Cannot move the front of a(n) `" ~ R.stringof ~ "`");
             }
 
             void popFront() { _range.popFront(); }
@@ -402,7 +412,11 @@ if (isInputRange!(Unqual!R))
                 @property E back() { return _range.back; }
 
                 E moveBack() {
-                    return _range.moveBack();
+                    static if (__traits(compiles, _range.moveFront()))
+                        return _range.moveBack();
+                    else
+                        throw new UnsupportedRangeMethod(
+                            "Cannot move the back of a(n) `" ~ R.stringof ~ "`");
                 }
 
                 void popBack() { return _range.popBack(); }
@@ -422,7 +436,11 @@ if (isInputRange!(Unqual!R))
                 }
 
                 E moveAt(size_t index) {
-                    return _range.moveAt(index);
+                    static if (__traits(compiles, _range.moveAt(index)))
+                        return _range.moveAt(index);
+                    else
+                        throw new UnsupportedRangeMethod(
+                            "Cannot move an element of a(n) `" ~ R.stringof ~ "`");
                 }
 
                 static if (hasAssignableElements!R)
@@ -520,6 +538,14 @@ template outputRangeObject(E...) {
      static assert(is(typeof(appWrapped) : OutputRange!(uint)));
 }
 
+/// Thrown when an interface method is not supported by the wrapped range
+class UnsupportedRangeMethod : Exception
+{
+    import std.exception : basicExceptionCtors;
+
+    mixin basicExceptionCtors;
+}
+
 @system unittest
 {
     import std.algorithm.comparison : equal;
@@ -568,3 +594,16 @@ template outputRangeObject(E...) {
     assert(app.data.length == 3);
     assert(equal(app.data, [1,2,3]));
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=19544
+@safe unittest
+{
+    import std.range : repeat;
+
+    static struct HasCC
+    {
+        inout this(ref inout typeof(this)) {}
+    }
+
+    auto r = repeat(HasCC.init).inputRangeObject;
+}
index 86bd4a1dd192406e73b0dbf34220788387cc5367..a21f4d017458e051d9b15ab64f8e6da8ced11edc 100644 (file)
@@ -902,7 +902,7 @@ if (Ranges.length > 0 &&
         private:
             alias R = staticMap!(Unqual, Ranges);
             alias RvalueElementType = CommonType!(staticMap!(.ElementType, R));
-            private template sameET(A)
+            template sameET(A)
             {
                 enum sameET = is(.ElementType!A == RvalueElementType);
             }
@@ -8427,7 +8427,7 @@ if (isForwardRange!Source && hasLength!Source)
     /// Ditto
     @property bool empty()
     {
-        return _source.empty;
+        return _chunkCount == 0;
     }
 
     /// Ditto
@@ -9713,9 +9713,18 @@ if (Values.length > 1)
 {
     private enum arity = Values.length;
 
+    private alias UnqualValues = staticMap!(Unqual, Values);
+
     private this(return scope ref Values values)
     {
-        this.values = values;
+        ref @trusted unqual(T)(ref T x){return cast() x;}
+
+        // TODO: this calls any possible copy constructors without qualifiers.
+        // Find a way to initialize values using qualified copy constructors.
+        static foreach (i; 0 .. Values.length)
+        {
+            this.values[i] = unqual(values[i]);
+        }
         this.backIndex = arity;
     }
 
@@ -9760,7 +9769,7 @@ if (Values.length > 1)
 
     alias opDollar = length;
 
-    CommonType!Values opIndex(size_t idx)
+    @trusted CommonType!Values opIndex(size_t idx)
     {
         // when i + idx points to elements popped
         // with popBack
@@ -9768,7 +9777,7 @@ if (Values.length > 1)
         final switch (frontIndex + idx)
             static foreach (i, T; Values)
             case i:
-                return values[i];
+                return cast(T) values[i];
     }
 
     OnlyResult opSlice()
@@ -9800,12 +9809,15 @@ if (Values.length > 1)
     {
         import std.traits : hasElaborateAssign;
         static if (hasElaborateAssign!T)
-            private Values values;
+            private UnqualValues values;
         else
-            private Values values = void;
+            private UnqualValues values = void;
     }
     else
-        private Values values;
+        // These may alias to shared or immutable data. Do not let the user
+        // to access these directly, and do not allow mutation without checking
+        // the qualifier.
+        private UnqualValues values;
 }
 
 // Specialize for single-element results
@@ -9814,12 +9826,12 @@ private struct OnlyResult(T)
     @property T front()
     {
         assert(!empty, "Attempting to fetch the front of an empty Only range");
-        return _value;
+        return fetchFront();
     }
     @property T back()
     {
         assert(!empty, "Attempting to fetch the back of an empty Only range");
-        return _value;
+        return fetchFront();
     }
     @property bool empty() const { return _empty; }
     @property size_t length() const { return !_empty; }
@@ -9838,14 +9850,17 @@ private struct OnlyResult(T)
 
     private this()(return scope auto ref T value)
     {
-        this._value = value;
+        ref @trusted unqual(ref T x){return cast() x;}
+        // TODO: this calls the possible copy constructor without qualifiers.
+        // Find a way to initialize value using a qualified copy constructor.
+        this._value = unqual(value);
         this._empty = false;
     }
 
     T opIndex(size_t i)
     {
         assert(!_empty && i == 0, "Attempting to fetch an out of bounds index from an Only range");
-        return _value;
+        return fetchFront();
     }
 
     OnlyResult opSlice()
@@ -9868,35 +9883,14 @@ private struct OnlyResult(T)
         return copy;
     }
 
+    // This may alias to shared or immutable data. Do not let the user
+    // to access this directly, and do not allow mutation without checking
+    // the qualifier.
     private Unqual!T _value;
     private bool _empty = true;
-}
-
-// Specialize for the empty range
-private struct OnlyResult()
-{
-    private static struct EmptyElementType {}
-
-    bool empty() @property { return true; }
-    size_t length() const @property { return 0; }
-    alias opDollar = length;
-    EmptyElementType front() @property { assert(false); }
-    void popFront() { assert(false); }
-    EmptyElementType back() @property { assert(false); }
-    void popBack() { assert(false); }
-    OnlyResult save() @property { return this; }
-
-    EmptyElementType opIndex(size_t i)
-    {
-        assert(false);
-    }
-
-    OnlyResult opSlice() { return this; }
-
-    OnlyResult opSlice(size_t from, size_t to)
+    private @trusted T fetchFront()
     {
-        assert(from == 0 && to == 0);
-        return this;
+        return *cast(T*)&_value;
     }
 }
 
@@ -9921,11 +9915,20 @@ Returns:
 See_Also: $(LREF chain) to chain ranges
  */
 auto only(Values...)(return scope Values values)
-if (!is(CommonType!Values == void) || Values.length == 0)
+if (!is(CommonType!Values == void))
 {
     return OnlyResult!Values(values);
 }
 
+/// ditto
+auto only()()
+{
+    // cannot use noreturn due to issue 22383
+    struct EmptyElementType {}
+    EmptyElementType[] result;
+    return result;
+}
+
 ///
 @safe unittest
 {
@@ -10157,6 +10160,19 @@ if (!is(CommonType!Values == void) || Values.length == 0)
     assert(range.join == "Hello World");
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=21022
+@safe pure nothrow unittest
+{
+    struct S
+    {
+        int* mem;
+    }
+
+    immutable S x;
+    immutable(S)[] arr;
+    auto r1 = arr.chain(x.only, only(x, x));
+}
+
 /**
 Iterate over `range` with an attached index variable.
 
@@ -12740,8 +12756,12 @@ if (isInputRange!R && isIntegral!(ElementType!R))
 
         import std.exception : assertThrown;
 
-        // Check out of bounds error
-        assertThrown!Error(bw[2 * bitsNum - 1]);
+        version (D_NoBoundsChecks) {}
+        else
+        {
+            // Check out of bounds error
+            assertThrown!Error(bw[2 * bitsNum - 1]);
+        }
 
         bw[2] = true;
         assert(bw[2] == true);
index 9c61ff5253a17f7d4b84b6adbd4122c902197fe6..c092a9d0946d868e05bc893303be114b0577346f 100644 (file)
@@ -2562,3 +2562,20 @@ package(std) mixin template ImplementLength(alias member)
         alias opDollar = length;
     }
 }
+
+@safe unittest
+{
+    import std.meta : AliasSeq;
+
+    foreach (alias E; AliasSeq!(noreturn, const(noreturn), immutable(noreturn) ))
+    {
+        alias R = E[];
+
+        static assert(isInputRange!R);
+        static assert(isForwardRange!R);
+        static assert(isBidirectionalRange!R);
+        static assert(isRandomAccessRange!R);
+    }
+
+    static assert(isOutputRange!(noreturn[], noreturn));
+}
index be0aeba5ca89a645bd558bba61a90bbc1f528d54..f8908cf76ef83eebd53fe3285572e98feb8cffbb 100644 (file)
@@ -2121,23 +2121,6 @@ enum SocketFlags: int
 }
 
 
-private mixin template FieldProxy(string target, string field)
-{
-    mixin(`
-        @property typeof(`~target~`) `~field~`() const pure nothrow @nogc
-        {
-            return `~target~`;
-        }
-
-        /// ditto
-        @property typeof(`~target~`) `~field~`(typeof(`~target~`) value) pure nothrow @nogc
-        {
-            return `~target~` = value;
-        }
-    `);
-}
-
-
 /// Duration timeout value.
 struct TimeVal
 {
@@ -2145,16 +2128,18 @@ struct TimeVal
     alias tv_sec_t = typeof(ctimeval.tv_sec);
     alias tv_usec_t = typeof(ctimeval.tv_usec);
 
-    version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
+    /// Number of _seconds.
+    pure nothrow @nogc @property
+    ref inout(tv_sec_t) seconds() inout return
     {
-        tv_sec_t seconds;           /// Number of _seconds.
-        tv_usec_t microseconds;     /// Number of additional _microseconds.
+        return ctimeval.tv_sec;
     }
-    else
+
+    /// Number of additional _microseconds.
+    pure nothrow @nogc @property
+    ref inout(tv_usec_t) microseconds() inout return
     {
-        // D interface
-        mixin FieldProxy!(`ctimeval.tv_sec`, `seconds`);
-        mixin FieldProxy!(`ctimeval.tv_usec`, `microseconds`);
+        return ctimeval.tv_usec;
     }
 }
 
@@ -2567,18 +2552,21 @@ struct Linger
 {
     _clinger clinger;
 
-    version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
+    private alias l_onoff_t = typeof(_clinger.init.l_onoff );
+    private alias l_linger_t = typeof(_clinger.init.l_linger);
+
+    /// Nonzero for _on.
+    pure nothrow @nogc @property
+    ref inout(l_onoff_t) on() inout return
     {
-        private alias l_onoff_t = typeof(_clinger.init.l_onoff );
-        private alias l_linger_t = typeof(_clinger.init.l_linger);
-        l_onoff_t  on;   /// Nonzero for _on.
-        l_linger_t time; /// Linger _time.
+        return clinger.l_onoff;
     }
-    else
+
+    /// Linger _time.
+    pure nothrow @nogc @property
+    ref inout(l_linger_t) time() inout return
     {
-        // D interface
-        mixin FieldProxy!(`clinger.l_onoff`, `on`);
-        mixin FieldProxy!(`clinger.l_linger`, `time`);
+        return clinger.l_linger;
     }
 }
 
@@ -3119,21 +3107,17 @@ public:
             from = createAddress();
         socklen_t nameLen = from.nameLen;
         version (Windows)
-        {
             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
-            from.setNameLen(nameLen);
-            assert(from.addressFamily == _family);
-            // if (!read) //connection closed
-            return read;
-        }
+
         else
-        {
             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
+
+        if (read >= 0)
+        {
             from.setNameLen(nameLen);
             assert(from.addressFamily == _family);
-            // if (!read) //connection closed
-            return read;
         }
+        return read;
     }
 
 
@@ -3576,6 +3560,17 @@ class UdpSocket: Socket
     }
 }
 
+@safe unittest
+{
+    byte[] buf;
+    buf.length = 1;
+    Address addr;
+    auto s = new UdpSocket;
+    s.blocking = false;
+    s.bind(new InternetAddress(InternetAddress.PORT_ANY));
+    s.receiveFrom(buf, addr);
+}
+
 // https://issues.dlang.org/show_bug.cgi?id=16514
 @safe unittest
 {
index a88beb8ff326e41eee74881f16cf52b10d82be7b..d3097d548ce2e1eb183c43591309fc0aa4cb2a1d 100644 (file)
@@ -281,17 +281,14 @@ else version (GENERIC_IO)
     nothrow:
     @nogc:
 
-    private int _FPUTC(int c, _iobuf* fp) { return fputc(c, cast(shared) fp); }
-    private int _FPUTWC(wchar_t c, _iobuf* fp)
+    extern (C) private
     {
-        import core.stdc.wchar_ : fputwc;
-        return fputwc(c, cast(shared) fp);
-    }
-    private int _FGETC(_iobuf* fp) { return fgetc(cast(shared) fp); }
-    private int _FGETWC(_iobuf* fp)
-    {
-        import core.stdc.wchar_ : fgetwc;
-        return fgetwc(cast(shared) fp);
+        static import core.stdc.wchar_;
+
+        pragma(mangle, fputc.mangleof) int _FPUTC(int c, _iobuf* fp);
+        pragma(mangle, core.stdc.wchar_.fputwc.mangleof) int _FPUTWC(wchar_t c, _iobuf* fp);
+        pragma(mangle, fgetc.mangleof) int _FGETC(_iobuf* fp);
+        pragma(mangle, core.stdc.wchar_.fgetwc.mangleof) int _FGETWC(_iobuf* fp);
     }
 
     version (Posix)
@@ -307,27 +304,19 @@ else version (GENERIC_IO)
     // @@@DEPRECATED_2.107@@@
     deprecated("internal function fputc_unlocked was unintentionally available "
                ~ "from std.stdio and will be removed afer 2.107")
-    int fputc_unlocked(int c, _iobuf* fp) { return fputc(c, cast(shared) fp); }
+    extern (C) pragma(mangle, fputc.mangleof) int fputc_unlocked(int c, _iobuf* fp);
     // @@@DEPRECATED_2.107@@@
     deprecated("internal function fputwc_unlocked was unintentionally available "
                ~ "from std.stdio and will be removed afer 2.107")
-    int fputwc_unlocked(wchar_t c, _iobuf* fp)
-    {
-        import core.stdc.wchar_ : fputwc;
-        return fputwc(c, cast(shared) fp);
-    }
+    extern (C) pragma(mangle, core.stdc.wchar_.fputwc.mangleof) int fputwc_unlocked(wchar_t c, _iobuf* fp);
     // @@@DEPRECATED_2.107@@@
     deprecated("internal function fgetc_unlocked was unintentionally available "
                ~ "from std.stdio and will be removed afer 2.107")
-    int fgetc_unlocked(_iobuf* fp) { return fgetc(cast(shared) fp); }
+    extern (C) pragma(mangle, fgetc.mangleof) int fgetc_unlocked(_iobuf* fp);
     // @@@DEPRECATED_2.107@@@
     deprecated("internal function fgetwc_unlocked was unintentionally available "
                ~ "from std.stdio and will be removed afer 2.107")
-    int fgetwc_unlocked(_iobuf* fp)
-    {
-        import core.stdc.wchar_ : fgetwc;
-        return fgetwc(cast(shared) fp);
-    }
+    extern (C) pragma(mangle, core.stdc.wchar_.fgetwc.mangleof) int fgetwc_unlocked(_iobuf* fp);
 
     // @@@DEPRECATED_2.107@@@
     deprecated("internal alias FPUTC was unintentionally available from "
@@ -363,6 +352,16 @@ else
     static assert(0, "unsupported C I/O system");
 }
 
+private extern (C) @nogc nothrow
+{
+    pragma(mangle, _FPUTC.mangleof) int trustedFPUTC(int ch, _iobuf* h) @trusted;
+
+    version (DIGITAL_MARS_STDIO)
+        pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(int ch, _iobuf* h) @trusted;
+    else
+        pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(wchar_t ch, _iobuf* h) @trusted;
+}
+
 static if (__traits(compiles, core.sys.posix.stdio.getdelim))
 {
     extern(C) nothrow @nogc
@@ -3183,16 +3182,7 @@ is empty, throws an `Exception`. In case of an I/O error throws
         /// ditto
         void put(C)(scope C c) @safe if (isSomeChar!C || is(C : const(ubyte)))
         {
-            import std.traits : Parameters;
             import std.utf : decodeFront, encode, stride;
-            static auto trustedFPUTC(int ch, _iobuf* h) @trusted
-            {
-                return _FPUTC(ch, h);
-            }
-            static auto trustedFPUTWC(Parameters!_FPUTWC[0] ch, _iobuf* h) @trusted
-            {
-                return _FPUTWC(ch, h);
-            }
 
             static if (c.sizeof == 1)
             {
index 420b68abe6a54fb0473aad19b842cec61fc3a2d3..5c9a2c946ba8090b0e40bd39ce26628c675cacf2 100644 (file)
@@ -1759,8 +1759,8 @@ if (isSomeChar!Char && isSomeChar!Char2)
         haystack = String to search for needles in.
         needles = Strings to search for in haystack.
         startIdx = slices haystack like this $(D haystack[startIdx .. $]). If
-            the startIdx is greater equal the length of haystack the functions
-            returns `-1`.
+            the startIdx is greater than or equal to the length of haystack the
+            functions returns `-1`.
         cs = Indicates whether the comparisons are case sensitive.
 */
 ptrdiff_t indexOfAny(Char,Char2)(const(Char)[] haystack, const(Char2)[] needles,
@@ -1926,8 +1926,8 @@ if (isSomeChar!Char && isSomeChar!Char2)
         haystack = String to search for needles in.
         needles = Strings to search for in haystack.
         stopIdx = slices haystack like this $(D haystack[0 .. stopIdx]). If
-            the stopIdx is greater equal the length of haystack the functions
-            returns `-1`.
+            the stopIdx is greater than or equal to the length of haystack the
+            functions returns `-1`.
         cs = Indicates whether the comparisons are case sensitive.
 */
 ptrdiff_t lastIndexOfAny(Char,Char2)(const(Char)[] haystack,
@@ -2105,8 +2105,8 @@ if (isSomeChar!Char && isSomeChar!Char2)
         haystack = String to search for needles in.
         needles = Strings to search for in haystack.
         startIdx = slices haystack like this $(D haystack[startIdx .. $]). If
-            the startIdx is greater equal the length of haystack the functions
-            returns `-1`.
+            the startIdx is greater than or equal to the length of haystack the
+            functions returns `-1`.
         cs = Indicates whether the comparisons are case sensitive.
 */
 ptrdiff_t indexOfNeither(Char,Char2)(const(Char)[] haystack,
@@ -2265,8 +2265,8 @@ if (isSomeChar!Char && isSomeChar!Char2)
         haystack = String to search for needles in.
         needles = Strings to search for in haystack.
         stopIdx = slices haystack like this $(D haystack[0 .. stopIdx]) If
-        the stopIdx is greater equal the length of haystack the functions
-        returns `-1`.
+            the stopIdx is greater than or equal to the length of haystack the
+            functions returns `-1`.
         cs = Indicates whether the comparisons are case sensitive.
 */
 ptrdiff_t lastIndexOfNeither(Char,Char2)(const(Char)[] haystack,
index 7a115da540951211c61059f6ddb6170010ad87b2..55fcfd773b7552df9760f4039c540ff12ced2075 100644 (file)
@@ -36,6 +36,7 @@ immutable
         watchOS,   /// watchOS
         freeBSD,   /// FreeBSD
         netBSD,    /// NetBSD
+        openBSD,   /// OpenBSD
         dragonFlyBSD, /// DragonFlyBSD
         solaris,   /// Solaris
         android,   /// Android
@@ -54,6 +55,7 @@ immutable
     else version (watchOS) OS os = OS.watchOS;
     else version (FreeBSD) OS os = OS.freeBSD;
     else version (NetBSD)  OS os = OS.netBSD;
+    else version (OpenBSD) OS os = OS.openBSD;
     else version (DragonFlyBSD) OS os = OS.dragonFlyBSD;
     else version (Posix)   OS os = OS.otherPosix;
     else OS os = OS.unknown;
index 230a7c677cf77cc90893aee3b557f717d2645e13..154141588baa691efabad1ae0058b43e4f078fc2 100644 (file)
@@ -562,15 +562,10 @@ struct MyStruct {}
 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
 -----------------
 */
-template fullyQualifiedName(T...)
-if (T.length == 1)
-{
+enum fullyQualifiedName(T) = fqnType!(T, false, false, false, false);
 
-    static if (is(T))
-        enum fullyQualifiedName = fqnType!(T[0], false, false, false, false);
-    else
-        enum fullyQualifiedName = fqnSym!(T[0]);
-}
+/// ditto
+enum fullyQualifiedName(alias T) = fqnSym!(T);
 
 ///
 @safe unittest
@@ -986,8 +981,8 @@ private template fqnType(T,
  * is not part of a type, but the attribute of the function
  * (see template $(LREF functionAttributes)).
  */
-template ReturnType(func...)
-if (func.length == 1 && isCallable!func)
+template ReturnType(alias func)
+if (isCallable!func)
 {
     static if (is(FunctionTypeOf!func R == return))
         alias ReturnType = R;
@@ -1045,8 +1040,8 @@ Get, as a tuple, the types of the parameters to a function, a pointer
 to function, a delegate, a struct with an `opCall`, a pointer to a
 struct with an `opCall`, or a class with an `opCall`.
 */
-template Parameters(func...)
-if (func.length == 1 && isCallable!func)
+template Parameters(alias func)
+if (isCallable!func)
 {
     static if (is(FunctionTypeOf!func P == function))
         alias Parameters = P;
@@ -1095,9 +1090,8 @@ alias ParameterTypeTuple = Parameters;
 Returns the number of arguments of function `func`.
 arity is undefined for variadic functions.
 */
-template arity(func...)
-if (func.length == 1 && isCallable!func &&
-    variadicFunctionStyle!func == Variadic.no)
+template arity(alias func)
+if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
 {
     enum size_t arity = Parameters!func.length;
 }
@@ -1143,8 +1137,8 @@ enum ParameterStorageClass : uint
 }
 
 /// ditto
-template ParameterStorageClassTuple(func...)
-if (func.length == 1 && isCallable!func)
+template ParameterStorageClassTuple(alias func)
+if (isCallable!func)
 {
     alias Func = FunctionTypeOf!func;
 
@@ -1308,8 +1302,8 @@ template extractParameterStorageClassFlags(Attribs...)
 /**
 Get, as a tuple, the identifiers of the parameters to a function symbol.
  */
-template ParameterIdentifierTuple(func...)
-if (func.length == 1 && isCallable!func)
+template ParameterIdentifierTuple(alias func)
+if (isCallable!func)
 {
     static if (is(FunctionTypeOf!func PT == __parameters))
     {
@@ -1331,7 +1325,7 @@ if (func.length == 1 && isCallable!func)
     }
     else
     {
-        static assert(0, func[0].stringof ~ " is not a function");
+        static assert(0, func.stringof ~ " is not a function");
 
         // Define dummy entities to avoid pointless errors
         template Get(size_t i) { enum Get = ""; }
@@ -1407,11 +1401,11 @@ if (func.length == 1 && isCallable!func)
 Get, as a tuple, the default value of the parameters to a function symbol.
 If a parameter doesn't have the default value, `void` is returned instead.
  */
-template ParameterDefaults(func...)
-if (func.length == 1 && isCallable!func)
+template ParameterDefaults(alias func)
+if (isCallable!func)
 {
     alias param_names = ParameterIdentifierTuple!func;
-    static if (is(FunctionTypeOf!(func[0]) PT == __parameters))
+    static if (is(FunctionTypeOf!(func) PT == __parameters))
     {
         template Get(size_t i)
         {
@@ -1444,7 +1438,7 @@ if (func.length == 1 && isCallable!func)
     }
     else
     {
-        static assert(0, func[0].stringof ~ " is not a function");
+        static assert(0, func.stringof ~ " is not a function");
 
         // Define dummy entities to avoid pointless errors
         template Get(size_t i) { enum Get = ""; }
@@ -1559,8 +1553,8 @@ enum FunctionAttribute : uint
 }
 
 /// ditto
-template functionAttributes(func...)
-if (func.length == 1 && isCallable!func)
+template functionAttributes(alias func)
+if (isCallable!func)
 {
     // @bug: workaround for opCall
     alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
@@ -2090,8 +2084,8 @@ Params:
 Returns:
     one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
 */
-template functionLinkage(func...)
-if (func.length == 1 && isCallable!func)
+template functionLinkage(alias func)
+if (isCallable!func)
 {
     enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
 }
@@ -2148,8 +2142,8 @@ enum Variadic
 }
 
 /// ditto
-template variadicFunctionStyle(func...)
-if (func.length == 1 && isCallable!func)
+template variadicFunctionStyle(alias func)
+if (isCallable!func)
 {
     enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
     enum Variadic variadicFunctionStyle =
@@ -2198,25 +2192,25 @@ Note:
 Do not confuse function types with function pointer types; function types are
 usually used for compile-time reflection purposes.
  */
-template FunctionTypeOf(func...)
-if (func.length == 1 && isCallable!func)
+template FunctionTypeOf(alias func)
+if (isCallable!func)
 {
-    static if ((is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func[0]) Fsym == delegate))
+    static if ((is(typeof(& func) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func) Fsym == delegate))
     {
         alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
     }
-    else static if (is(typeof(& func[0].opCall) Fobj == delegate) || is(typeof(& func[0].opCall!()) Fobj == delegate))
+    else static if (is(typeof(& func.opCall) Fobj == delegate) || is(typeof(& func.opCall!()) Fobj == delegate))
     {
         alias FunctionTypeOf = Fobj; // HIT: callable object
     }
     else static if (
-            (is(typeof(& func[0].opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
-            (is(typeof(& func[0].opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
+            (is(typeof(& func.opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
+            (is(typeof(& func.opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
         )
     {
         alias FunctionTypeOf = Ftyp; // HIT: callable type
     }
-    else static if (is(func[0] T) || is(typeof(func[0]) T))
+    else static if (is(func T) || is(typeof(func) T))
     {
         static if (is(T == function))
             alias FunctionTypeOf = T;    // HIT: function
@@ -2675,12 +2669,8 @@ template hasNested(T)
  */
 template Fields(T)
 {
-    static if (is(T == struct) || is(T == union))
-        alias Fields = typeof(T.tupleof[0 .. $ - isNested!T]);
-    else static if (is(T == class) || is(T == interface))
-        alias Fields = typeof(T.tupleof);
-    else
-        alias Fields = AliasSeq!T;
+    import core.internal.traits : _Fields = Fields;
+    alias Fields = _Fields!T;
 }
 
 ///
@@ -2847,6 +2837,8 @@ template RepresentationTypeTuple(T)
     struct S5 { int a; Rebindable!(immutable Object) b; }
     alias R2 = RepresentationTypeTuple!S5;
     static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object)));
+
+    static assert(is(RepresentationTypeTuple!noreturn == AliasSeq!noreturn));
 }
 
 @safe unittest
@@ -2869,7 +2861,7 @@ private template RepresentationTypeTupleImpl(T)
 {
     import std.typecons : Rebindable;
 
-    static if (is(T R: Rebindable!R))
+    static if (is(immutable T == immutable Rebindable!R, R))
     {
         alias RepresentationTypeTupleImpl
             = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R);
@@ -3292,13 +3284,15 @@ template hasAliasing(T...)
     class S15 { S15[1] a; }
     static assert( hasAliasing!S15);
     static assert(!hasAliasing!(immutable(S15)));
+
+    static assert(!hasAliasing!noreturn);
 }
 
 private template hasAliasingImpl(T)
 {
     import std.typecons : Rebindable;
 
-    static if (is(T : Rebindable!R, R))
+    static if (is(immutable T == immutable Rebindable!R, R))
     {
         enum hasAliasingImpl = hasAliasingImpl!R;
     }
@@ -3324,15 +3318,8 @@ $(LI a [context pointer][isNested].))
  */
 template hasIndirections(T)
 {
-    static if (is(T == struct) || is(T == union))
-        enum hasIndirections = anySatisfy!(.hasIndirections, typeof(T.tupleof));
-    else static if (isStaticArray!T && is(T : E[N], E, size_t N))
-        enum hasIndirections = is(E == void) ? true : hasIndirections!E;
-    else static if (isFunctionPointer!T)
-        enum hasIndirections = false;
-    else
-        enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T ||
-            isAssociativeArray!T || is (T == class) || is(T == interface);
+    import core.internal.traits : _hasIndirections = hasIndirections;
+    alias hasIndirections = _hasIndirections!T;
 }
 
 ///
@@ -3409,6 +3396,8 @@ template hasIndirections(T)
     int local;
     struct HasContextPointer { int opCall() { return ++local; } }
     static assert(hasIndirections!HasContextPointer);
+
+    static assert(!hasIndirections!noreturn);
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=12000
@@ -3575,13 +3564,15 @@ template hasUnsharedAliasing(T...)
     static assert( hasUnsharedAliasing!S18);
     static assert( hasUnsharedAliasing!S19);
     static assert(!hasUnsharedAliasing!S20);
+
+    static assert(!hasUnsharedAliasing!noreturn);
 }
 
 private template hasUnsharedAliasingImpl(T)
 {
     import std.typecons : Rebindable;
 
-    static if (is(T R: Rebindable!R))
+    static if (is(immutable T == immutable Rebindable!R, R))
     {
         enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R;
     }
@@ -3603,17 +3594,25 @@ private template hasUnsharedAliasingImpl(T)
     }
 }
 
-/**
- True if `S` or any type embedded directly in the representation of `S`
- defines an elaborate copy constructor. Elaborate copy constructors are
- introduced by defining `this(this)` for a `struct`.
+version (StdDdoc)
+{
+    /**
+       True if `S` or any type embedded directly in the representation of `S`
+       defines an elaborate copy constructor. Elaborate copy constructors are
+       introduced by defining `this(this)` for a `struct`.
 
- Classes and unions never have elaborate copy constructors.
- */
-template hasElaborateCopyConstructor(S)
+       Classes and unions never have elaborate copy constructors.
+    */
+    template hasElaborateCopyConstructor(S)
+    {
+        import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
+        alias hasElaborateCopyConstructor = hasElabCCtor!(S);
+    }
+}
+else
 {
     import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor;
-    alias hasElaborateCopyConstructor = hasElabCCtor!(S);
+    alias hasElaborateCopyConstructor = hasElabCCtor;
 }
 
 ///
@@ -3732,19 +3731,27 @@ template hasElaborateAssign(S)
     static assert( hasElaborateAssign!SS9);
 }
 
-/**
-   True if `S` or any type directly embedded in the representation
-   of `S` defines an elaborate destructor. Elaborate destructors
-   are introduced by defining `~this()` for a $(D
-   struct).
+version (StdDdoc)
+{
+    /**
+       True if `S` or any type directly embedded in the representation
+       of `S` defines an elaborate destructor. Elaborate destructors
+       are introduced by defining `~this()` for a $(D
+       struct).
 
-   Classes and unions never have elaborate destructors, even
-   though classes may define `~this()`.
- */
-template hasElaborateDestructor(S)
+       Classes and unions never have elaborate destructors, even
+       though classes may define `~this()`.
+    */
+    template hasElaborateDestructor(S)
+    {
+        import core.internal.traits : hasElabDest = hasElaborateDestructor;
+        alias hasElaborateDestructor = hasElabDest!(S);
+    }
+}
+else
 {
     import core.internal.traits : hasElabDest = hasElaborateDestructor;
-    alias hasElaborateDestructor = hasElabDest!(S);
+    alias hasElaborateDestructor = hasElabDest;
 }
 
 ///
@@ -3771,17 +3778,25 @@ template hasElaborateDestructor(S)
     static assert( hasElaborateDestructor!S7);
 }
 
-/**
- True if `S` or any type embedded directly in the representation of `S`
- defines elaborate move semantics. Elaborate move semantics are
- introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
+version (StdDdoc)
+{
+    /**
+       True if `S` or any type embedded directly in the representation of `S`
+       defines elaborate move semantics. Elaborate move semantics are
+       introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
 
- Classes and unions never have elaborate move semantics.
- */
-template hasElaborateMove(S)
+       Classes and unions never have elaborate move semantics.
+    */
+    template hasElaborateMove(S)
+    {
+        import core.internal.traits : hasElabMove = hasElaborateMove;
+        alias hasElaborateMove = hasElabMove!(S);
+    }
+}
+else
 {
     import core.internal.traits : hasElabMove = hasElaborateMove;
-    alias hasElaborateMove = hasElabMove!(S);
+    alias hasElaborateMove = hasElabMove;
 }
 
 ///
@@ -4116,50 +4131,9 @@ int[] abc = cast(int[]) [ EnumMembers!E ];
 template EnumMembers(E)
 if (is(E == enum))
 {
-    import std.meta : AliasSeq;
-    // Supply the specified identifier to an constant value.
-    template WithIdentifier(string ident)
-    {
-        static if (ident == "Symbolize")
-        {
-            template Symbolize(alias value)
-            {
-                enum Symbolize = value;
-            }
-        }
-        else
-        {
-            mixin("template Symbolize(alias "~ ident ~")"
-                 ~"{"
-                     ~"alias Symbolize = "~ ident ~";"
-                 ~"}");
-        }
-    }
-
-    template EnumSpecificMembers(names...)
-    {
-        static if (names.length == 1)
-        {
-            alias EnumSpecificMembers = AliasSeq!(WithIdentifier!(names[0])
-                        .Symbolize!(__traits(getMember, E, names[0])));
-        }
-        else static if (names.length > 0)
-        {
-            alias EnumSpecificMembers =
-                AliasSeq!(
-                    WithIdentifier!(names[0])
-                        .Symbolize!(__traits(getMember, E, names[0])),
-                    EnumSpecificMembers!(names[1 .. $/2]),
-                    EnumSpecificMembers!(names[$/2..$])
-                );
-        }
-        else
-        {
-            alias EnumSpecificMembers = AliasSeq!();
-        }
-    }
-
-    alias EnumMembers = EnumSpecificMembers!(__traits(allMembers, E));
+    alias EnumMembers = AliasSeq!();
+    static foreach (M; __traits(allMembers, E))
+        EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, M));
 }
 
 /// Create an array of enumerated values
@@ -4494,14 +4468,7 @@ template InterfacesTuple(T)
  * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the
  * empty type tuple.
  */
-template TransitiveBaseTypeTuple(T)
-{
-    static if (is(T == Object))
-        alias TransitiveBaseTypeTuple = AliasSeq!();
-    else
-        alias TransitiveBaseTypeTuple =
-            AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
-}
+alias TransitiveBaseTypeTuple(T) = AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T);
 
 ///
 @safe unittest
@@ -4748,22 +4715,13 @@ if (is(C == class) || is(C == interface))
 Returns an alias to the template that `T` is an instance of.
 It will return `void` if a symbol without a template is given.
  */
-template TemplateOf(alias T : Base!Args, alias Base, Args...)
-{
-    alias TemplateOf = Base;
-}
+alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
 
 /// ditto
-template TemplateOf(T : Base!Args, alias Base, Args...)
-{
-    alias TemplateOf = Base;
-}
+alias TemplateOf(T : Base!Args, alias Base, Args...) = Base;
 
 /// ditto
-template TemplateOf(T)
-{
-    alias TemplateOf = void;
-}
+alias TemplateOf(T) = void;
 
 ///
 @safe unittest
@@ -4805,16 +4763,10 @@ template TemplateOf(T)
 /**
 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
  */
-template TemplateArgsOf(alias T : Base!Args, alias Base, Args...)
-{
-    alias TemplateArgsOf = Args;
-}
+alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
 
 /// ditto
-template TemplateArgsOf(T : Base!Args, alias Base, Args...)
-{
-    alias TemplateArgsOf = Args;
-}
+alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
 
 ///
 @safe unittest
@@ -4850,24 +4802,15 @@ template TemplateArgsOf(T : Base!Args, alias Base, Args...)
     static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
 }
 
-
-package template maxAlignment(U...)
-if (isTypeTuple!U)
+// Returns the largest alignment in a type tuple.
+package enum maxAlignment(U...) =
 {
-    static if (U.length == 0)
-        static assert(0);
-    else static if (U.length == 1)
-        enum maxAlignment = U[0].alignof;
-    else static if (U.length == 2)
-        enum maxAlignment = U[0].alignof > U[1].alignof ? U[0].alignof : U[1].alignof;
-    else
-    {
-        enum a = maxAlignment!(U[0 .. ($+1)/2]);
-        enum b = maxAlignment!(U[($+1)/2 .. $]);
-        enum maxAlignment = a > b ? a : b;
-    }
-}
-
+    size_t result = U[0].alignof;
+    static foreach (T; U[1 .. $])
+        if (result < T.alignof)
+            result = T.alignof;
+    return result;
+}();
 
 /**
 Returns class instance alignment.
@@ -4902,25 +4845,10 @@ types have no common type.
  */
 template CommonType(T...)
 {
-    static if (!T.length)
-    {
-        alias CommonType = void;
-    }
-    else static if (T.length == 1)
-    {
-        static if (is(typeof(T[0])))
-        {
-            alias CommonType = typeof(T[0]);
-        }
-        else
-        {
-            alias CommonType = T[0];
-        }
-    }
+    static if (T.length == 1)
+        alias CommonType = typeof(T[0].init);
     else static if (is(typeof(true ? T[0].init : T[1].init) U))
-    {
         alias CommonType = CommonType!(U, T[2 .. $]);
-    }
     else
         alias CommonType = void;
 }
@@ -4966,36 +4894,29 @@ template AllImplicitConversionTargets(T)
 {
     static if (is(T == bool))
         alias AllImplicitConversionTargets =
-            AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
-                       float, double, real, char, wchar, dchar);
+            AliasSeq!(byte, AllImplicitConversionTargets!byte);
     else static if (is(T == byte))
         alias AllImplicitConversionTargets =
-            AliasSeq!(ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
-                       float, double, real, char, wchar, dchar);
+            AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
     else static if (is(T == ubyte))
         alias AllImplicitConversionTargets =
-            AliasSeq!(byte, short, ushort, int, uint, long, ulong, CentTypeList,
-                       float, double, real, char, wchar, dchar);
+            AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
     else static if (is(T == short))
         alias AllImplicitConversionTargets =
-            AliasSeq!(ushort, int, uint, long, ulong, CentTypeList, float, double, real);
+            AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
     else static if (is(T == ushort))
         alias AllImplicitConversionTargets =
-            AliasSeq!(short, int, uint, long, ulong, CentTypeList, float, double, real);
+            AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
     else static if (is(T == int))
         alias AllImplicitConversionTargets =
-            AliasSeq!(uint, long, ulong, CentTypeList, float, double, real);
+            AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
     else static if (is(T == uint))
         alias AllImplicitConversionTargets =
-            AliasSeq!(int, long, ulong, CentTypeList, float, double, real);
+            AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
     else static if (is(T == long))
-        alias AllImplicitConversionTargets = AliasSeq!(ulong, float, double, real);
+        alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
     else static if (is(T == ulong))
-        alias AllImplicitConversionTargets = AliasSeq!(long, float, double, real);
-    else static if (is(cent) && is(T == cent))
-        alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
-    else static if (is(ucent) && is(T == ucent))
-        alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
+        alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
     else static if (is(T == float))
         alias AllImplicitConversionTargets = AliasSeq!(double, real);
     else static if (is(T == double))
@@ -5004,21 +4925,17 @@ template AllImplicitConversionTargets(T)
         alias AllImplicitConversionTargets = AliasSeq!(float, double);
     else static if (is(T == char))
         alias AllImplicitConversionTargets =
-            AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
-                       int, uint, long, ulong, CentTypeList, float, double, real);
+            AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
     else static if (is(T == wchar))
         alias AllImplicitConversionTargets =
-            AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
-                       float, double, real);
+            AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
     else static if (is(T == dchar))
         alias AllImplicitConversionTargets =
-            AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
-    else static if (is(T : typeof(null)))
-        alias AllImplicitConversionTargets = AliasSeq!(typeof(null));
+            AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
     else static if (is(T == class))
-        alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
+        alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
     else static if (is(T == interface))
-        alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!(T));
+        alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
     else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
     {
        static if (is(typeof(T.init[0]) == shared))
@@ -5028,8 +4945,12 @@ template AllImplicitConversionTargets(T)
            alias AllImplicitConversionTargets =
            AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
     }
-    else static if (is(T : void*))
+    else static if (is(T : void*) && !is(T == void*))
         alias AllImplicitConversionTargets = AliasSeq!(void*);
+    else static if (is(cent) && is(T == cent))
+        alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
+    else static if (is(ucent) && is(T == ucent))
+        alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
     else
         alias AllImplicitConversionTargets = AliasSeq!();
 }
@@ -5040,22 +4961,23 @@ template AllImplicitConversionTargets(T)
     import std.meta : AliasSeq;
 
     static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
-    static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(uint, long, ulong, float, double, real)));
+    static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
     static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
     static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
 
-    static assert(is(AllImplicitConversionTargets!(char) == AliasSeq!(
-        wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
-    )));
+    static assert(is(AllImplicitConversionTargets!(char) ==
+        AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
+            ulong, float, double, real)
+    ));
     static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
-        dchar, short, ushort, int, uint, long, ulong, float, double, real
+        short, ushort, dchar, int, uint, long, ulong, float, double, real
     )));
     static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
         int, uint, long, ulong, float, double, real
     )));
 
     static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
-    static assert(is(AllImplicitConversionTargets!(void*) == AliasSeq!(void*)));
+    static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
 
     interface A {}
     interface B {}
@@ -5747,13 +5669,11 @@ Note: Trying to use returned value will result in a
 // SomethingTypeOf
 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
 
-private alias AliasThisTypeOf(T) = typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0]));
-
 /*
  */
 template BooleanTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = BooleanTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -5804,7 +5724,7 @@ template BooleanTypeOf(T)
  */
 template IntegralTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = IntegralTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -5840,7 +5760,7 @@ template IntegralTypeOf(T)
  */
 template FloatingPointTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = FloatingPointTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -5925,7 +5845,7 @@ template SignedTypeOf(T)
  */
 template CharTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = CharTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -5966,7 +5886,7 @@ template CharTypeOf(T)
  */
 template StaticArrayTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = StaticArrayTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -6001,17 +5921,8 @@ template StaticArrayTypeOf(T)
  */
 template DynamicArrayTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
-        alias X = DynamicArrayTypeOf!AT;
-    else
-        alias X = OriginalType!T;
-
-    static if (is(X == E[], E))
-    {
-        alias DynamicArrayTypeOf = X;
-    }
-    else
-        static assert(0, T.stringof~" is not a dynamic array");
+    import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
+    alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
 }
 
 @safe unittest
@@ -6132,7 +6043,7 @@ template StringTypeOf(T)
  */
 template AssocArrayTypeOf(T)
 {
-    static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+    static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
         alias X = AssocArrayTypeOf!AT;
     else
         alias X = OriginalType!T;
@@ -6173,7 +6084,7 @@ template BuiltinTypeOf(T)
         alias BuiltinTypeOf = void;
     else
     {
-        static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
+        static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
             alias X = BuiltinTypeOf!AT;
         else
             alias X = OriginalType!T;
@@ -6902,7 +6813,9 @@ template isAutodecodableString(T)
     import std.range.primitives : autodecodeStrings;
 
     enum isAutodecodableString = autodecodeStrings &&
-        (is(T : const char[]) || is(T : const wchar[])) && !is(T : U[n], U, size_t n);
+        (is(T : const char[]) || is(T : const wchar[]))
+        && !is(T : U[n], U, size_t n)
+        && !is(immutable T : immutable noreturn[]);
 }
 
 ///
@@ -6937,6 +6850,9 @@ template isAutodecodableString(T)
 
     static assert(isAutodecodableString!(H));
     static assert(isAutodecodableString!(I));
+
+    static assert(!isAutodecodableString!(noreturn[]));
+    static assert(!isAutodecodableString!(immutable(noreturn)[]));
 }
 
 /**
@@ -7381,15 +7297,14 @@ alias isExpressionTuple = isExpressions;
  *
  * See_Also: $(LREF isExpressions).
  */
-template isTypeTuple(T...)
+enum isTypeTuple(T...) =
 {
-    static if (T.length >= 2)
-        enum bool isTypeTuple = isTypeTuple!(T[0 .. $/2]) && isTypeTuple!(T[$/2 .. $]);
-    else static if (T.length == 1)
-        enum bool isTypeTuple = is(T[0]);
-    else
-        enum bool isTypeTuple = true; // default
-}
+    static foreach (U; T)
+        static if (!is(U))
+            if (__ctfe)
+                return false;
+    return true;
+}();
 
 ///
 @safe unittest
@@ -7473,15 +7388,14 @@ Params:
 Returns:
     A `bool`
  */
-template isSomeFunction(T...)
-if (T.length == 1)
+template isSomeFunction(alias T)
 {
-    static if (is(typeof(& T[0]) U : U*) && is(U == function) || is(typeof(& T[0]) U == delegate))
+    static if (is(typeof(& T) U : U*) && is(U == function) || is(typeof(& T) U == delegate))
     {
         // T is a (nested) function symbol.
         enum bool isSomeFunction = true;
     }
-    else static if (is(T[0] W) || is(typeof(T[0]) W))
+    else static if (is(T W) || is(typeof(T) W))
     {
         // T is an expression or a type.  Take the type of it and examine.
         static if (is(W F : F*) && is(F == function))
@@ -7623,11 +7537,7 @@ Params:
 Returns:
     A `bool`
  */
-template isAbstractFunction(T...)
-if (T.length == 1)
-{
-    enum bool isAbstractFunction = __traits(isAbstractFunction, T[0]);
-}
+enum isAbstractFunction(alias T) = __traits(isAbstractFunction, T);
 
 ///
 @safe unittest
@@ -7644,11 +7554,7 @@ if (T.length == 1)
 /**
  * Detect whether `T` is a final function.
  */
-template isFinalFunction(T...)
-if (T.length == 1)
-{
-    enum bool isFinalFunction = __traits(isFinalFunction, T[0]);
-}
+enum isFinalFunction(alias T) = __traits(isFinalFunction, T);
 
 ///
 @safe unittest
@@ -7716,11 +7622,7 @@ template isNestedFunction(alias f)
 /**
  * Detect whether `T` is an abstract class.
  */
-template isAbstractClass(T...)
-if (T.length == 1)
-{
-    enum bool isAbstractClass = __traits(isAbstractClass, T[0]);
-}
+enum isAbstractClass(alias T) = __traits(isAbstractClass, T);
 
 ///
 @safe unittest
@@ -7740,11 +7642,7 @@ if (T.length == 1)
 /**
  * Detect whether `T` is a final class.
  */
-template isFinalClass(T...)
-if (T.length == 1)
-{
-    enum bool isFinalClass = __traits(isFinalClass, T[0]);
-}
+enum isFinalClass(alias T) = __traits(isFinalClass, T);
 
 ///
 @safe unittest
@@ -7767,13 +7665,21 @@ if (T.length == 1)
 // General Types
 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
 
-/**
-Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
- */
-template Unconst(T)
+version (StdDdoc)
+{
+    /**
+       Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
+    */
+    template Unconst(T)
+    {
+        import core.internal.traits : CoreUnconst = Unconst;
+        alias Unconst = CoreUnconst!(T);
+    }
+}
+else
 {
     import core.internal.traits : CoreUnconst = Unconst;
-    alias Unconst = CoreUnconst!(T);
+    alias Unconst = CoreUnconst;
 }
 
 ///
@@ -7802,13 +7708,21 @@ template Unconst(T)
     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
 }
 
-/**
-Removes all qualifiers, if any, from type `T`.
- */
-template Unqual(T)
+version (StdDdoc)
+{
+    /**
+       Removes all qualifiers, if any, from type `T`.
+    */
+    template Unqual(T)
+    {
+        import core.internal.traits : CoreUnqual = Unqual;
+        alias Unqual = CoreUnqual!(T);
+    }
+}
+else
 {
     import core.internal.traits : CoreUnqual = Unqual;
-    alias Unqual = CoreUnqual!(T);
+    alias Unqual = CoreUnqual;
 }
 
 ///
@@ -7840,29 +7754,8 @@ template Unqual(T)
 // [For internal use]
 package template ModifyTypePreservingTQ(alias Modifier, T)
 {
-         static if (is(T U ==          immutable U)) alias ModifyTypePreservingTQ =          immutable Modifier!U;
-    else static if (is(T U == shared inout const U)) alias ModifyTypePreservingTQ = shared inout const Modifier!U;
-    else static if (is(T U == shared inout       U)) alias ModifyTypePreservingTQ = shared inout       Modifier!U;
-    else static if (is(T U == shared       const U)) alias ModifyTypePreservingTQ = shared       const Modifier!U;
-    else static if (is(T U == shared             U)) alias ModifyTypePreservingTQ = shared             Modifier!U;
-    else static if (is(T U ==        inout const U)) alias ModifyTypePreservingTQ =        inout const Modifier!U;
-    else static if (is(T U ==        inout       U)) alias ModifyTypePreservingTQ =              inout Modifier!U;
-    else static if (is(T U ==              const U)) alias ModifyTypePreservingTQ =              const Modifier!U;
-    else                                             alias ModifyTypePreservingTQ =                    Modifier!T;
-}
-
-@safe unittest
-{
-    alias Intify(T) = int;
-    static assert(is(ModifyTypePreservingTQ!(Intify,                    real) ==                    int));
-    static assert(is(ModifyTypePreservingTQ!(Intify,              const real) ==              const int));
-    static assert(is(ModifyTypePreservingTQ!(Intify,        inout       real) ==        inout       int));
-    static assert(is(ModifyTypePreservingTQ!(Intify,        inout const real) ==        inout const int));
-    static assert(is(ModifyTypePreservingTQ!(Intify, shared             real) == shared             int));
-    static assert(is(ModifyTypePreservingTQ!(Intify, shared       const real) == shared       const int));
-    static assert(is(ModifyTypePreservingTQ!(Intify, shared inout       real) == shared inout       int));
-    static assert(is(ModifyTypePreservingTQ!(Intify, shared inout const real) == shared inout const int));
-    static assert(is(ModifyTypePreservingTQ!(Intify,          immutable real) ==          immutable int));
+    import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
+    alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
 }
 
 /**
@@ -8009,20 +7902,8 @@ template ForeachType(T)
  */
 template OriginalType(T)
 {
-    static if (is(T == enum))
-    {
-        template Impl(T)
-        {
-            static if (is(T U == enum)) alias Impl = OriginalType!U;
-            else                        alias Impl =              T;
-        }
-
-        alias OriginalType = ModifyTypePreservingTQ!(Impl, T);
-    }
-    else
-    {
-        alias OriginalType = T;
-    }
+    import core.internal.traits : _OriginalType = OriginalType;
+    alias OriginalType = _OriginalType!T;
 }
 
 ///
@@ -8158,25 +8039,9 @@ returned.
 template Largest(T...)
 if (T.length >= 1)
 {
-    static if (T.length == 1)
-    {
-        alias Largest = T[0];
-    }
-    else static if (T.length == 2)
-    {
-        static if (T[0].sizeof >= T[1].sizeof)
-        {
-            alias Largest = T[0];
-        }
-        else
-        {
-            alias Largest = T[1];
-        }
-    }
-    else
-    {
-        alias Largest = Largest!(Largest!(T[0 .. $/2]), Largest!(T[$/2 .. $]));
-    }
+    alias Largest = T[0];
+    static foreach (U; T[1 .. $])
+        Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
 }
 
 ///
@@ -8332,11 +8197,7 @@ Returns the mangled name of symbol or type `sth`.
 might be more convenient in generic code, e.g. as a template argument
 when invoking staticMap.
  */
-template mangledName(sth...)
-if (sth.length == 1)
-{
-    enum string mangledName = sth[0].mangleof;
-}
+enum mangledName(alias sth) = sth.mangleof;
 
 ///
 @safe unittest
@@ -8451,10 +8312,7 @@ B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
     See_Also:
         $(LREF getUDAs)
   +/
-template hasUDA(alias symbol, alias attribute)
-{
-    enum hasUDA = getUDAs!(symbol, attribute).length != 0;
-}
+enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
 
 ///
 @safe unittest
@@ -8941,28 +8799,22 @@ private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
 }
 
 /**
-   Returns: `true` iff all types `T` are the same.
+   Returns: `true` iff all types `Ts` are the same.
 */
-template allSameType(T...)
+enum bool allSameType(Ts...) =
 {
-    static foreach (idx, Ti; T)
-    {
-        static if (idx + 1 < T.length &&
-                   !is(typeof(allSameType) == bool) &&
-                   !is(T[idx] == T[idx + 1]))
-        {
-            enum bool allSameType = false;
-        }
-    }
-    static if (!is(typeof(allSameType) == bool))
-    {
-        enum bool allSameType = true;
-    }
-}
+    static foreach (T; Ts[Ts.length > 1 .. $])
+        static if (!is(Ts[0] == T))
+            if (__ctfe)  // Dodge the "statement is unreachable" warning
+                return false;
+    return true;
+}();
 
 ///
 @safe unittest
 {
+    static assert(allSameType!());
+    static assert(allSameType!(int));
     static assert(allSameType!(int, int));
     static assert(allSameType!(int, int, int));
     static assert(allSameType!(float, float, float));
@@ -8993,11 +8845,7 @@ enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init))
  * Returns:
  *      `true` if `X` is a type, `false` otherwise
  */
-template isType(X...)
-if (X.length == 1)
-{
-    enum isType = is(X[0]);
-}
+enum isType(alias X) = is(X);
 
 ///
 @safe unittest
@@ -9037,16 +8885,15 @@ if (X.length == 1)
  *     Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
  *     respectively.
  */
-template isFunction(X...)
-if (X.length == 1)
+template isFunction(alias X)
 {
-    static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
-               is(typeof(&X[0]) U == delegate))
+    static if (is(typeof(&X) U : U*) && is(U == function) ||
+               is(typeof(&X) U == delegate))
     {
         // x is a (nested) function symbol.
         enum isFunction = true;
     }
-    else static if (is(X[0] T))
+    else static if (is(X T))
     {
         // x is a type.  Take the type of it and examine.
         enum isFunction = is(T == function);
@@ -9074,13 +8921,12 @@ if (X.length == 1)
  * Returns:
  *     `true` if `X` is final, `false` otherwise
  */
-template isFinal(X...)
-if (X.length == 1)
+template isFinal(alias X)
 {
-    static if (is(X[0] == class))
-        enum isFinal = __traits(isFinalClass, X[0]);
+    static if (is(X == class))
+        enum isFinal = __traits(isFinalClass, X);
     else static if (isFunction!X)
-        enum isFinal = __traits(isFinalFunction, X[0]);
+        enum isFinal = __traits(isFinalFunction, X);
     else
         enum isFinal = false;
 }
index feedf90e951d124015d0c3b684fc2c34f55fa56b..db0e3da304cca29cfacebdf150477ee1c860af54 100644 (file)
@@ -448,6 +448,90 @@ private enum bool distinctFieldNames(names...) = __traits(compiles,
     static assert(!distinctFieldNames!(int, "int"));
 }
 
+
+// Parse (type,name) pairs (FieldSpecs) out of the specified
+// arguments. Some fields would have name, others not.
+private template parseSpecs(Specs...)
+{
+    static if (Specs.length == 0)
+    {
+        alias parseSpecs = AliasSeq!();
+    }
+    else static if (is(Specs[0]))
+    {
+        static if (is(typeof(Specs[1]) : string))
+        {
+            alias parseSpecs =
+                AliasSeq!(FieldSpec!(Specs[0 .. 2]),
+                          parseSpecs!(Specs[2 .. $]));
+        }
+        else
+        {
+            alias parseSpecs =
+                AliasSeq!(FieldSpec!(Specs[0]),
+                          parseSpecs!(Specs[1 .. $]));
+        }
+    }
+    else
+    {
+        static assert(0, "Attempted to instantiate Tuple with an "
+                        ~"invalid argument: "~ Specs[0].stringof);
+    }
+}
+
+private template FieldSpec(T, string s = "")
+{
+    alias Type = T;
+    alias name = s;
+}
+
+// Used with staticMap.
+private alias extractType(alias spec) = spec.Type;
+private alias extractName(alias spec) = spec.name;
+private template expandSpec(alias spec)
+{
+    static if (spec.name.length == 0)
+        alias expandSpec = AliasSeq!(spec.Type);
+    else
+        alias expandSpec = AliasSeq!(spec.Type, spec.name);
+}
+
+
+private enum areCompatibleTuples(Tup1, Tup2, string op) =
+    isTuple!(OriginalType!Tup2) && Tup1.Types.length == Tup2.Types.length && is(typeof(
+    (ref Tup1 tup1, ref Tup2 tup2)
+    {
+        static foreach (i; 0 .. Tup1.Types.length)
+        {{
+            auto lhs = typeof(tup1.field[i]).init;
+            auto rhs = typeof(tup2.field[i]).init;
+            static if (op == "=")
+                lhs = rhs;
+            else
+                auto result = mixin("lhs "~op~" rhs");
+        }}
+    }));
+
+private enum areBuildCompatibleTuples(Tup1, Tup2) =
+    isTuple!Tup2 && Tup1.Types.length == Tup2.Types.length && is(typeof(
+    {
+        static foreach (i; 0 .. Tup1.Types.length)
+            static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
+    }));
+
+// Returns `true` iff a `T` can be initialized from a `U`.
+private enum isBuildable(T, U) = is(typeof(
+    {
+        U u = U.init;
+        T t = u;
+    }));
+// Helper for partial instantiation
+private template isBuildableFrom(U)
+{
+    enum isBuildableFrom(T) = isBuildable!(T, U);
+}
+
+
 /**
 _Tuple of values, for example $(D Tuple!(int, string)) is a record that
 stores an `int` and a `string`. `Tuple` can be used to bundle
@@ -466,48 +550,8 @@ if (distinctFieldNames!(Specs))
 {
     import std.meta : staticMap;
 
-    // Parse (type,name) pairs (FieldSpecs) out of the specified
-    // arguments. Some fields would have name, others not.
-    template parseSpecs(Specs...)
-    {
-        static if (Specs.length == 0)
-        {
-            alias parseSpecs = AliasSeq!();
-        }
-        else static if (is(Specs[0]))
-        {
-            static if (is(typeof(Specs[1]) : string))
-            {
-                alias parseSpecs =
-                    AliasSeq!(FieldSpec!(Specs[0 .. 2]),
-                              parseSpecs!(Specs[2 .. $]));
-            }
-            else
-            {
-                alias parseSpecs =
-                    AliasSeq!(FieldSpec!(Specs[0]),
-                              parseSpecs!(Specs[1 .. $]));
-            }
-        }
-        else
-        {
-            static assert(0, "Attempted to instantiate Tuple with an "
-                            ~"invalid argument: "~ Specs[0].stringof);
-        }
-    }
-
-    template FieldSpec(T, string s = "")
-    {
-        alias Type = T;
-        alias name = s;
-    }
-
     alias fieldSpecs = parseSpecs!Specs;
 
-    // Used with staticMap.
-    alias extractType(alias spec) = spec.Type;
-    alias extractName(alias spec) = spec.name;
-
     // Generates named fields as follows:
     //    alias name_0 = Identity!(field[0]);
     //    alias name_1 = Identity!(field[1]);
@@ -534,52 +578,6 @@ if (distinctFieldNames!(Specs))
     alias sliceSpecs(size_t from, size_t to) =
         staticMap!(expandSpec, fieldSpecs[from .. to]);
 
-    template expandSpec(alias spec)
-    {
-        static if (spec.name.length == 0)
-        {
-            alias expandSpec = AliasSeq!(spec.Type);
-        }
-        else
-        {
-            alias expandSpec = AliasSeq!(spec.Type, spec.name);
-        }
-    }
-
-    enum areCompatibleTuples(Tup1, Tup2, string op) = isTuple!(OriginalType!Tup2) && is(typeof(
-    (ref Tup1 tup1, ref Tup2 tup2)
-    {
-        static assert(tup1.field.length == tup2.field.length);
-        static foreach (i; 0 .. Tup1.Types.length)
-        {{
-            auto lhs = typeof(tup1.field[i]).init;
-            auto rhs = typeof(tup2.field[i]).init;
-            static if (op == "=")
-                lhs = rhs;
-            else
-                auto result = mixin("lhs "~op~" rhs");
-        }}
-    }));
-
-    enum areBuildCompatibleTuples(Tup1, Tup2) = isTuple!Tup2 && is(typeof(
-    {
-        static assert(Tup1.Types.length == Tup2.Types.length);
-        static foreach (i; 0 .. Tup1.Types.length)
-            static assert(isBuildable!(Tup1.Types[i], Tup2.Types[i]));
-    }));
-
-    /+ Returns `true` iff a `T` can be initialized from a `U`. +/
-    enum isBuildable(T, U) =  is(typeof(
-    {
-        U u = U.init;
-        T t = u;
-    }));
-    /+ Helper for partial instantiation +/
-    template isBuildableFrom(U)
-    {
-        enum isBuildableFrom(T) = isBuildable!(T, U);
-    }
-
     struct Tuple
     {
         /**
@@ -1359,8 +1357,7 @@ if (distinctFieldNames!(Specs))
         }
 
         ///
-        static if (Types.length == 0)
-        @safe unittest
+        static if (Specs.length == 0) @safe unittest
         {
             import std.format : format;
 
@@ -1381,8 +1378,7 @@ if (distinctFieldNames!(Specs))
         }
 
         ///
-        static if (Types.length == 0)
-        @safe unittest
+        static if (Specs.length == 0) @safe unittest
         {
             import std.exception : assertThrown;
             import std.format : format, FormatException;
@@ -2762,7 +2758,11 @@ struct Nullable(T)
 {
     private union DontCallDestructorT
     {
-        T payload;
+        import std.traits : hasIndirections;
+        static if (hasIndirections!T)
+            T payload;
+        else
+            T payload = void;
     }
 
     private DontCallDestructorT _value = DontCallDestructorT.init;
@@ -3020,7 +3020,7 @@ struct Nullable(T)
 
         if (_isNull)
         {
-            // trusted since payload is known to be T.init here.
+            // trusted since payload is known to be uninitialized.
             () @trusted { moveEmplace(copy.payload, _value.payload); }();
         }
         else
@@ -6850,9 +6850,10 @@ RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
 {
     static struct File
     {
+        static size_t nDestroyed;
         string name;
         @disable this(this); // not copyable
-        ~this() { name = null; }
+        ~this() { name = null; ++nDestroyed; }
     }
 
     auto file = File("name");
@@ -6860,14 +6861,37 @@ RefCounted!(T, RefCountedAutoInitialize.no) refCounted(T)(T val)
     // file cannot be copied and has unique ownership
     static assert(!__traits(compiles, {auto file2 = file;}));
 
+    assert(File.nDestroyed == 0);
+
     // make the file refcounted to share ownership
-    import std.algorithm.mutation : move;
-    auto rcFile = refCounted(move(file));
-    assert(rcFile.name == "name");
-    assert(file.name == null);
-    auto rcFile2 = rcFile;
-    assert(rcFile.refCountedStore.refCount == 2);
-    // file gets properly closed when last reference is dropped
+    // Note:
+    //   We write a compound statement (brace-delimited scope) in which all `RefCounted!File` handles are created and deleted.
+    //   This allows us to see (after the scope) what happens after all handles have been destroyed.
+    {
+        // We move the content of `file` to a separate (and heap-allocated) `File` object,
+        // managed-and-accessed via one-or-multiple (initially: one) `RefCounted!File` objects ("handles").
+        // This "moving":
+        //   (1) invokes `file`'s destructor (=> `File.nDestroyed` is incremented from 0 to 1 and `file.name` becomes `null`);
+        //   (2) overwrites `file` with `File.init` (=> `file.name` becomes `null`).
+        // It appears that writing `name = null;` in the destructor is redundant,
+        // but please note that (2) is only performed if `File` defines a destructor (or post-blit operator),
+        // and in the absence of the `nDestroyed` instrumentation there would have been no reason to define a destructor.
+        import std.algorithm.mutation : move;
+        auto rcFile = refCounted(move(file));
+        assert(rcFile.name == "name");
+        assert(File.nDestroyed == 1);
+        assert(file.name == null);
+
+        // We create another `RefCounted!File` handle to the same separate `File` object.
+        // While any of the handles is still alive, the `File` object is kept alive (=> `File.nDestroyed` is not modified).
+        auto rcFile2 = rcFile;
+        assert(rcFile.refCountedStore.refCount == 2);
+        assert(File.nDestroyed == 1);
+    }
+    // The separate `File` object is deleted when the last `RefCounted!File` handle is destroyed
+    // (i.e. at the closing brace of the compound statement above, which destroys both handles: `rcFile` and `rcFile2`)
+    // (=> `File.nDestroyed` is incremented again, from 1 to 2):
+    assert(File.nDestroyed == 2);
 }
 
 /**
@@ -9086,9 +9110,14 @@ template ReplaceTypeUnless(alias pred, From, To, T...)
         {
             template replaceTemplateArgs(T...)
             {
-                static if (is(typeof(T[0])))    // template argument is value or symbol
-                    enum replaceTemplateArgs = T[0];
-                else
+                static if (is(typeof(T[0]))) {   // template argument is value or symbol
+                    static if (__traits(compiles, { alias _ = T[0]; }))
+                        // it's a symbol
+                        alias replaceTemplateArgs = T[0];
+                    else
+                        // it's a value
+                        enum replaceTemplateArgs = T[0];
+                } else
                     alias replaceTemplateArgs = ReplaceTypeUnless!(pred, From, To, T[0]);
             }
             alias ReplaceTypeUnless = U!(staticMap!(replaceTemplateArgs, V));
@@ -9341,6 +9370,14 @@ private template replaceTypeInFunctionTypeUnless(alias pred, From, To, fun)
     static assert(is(ReplaceType!(int, string, C) == C));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=22325
+@safe unittest
+{
+    static struct Foo(alias f) {}
+    static void bar() {}
+    alias _ = ReplaceType!(int, int, Foo!bar);
+}
+
 /**
 Ternary type with three truth values:
 
index 318bcb32a6fbd7432064c9b2d867083055d41fee..45b7207c1f13ff6fc3c13d0e8a44bb8f9e94b131 100644 (file)
@@ -1528,7 +1528,7 @@ if (is(Unqual!T == T))
     return SliceOverIndexed!T(a, b, x);
 }
 
-@system unittest
+@safe unittest
 {
     int[] idxArray = [2, 3, 5, 8, 13];
     auto sliced = sliceOverIndexed(0, idxArray.length, &idxArray);
@@ -3116,7 +3116,7 @@ private:
     CowArray!SP data;
 }
 
-pure @system unittest
+pure @safe unittest
 {
     import std.conv : to;
     assert(unicode.ASCII.to!string() == "[0..128)");
@@ -5410,7 +5410,7 @@ pure @safe unittest
 }
 
 // cover decode fail cases of Matcher
-pure @system unittest
+pure @safe unittest
 {
     import std.algorithm.iteration : map;
     import std.exception : collectException;
@@ -5427,7 +5427,7 @@ pure @system unittest
             auto s = msg;
             size_t idx = 0;
             utf8.test(s);
-        }()), format("%( %2x %)", cast(ubyte[]) msg));
+        }()), format("%( %2x %)", cast(immutable(ubyte)[]) msg));
     }
     //decode failure cases UTF-16
     alias fails16 = AliasSeq!([0xD811], [0xDC02]);
@@ -7150,7 +7150,7 @@ if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
     return genericDecodeGrapheme!true(inp);
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
 
@@ -7233,7 +7233,7 @@ if (isInputRange!Range && is(immutable ElementType!Range == immutable dchar))
 
 // For testing non-forward-range input ranges
 version (StdUnittest)
-private static struct InputRangeString
+private static @safe struct InputRangeString
 {
     private string s;
 
@@ -7242,7 +7242,7 @@ private static struct InputRangeString
     void popFront() { s.popFront(); }
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.array : array;
@@ -7366,7 +7366,7 @@ if (isInputRange!Range && is(immutable ElementType!Range == immutable dchar))
     assert(reverse == "le\u0308on"); // lëon
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.range.primitives : walkLength;
@@ -7523,7 +7523,7 @@ public:
     }
 
     ///
-    @system unittest
+    @safe unittest
     {
         import std.algorithm.comparison : equal;
         auto g = Grapheme("A");
@@ -7650,7 +7650,7 @@ private:
 static assert(Grapheme.sizeof == size_t.sizeof*4);
 
 
-@system pure /*nothrow @nogc*/ unittest // TODO: string .front is GC and throw
+@safe pure /*nothrow @nogc*/ unittest // TODO: string .front is GC and throw
 {
     import std.algorithm.comparison : equal;
     Grapheme[3] data = [Grapheme("Ю"), Grapheme("У"), Grapheme("З")];
@@ -7658,7 +7658,7 @@ static assert(Grapheme.sizeof == size_t.sizeof*4);
 }
 
 ///
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.algorithm.iteration : filter;
@@ -7704,7 +7704,7 @@ static assert(Grapheme.sizeof == size_t.sizeof*4);
     assert(!g.valid);
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.algorithm.iteration : map;
@@ -8205,7 +8205,7 @@ package(std) auto simpleCaseFoldings(dchar ch) @safe
     return Range(start, entry.size);
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.algorithm.searching : canFind;
@@ -8356,7 +8356,7 @@ public Grapheme decompose(UnicodeDecomposition decompType=Canonical)(dchar ch) @
 }
 
 ///
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
 
@@ -8464,7 +8464,7 @@ Grapheme decomposeHangul(dchar ch) @safe
 }
 
 ///
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     assert(decomposeHangul('\uD4DB')[].equal("\u1111\u1171\u11B6"));
@@ -8504,7 +8504,7 @@ dchar composeJamo(dchar lead, dchar vowel, dchar trailing=dchar.init) pure nothr
     assert(composeJamo('A', '\u1171') == dchar.init);
 }
 
-@system unittest
+@safe unittest
 {
     import std.algorithm.comparison : equal;
     import std.conv : text;
@@ -10105,7 +10105,7 @@ if (isSomeString!S || (isRandomAccessRange!S && hasLength!S && hasSlicing!S && i
     assert(s2 !is s1);
 }
 
-@system unittest
+@safe unittest
 {
     static void doTest(C)(const(C)[] s, const(C)[] trueUp, const(C)[] trueLow)
     {
@@ -10118,9 +10118,9 @@ if (isSomeString!S || (isRandomAccessRange!S && hasLength!S && hasSlicing!S && i
         assert(low == trueLow, format(diff, low, trueLow));
         assert(up == trueUp,  format(diff, up, trueUp));
         assert(lowInp == trueLow,
-            format(diff, cast(ubyte[]) s, cast(ubyte[]) lowInp, cast(ubyte[]) trueLow));
+            format(diff, cast(const(ubyte)[]) s, cast(const(ubyte)[]) lowInp, cast(const(ubyte)[]) trueLow));
         assert(upInp == trueUp,
-            format(diff, cast(ubyte[]) s, cast(ubyte[]) upInp, cast(ubyte[]) trueUp));
+            format(diff, cast(const(ubyte)[]) s, cast(const(ubyte)[]) upInp, cast(const(ubyte)[]) trueUp));
     }
     static foreach (S; AliasSeq!(dstring, wstring, string))
     {{
index 953d6eafaee3c887aeb8b6913d061499ce912dcd..ce635fb9b342cc407af19c59cdadd4569d0ac7ad 100644 (file)
@@ -78,7 +78,7 @@ import std.meta, std.traits, std.typecons;
 /++
     Gives the `sizeof` the largest type given.
 
-    See_Also: https://forum.dlang.org/thread/wbpnncxepehgcswhuazl@forum.dlang.org?page=1
+    See_Also: $(LINK https://forum.dlang.org/thread/wbpnncxepehgcswhuazl@forum.dlang.org?page=1)
   +/
 template maxSize(Ts...)
 {
index cdf37c11cf6e6c33961a55bab2fa22018d282b8b..d66adff58ca774e529dd27598b478a24f5802c8b 100644 (file)
@@ -881,7 +881,6 @@ public:
         return new ValueNameSequence(this);
     }
 
-public:
     /**
         Returns the named sub-key of this key.
 
@@ -1412,7 +1411,6 @@ public:
         return getKeyName(index);
     }
 
-public:
     ///
     int opApply(scope int delegate(ref string name) dg)
     {
@@ -1509,7 +1507,6 @@ public:
         return getKey(index);
     }
 
-public:
     ///
     int opApply(scope int delegate(ref Key key) dg)
     {
@@ -1618,7 +1615,6 @@ public:
         return getValueName(index);
     }
 
-public:
     ///
     int opApply(scope int delegate(ref string name) dg)
     {
@@ -1712,7 +1708,6 @@ public:
         return getValue(index);
     }
 
-public:
     ///
     int opApply(scope int delegate(ref Value value) dg)
     {
diff --git a/libphobos/testsuite/libphobos.betterc/test22336.d b/libphobos/testsuite/libphobos.betterc/test22336.d
new file mode 100644 (file)
index 0000000..de0e31d
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************/
+// https://issues.dlang.org/show_bug.cgi?id=22336
+
+import core.lifetime;
+
+struct Foo {
+    int f = -1;
+    @disable this(this);
+    this(int x) { f = x; }
+    @disable this();
+}
+
+extern(C) int main() {
+    Foo a = Foo(42);
+    Foo b = move(a);
+    assert(a.f == -1);
+    assert(b.f == 42);
+    return 0;
+}
index 79b3cb8139efdef0371f203b2529f369b633bcbd..352ccca3901d28155b77e39b5fdcfd5097980640 100644 (file)
@@ -426,6 +426,18 @@ void testShared()
     import core.atomic : atomicLoad;
     static assert( __traits(compiles, atomicLoad(s1)));
     static assert(!__traits(compiles, atomicLoad(b1)));
+
+    static struct Fail
+    {
+        int value;
+
+        @safe pure nothrow @nogc:
+        bool opCast () shared const scope { return true; }
+    }
+
+    shared Fail fail = { value: 1 };
+    assert(_d_assert_fail!(shared Fail)("==", fail) == "Fail(1) != true");
+    assert(_d_assert_fail!(shared Fail)("==", fail, fail) == "Fail(1) != Fail(1)");
 }
 
 void testException()