aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2021-04-02 13:29:22 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2021-04-04 01:26:20 +0200
commit5a0aa603b2452dca48ad86d97d4b918187d259fc (patch)
tree67439099b8129248a45826b5791912b20ff3c3fb
parentba0f6902666430e5d065a92b3d5292cba91813d3 (diff)
downloadgcc-5a0aa603b2452dca48ad86d97d4b918187d259fc.zip
gcc-5a0aa603b2452dca48ad86d97d4b918187d259fc.tar.gz
gcc-5a0aa603b2452dca48ad86d97d4b918187d259fc.tar.bz2
d: Merge upstream dmd 3b808e838, druntime 483bc129, phobos f89dc217a
D front-end changes: - Explicit package visibility attribute is now always applied to introducing scopes. - Added `__traits(totype, string)' to convert mangled type string to an existing type. - Printf-like and scanf-like functions are now detected by prefixing them with `pragma(printf)' for printf-like functions or `pragma(scanf)' for scanf-like functions. - Added `__c_wchar_t', `__c_complex_float', `__c_complex_double', and `__c_complex_real' types for interfacing with C and C++. - Template alias parameters can now be instantiated with basic types, such as `int` or `void function()`. - Mixins can now be used as types in the form `mixin(string) var'. - Mixin expressions can take an argument list, same as `pragma(msg)'. - Implement DIP1034, add `typeof(*null)' types to represent `noreturn'. - `pragma(msg)' can print expressions of type `void'. - It is now an error to use private variables selectively imported from other modules. Due to a bug, some imported private members were visible from other modules, violating the specification. - Added new syntax to declare an alias to a function type using the `alias' syntax based on the assignment operator. - Function literals can now return a value by reference. Phobos changes: - Synchronize C bindings with the latest port fixes in upstream druntime. - Added alias for a `noreturn' type in object.d - Make use of the new `pragma(printf)' and `pragma(scanf)' pragmas, fix all code that got flagged as being incorrect. - Fixed code that relied on bugs in the D import package system. Reviewed-on: https://github.com/dlang/dmd/pull/12339 https://github.com/dlang/druntime/pull/3422 https://github.com/dlang/phobos/pull/7932 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 3b808e838. * Make-lang.in (D_FRONTEND_OBJS): Add d/chkformat.o. * d-codegen.cc (build_struct_literal): Handle special enums. * d-convert.cc (convert_expr): Handle noreturn type. (convert_for_condition): Likewise. * d-target.cc (Target::_init): Set type for wchar_t. (TargetCPP::derivedClassOffset): New method. (Target::libraryObjectMonitors): New method. * decl.cc (get_symbol_decl): Set TREE_THIS_VOLATILE for functions of type noreturn. * toir.cc (IRVisitor::visit (ReturnStatement *)): Handle returning noreturn types. * types.cc (TypeVisitor::visit (TypeNoreturn *)): New method. (TypeVisitor::visit (TypeEnum *)): Handle special enums. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 483bc129. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add core/sys/darwin/fcntl.d. (DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/unistd.d. (DRUNTIME_DSOURCES_WINDOWS): Add core/sys/windows/stdc/malloc.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos f89dc217a. * src/Makefile.am (PHOBOS_DSOURCES): Add std/regex/internal/tests2.d. * src/Makefile.in: Regenerate. * testsuite/libphobos.exceptions/chain.d: Fix format arguments. * testsuite/libphobos.exceptions/line_trace.d: Likewise.
-rw-r--r--gcc/d/Make-lang.in1
-rw-r--r--gcc/d/d-codegen.cc8
-rw-r--r--gcc/d/d-convert.cc14
-rw-r--r--gcc/d/d-target.cc28
-rw-r--r--gcc/d/decl.cc4
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/attrib.c39
-rw-r--r--gcc/d/dmd/attrib.h4
-rw-r--r--gcc/d/dmd/blockexit.c2
-rw-r--r--gcc/d/dmd/chkformat.c975
-rw-r--r--gcc/d/dmd/cppmangle.c18
-rw-r--r--gcc/d/dmd/ctfeexpr.c2
-rw-r--r--gcc/d/dmd/dcast.c5
-rw-r--r--gcc/d/dmd/dclass.c20
-rw-r--r--gcc/d/dmd/declaration.h4
-rw-r--r--gcc/d/dmd/denum.c19
-rw-r--r--gcc/d/dmd/dimport.c80
-rw-r--r--gcc/d/dmd/dmangle.c37
-rw-r--r--gcc/d/dmd/dmodule.c33
-rw-r--r--gcc/d/dmd/dscope.c6
-rw-r--r--gcc/d/dmd/dsymbol.c32
-rw-r--r--gcc/d/dmd/dsymbol.h3
-rw-r--r--gcc/d/dmd/dsymbolsem.c139
-rw-r--r--gcc/d/dmd/dtemplate.c210
-rw-r--r--gcc/d/dmd/expression.c1884
-rw-r--r--gcc/d/dmd/expression.h9
-rw-r--r--gcc/d/dmd/expressionsem.c2055
-rw-r--r--gcc/d/dmd/func.c18
-rw-r--r--gcc/d/dmd/hdrgen.c57
-rw-r--r--gcc/d/dmd/hdrgen.h1
-rw-r--r--gcc/d/dmd/idgen.c8
-rw-r--r--gcc/d/dmd/import.h1
-rw-r--r--gcc/d/dmd/module.h1
-rw-r--r--gcc/d/dmd/mtype.c282
-rw-r--r--gcc/d/dmd/mtype.h38
-rw-r--r--gcc/d/dmd/parse.c217
-rw-r--r--gcc/d/dmd/parse.h1
-rw-r--r--gcc/d/dmd/scope.h4
-rw-r--r--gcc/d/dmd/semantic2.c20
-rw-r--r--gcc/d/dmd/semantic3.c34
-rw-r--r--gcc/d/dmd/statement.c36
-rw-r--r--gcc/d/dmd/statement.h3
-rw-r--r--gcc/d/dmd/statementsem.c2
-rw-r--r--gcc/d/dmd/target.h4
-rw-r--r--gcc/d/dmd/template.h1
-rw-r--r--gcc/d/dmd/templateparamsem.c2
-rw-r--r--gcc/d/dmd/traits.c103
-rw-r--r--gcc/d/dmd/typesem.c77
-rw-r--r--gcc/d/dmd/visitor.h4
-rw-r--r--gcc/d/toir.cc7
-rw-r--r--gcc/d/types.cc47
-rw-r--r--gcc/testsuite/gdc.test/compilable/bug20796.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/cppmangle.d18
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddocunittest.d1
-rw-r--r--gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d8
-rw-r--r--gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d12
-rw-r--r--gcc/testsuite/gdc.test/compilable/fix21585.d24
-rw-r--r--gcc/testsuite/gdc.test/compilable/fix21647.d30
-rw-r--r--gcc/testsuite/gdc.test/compilable/ice10598.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/issue21614a.d22
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test20530a.d0
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test21501b.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test21501c.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue16020.d39
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue21614.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue21726.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/mixintype.d55
-rw-r--r--gcc/testsuite/gdc.test/compilable/mixintype2.d68
-rw-r--r--gcc/testsuite/gdc.test/compilable/noreturn1.d21
-rw-r--r--gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d5
-rw-r--r--gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d1
-rw-r--r--gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test16002.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test17991.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19292.d15
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20151a.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20280.d8
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20530.d46
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20537.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20692.d18
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21501a.d19
-rw-r--r--gcc/testsuite/gdc.test/compilable/test9029.d39
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug15613.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug16165.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug9631.d100
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/chkformat.d139
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/cppmangle.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag11819b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag13082.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag16271.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag8101.d47
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag8101b.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag9420.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail11038.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail11445.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail15361.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail15896.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail17630.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18219.d20
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19107.d21
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail263.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail3.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail322.d7
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail332.d45
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail347.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail53.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail55.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail79.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail99.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fix21585.d19
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/format.d44
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10598.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10922.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice12497.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice12501.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice14907.d22
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice14923.d5
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice8255.d5
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice9540.d5
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/ice10598a.d (renamed from gcc/testsuite/gdc.test/compilable/imports/ice10598a.d)0
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/ice10598b.d (renamed from gcc/testsuite/gdc.test/compilable/imports/ice10598b.d)0
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/issue16020.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/mixintype2.d16
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test16002.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21651.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/warn12809.d41
-rw-r--r--gcc/testsuite/gdc.test/runnable/funclit.d61
-rw-r--r--gcc/testsuite/gdc.test/runnable/mangle.d6
-rw-r--r--gcc/testsuite/gdc.test/runnable/noreturn1.d74
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/cppa.d29
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp4
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp82
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/test21515.d104
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/Makefile.am58
-rw-r--r--libphobos/libdruntime/Makefile.in105
-rw-r--r--libphobos/libdruntime/core/stdc/complex.d70
-rw-r--r--libphobos/libdruntime/core/stdc/config.d43
-rw-r--r--libphobos/libdruntime/core/stdc/errno.d16
-rw-r--r--libphobos/libdruntime/core/stdc/math.d400
-rw-r--r--libphobos/libdruntime/core/stdc/stdio.d61
-rw-r--r--libphobos/libdruntime/core/stdc/stdlib.d6
-rw-r--r--libphobos/libdruntime/core/stdc/tgmath.d653
-rw-r--r--libphobos/libdruntime/core/stdc/wchar_.d9
-rw-r--r--libphobos/libdruntime/core/sys/darwin/fcntl.d20
-rw-r--r--libphobos/libdruntime/core/sys/linux/epoll.d88
-rw-r--r--libphobos/libdruntime/core/sys/openbsd/string.d2
-rw-r--r--libphobos/libdruntime/core/sys/openbsd/unistd.d17
-rw-r--r--libphobos/libdruntime/core/sys/posix/config.d1
-rw-r--r--libphobos/libdruntime/core/sys/posix/dlfcn.d11
-rw-r--r--libphobos/libdruntime/core/sys/posix/signal.d14
-rw-r--r--libphobos/libdruntime/core/sys/posix/unistd.d48
-rw-r--r--libphobos/libdruntime/core/sys/windows/com.d20
-rw-r--r--libphobos/libdruntime/core/sys/windows/dll.d12
-rw-r--r--libphobos/libdruntime/core/sys/windows/stdc/malloc.d26
-rw-r--r--libphobos/libdruntime/gc/impl/conservative/gc.d4
-rw-r--r--libphobos/libdruntime/object.d7
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/Makefile.am12
-rw-r--r--libphobos/src/Makefile.in14
-rw-r--r--libphobos/src/std/algorithm/iteration.d8
-rw-r--r--libphobos/src/std/algorithm/searching.d4
-rw-r--r--libphobos/src/std/container/rbtree.d4
-rw-r--r--libphobos/src/std/conv.d2
-rw-r--r--libphobos/src/std/datetime/systime.d4
-rw-r--r--libphobos/src/std/experimental/logger/nulllogger.d2
-rw-r--r--libphobos/src/std/experimental/typecons.d6
-rw-r--r--libphobos/src/std/file.d5
-rw-r--r--libphobos/src/std/format.d4
-rw-r--r--libphobos/src/std/internal/math/biguintcore.d4
-rw-r--r--libphobos/src/std/math.d4
-rw-r--r--libphobos/src/std/parallelism.d4
-rw-r--r--libphobos/src/std/range/package.d1
-rw-r--r--libphobos/src/std/regex/internal/tests.d653
-rw-r--r--libphobos/src/std/regex/internal/tests2.d662
-rw-r--r--libphobos/src/std/socket.d2
-rw-r--r--libphobos/src/std/typecons.d10
-rw-r--r--libphobos/src/std/zip.d6
-rw-r--r--libphobos/testsuite/libphobos.exceptions/chain.d4
-rw-r--r--libphobos/testsuite/libphobos.exceptions/line_trace.d2
191 files changed, 7472 insertions, 3915 deletions
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 75857d8..b3c77a0 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -64,6 +64,7 @@ D_FRONTEND_OBJS = \
d/blockexit.o \
d/canthrow.o \
d/checkedint.o \
+ d/chkformat.o \
d/clone.o \
d/cond.o \
d/constfold.o \
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 5e6f240..608abcd 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1153,6 +1153,14 @@ build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
if (vec_safe_is_empty (init))
return build_constructor (type, NULL);
+ /* Struct literals can be seen for special enums representing `_Complex',
+ make sure to reinterpret the literal as the correct type. */
+ if (COMPLEX_FLOAT_TYPE_P (type))
+ {
+ gcc_assert (vec_safe_length (init) == 2);
+ return build_complex (type, (*init)[0].value, (*init)[1].value);
+ }
+
vec <constructor_elt, va_gc> *ve = NULL;
HOST_WIDE_INT offset = 0;
bool constant_p = true;
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index f407a46..3073eda 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -559,7 +559,9 @@ convert_expr (tree exp, Type *etype, Type *totype)
break;
case Tnull:
- /* Casting from typeof(null) is represented as all zeros. */
+ case Tnoreturn:
+ /* Casting from `typeof(null)' for `null' expressions, or `typeof(*null)'
+ for `noreturn' expressions is represented as all zeros. */
result = build_typeof_null_value (totype);
/* Make sure the expression is still evaluated if necessary. */
@@ -742,6 +744,16 @@ convert_for_condition (tree expr, Type *type)
break;
}
+ case Tnoreturn:
+ /* Front-end allows conditionals that never return, represent the
+ conditional result value as all zeros. */
+ result = build_zero_cst (d_bool_type);
+
+ /* Make sure the expression is still evaluated if necessary. */
+ if (TREE_SIDE_EFFECTS (expr))
+ result = compound_expr (expr, result);
+ break;
+
default:
result = expr;
break;
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d50fcef..a1dc2ee 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -164,6 +164,15 @@ Target::_init (const Param &)
this->c.longsize = int_size_in_bytes (long_integer_type_node);
this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
+ /* Define what type to use for wchar_t. We don't want to support wide
+ characters less than "short" in D. */
+ if (WCHAR_TYPE_SIZE == 32)
+ this->c.twchar_t = Type::basic[Tdchar];
+ else if (WCHAR_TYPE_SIZE == 16)
+ this->c.twchar_t = Type::basic[Twchar];
+ else
+ sorry ("D does not support wide characters on this target.");
+
/* Set-up target C++ ABI. */
this->cpp.reverseOverloads = false;
this->cpp.exceptions = true;
@@ -417,6 +426,15 @@ TargetCPP::fundamentalType (const Type *, bool &)
return false;
}
+/* Get the starting offset position for fields of an `extern(C++)` class
+ that is derived from the given BASE_CLASS. */
+
+unsigned
+TargetCPP::derivedClassOffset(ClassDeclaration *base_class)
+{
+ return base_class->structsize;
+}
+
/* Return the default system linkage for the target. */
LINK
@@ -517,3 +535,13 @@ Target::getTargetInfo (const char *key, const Loc &loc)
return NULL;
}
+
+/**
+ * Returns true if the implementation for object monitors is always defined
+ * in the D runtime library (rt/monitor_.d). */
+
+bool
+Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
+{
+ return true;
+}
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 042abbf..0ec1934 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1277,6 +1277,10 @@ get_symbol_decl (Declaration *decl)
if (decl->storage_class & STCfinal)
DECL_FINAL_P (decl->csym) = 1;
+ /* Function is of type `noreturn' or `typeof(*null)'. */
+ if (fd->type->nextOf ()->ty == Tnoreturn)
+ TREE_THIS_VOLATILE (decl->csym) = 1;
+
/* Check whether this function is expanded by the frontend. */
DECL_INTRINSIC_CODE (decl->csym) = INTRINSIC_NONE;
maybe_set_intrinsic (fd);
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 78b454c..86475c8 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-a3c9bf422e7ff54d45846b8c577ee82da4234db1
+3b808e838bb00f527eb4ed5281cd985756237b8f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/attrib.c b/gcc/d/dmd/attrib.c
index 56b8ce8..a808b8a 100644
--- a/gcc/d/dmd/attrib.c
+++ b/gcc/d/dmd/attrib.c
@@ -80,8 +80,8 @@ Scope *AttribDeclaration::createNewScope(Scope *sc,
if (stc != sc->stc ||
linkage != sc->linkage ||
cppmangle != sc->cppmangle ||
- !protection.isSubsetOf(sc->protection) ||
explicitProtection != sc->explicitProtection ||
+ !(protection == sc->protection) ||
aligndecl != sc->aligndecl ||
inlining != sc->inlining)
{
@@ -552,10 +552,21 @@ void ProtDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
if (protection.kind == Prot::package_ && protection.pkg && sc->_module)
{
Module *m = sc->_module;
- Package* pkg = m->parent ? m->parent->isPackage() : NULL;
- if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
- error("does not bind to one of ancestor packages of module `%s`",
- m->toPrettyChars(true));
+
+ // While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if
+ // each package's .isModule() properites are equal.
+ //
+ // Properties generated from `package(foo)` i.e. protection.pkg have .isModule() == null.
+ // This breaks package declarations of the package in question if they are declared in
+ // the same package.d file, which _do_ have a module associated with them, and hence a non-null
+ // isModule()
+ if (!m->isPackage() || !protection.pkg->ident->equals(m->isPackage()->ident))
+ {
+ Package* pkg = m->parent ? m->parent->isPackage() : NULL;
+ if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
+ error("does not bind to one of ancestor packages of module `%s`",
+ m->toPrettyChars(true));
+ }
}
return AttribDeclaration::addMember(sc, sds);
@@ -795,6 +806,18 @@ Scope *PragmaDeclaration::newScope(Scope *sc)
sc->protection, sc->explicitProtection, sc->aligndecl,
inlining);
}
+ if (ident == Id::printf || ident == Id::scanf)
+ {
+ Scope *sc2 = sc->push();
+
+ if (ident == Id::printf)
+ // Override previous setting, never let both be set
+ sc2->flags = (sc2->flags & ~SCOPEscanf) | SCOPEprintf;
+ else
+ sc2->flags = (sc2->flags & ~SCOPEprintf) | SCOPEscanf;
+
+ return sc2;
+ }
return sc;
}
@@ -1164,12 +1187,12 @@ void ForwardingAttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
// These are mixin declarations, like mixin("int x");
-CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
+CompileDeclaration::CompileDeclaration(Loc loc, Expressions *exps)
: AttribDeclaration(NULL)
{
//printf("CompileDeclaration(loc = %d)\n", loc.linnum);
this->loc = loc;
- this->exp = exp;
+ this->exps = exps;
this->scopesym = NULL;
this->compiled = false;
}
@@ -1177,7 +1200,7 @@ CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *)
{
//printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
- return new CompileDeclaration(loc, exp->syntaxCopy());
+ return new CompileDeclaration(loc, Expression::arraySyntaxCopy(exps));
}
void CompileDeclaration::addMember(Scope *, ScopeDsymbol *sds)
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index 7436417..174d3c1 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -234,12 +234,12 @@ public:
class CompileDeclaration : public AttribDeclaration
{
public:
- Expression *exp;
+ Expressions *exps;
ScopeDsymbol *scopesym;
bool compiled;
- CompileDeclaration(Loc loc, Expression *exp);
+ CompileDeclaration(Loc loc, Expressions *exps);
Dsymbol *syntaxCopy(Dsymbol *s);
void addMember(Scope *sc, ScopeDsymbol *sds);
void setScope(Scope *sc);
diff --git a/gcc/d/dmd/blockexit.c b/gcc/d/dmd/blockexit.c
index 44e3cc1..1895d36 100644
--- a/gcc/d/dmd/blockexit.c
+++ b/gcc/d/dmd/blockexit.c
@@ -62,6 +62,8 @@ int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow)
return;
}
}
+ if (s->exp->type->toBasetype()->isTypeNoreturn())
+ result = BEhalt;
if (canThrow(s->exp, func, mustNotThrow))
result |= BEthrow;
}
diff --git a/gcc/d/dmd/chkformat.c b/gcc/d/dmd/chkformat.c
new file mode 100644
index 0000000..d00b658
--- /dev/null
+++ b/gcc/d/dmd/chkformat.c
@@ -0,0 +1,975 @@
+
+/* 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
+ */
+
+// Check the arguments to `printf` and `scanf` against the `format` string.
+
+#include "root/dsystem.h"
+#include "root/dcompat.h"
+
+#include "arraytypes.h"
+#include "cond.h"
+#include "errors.h"
+#include "expression.h"
+#include "globals.h"
+#include "identifier.h"
+#include "mtype.h"
+#include "target.h"
+
+
+/* Different kinds of formatting specifications, variations we don't
+ care about are merged. (Like we don't care about the difference between
+ f, e, g, a, etc.)
+
+ For `scanf`, every format is a pointer.
+ */
+enum Format
+{
+ Format_d, // int
+ Format_hhd, // signed char
+ Format_hd, // short int
+ Format_ld, // long int
+ Format_lld, // long long int
+ Format_jd, // intmax_t
+ Format_zd, // size_t
+ Format_td, // ptrdiff_t
+ Format_u, // unsigned int
+ Format_hhu, // unsigned char
+ Format_hu, // unsigned short int
+ Format_lu, // unsigned long int
+ Format_llu, // unsigned long long int
+ Format_ju, // uintmax_t
+ Format_g, // float (scanf) / double (printf)
+ Format_lg, // double (scanf)
+ Format_Lg, // long double (both)
+ Format_s, // char string (both)
+ Format_ls, // wchar_t string (both)
+ Format_c, // char (printf)
+ Format_lc, // wint_t (printf)
+ Format_p, // pointer
+ Format_n, // pointer to int
+ Format_hhn, // pointer to signed char
+ Format_hn, // pointer to short
+ Format_ln, // pointer to long int
+ Format_lln, // pointer to long long int
+ Format_jn, // pointer to intmax_t
+ Format_zn, // pointer to size_t
+ Format_tn, // pointer to ptrdiff_t
+ Format_GNU_a, // GNU ext. : address to a string with no maximum size (scanf)
+ Format_GNU_m, // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
+ Format_percent, // %% (i.e. no argument)
+ Format_error, // invalid format specification
+};
+
+/**************************************
+ * Parse the *length specifier* and the *specifier* of the following form:
+ * `[length]specifier`
+ *
+ * Params:
+ * format = format string
+ * idx = index of of start of format specifier,
+ * which gets updated to index past the end of it,
+ * even if `Format_error` is returned
+ * genSpecifier = Generic specifier. For instance, it will be set to `d` if the
+ * format is `hdd`.
+ * Returns:
+ * Format
+ */
+static Format parseGenericFormatSpecifier(const char *format,
+ size_t &idx, char &genSpecifier, bool useGNUExts =
+ findCondition(global.versionids, Identifier::idPool("CRuntime_Glibc")))
+{
+ genSpecifier = 0;
+
+ const size_t length = strlen(format);
+
+ /* Read the `length modifier`
+ */
+ const char lm = format[idx];
+ bool lm1= false; // if jztL
+ bool lm2= false; // if `hh` or `ll`
+ if (lm == 'j' ||
+ lm == 'z' ||
+ lm == 't' ||
+ lm == 'L')
+ {
+ ++idx;
+ if (idx == length)
+ return Format_error;
+ lm1 = true;
+ }
+ else if (lm == 'h' || lm == 'l')
+ {
+ ++idx;
+ if (idx == length)
+ return Format_error;
+ lm2 = lm == format[idx];
+ if (lm2)
+ {
+ ++idx;
+ if (idx == length)
+ return Format_error;
+ }
+ }
+
+ /* Read the `specifier`
+ */
+ Format specifier;
+ const char sc = format[idx];
+ genSpecifier = sc;
+ switch (sc)
+ {
+ case 'd':
+ case 'i':
+ if (lm == 'L')
+ specifier = Format_error;
+ else
+ specifier = lm == 'h' && lm2 ? Format_hhd :
+ lm == 'h' ? Format_hd :
+ lm == 'l' && lm2 ? Format_lld :
+ lm == 'l' ? Format_ld :
+ lm == 'j' ? Format_jd :
+ lm == 'z' ? Format_zd :
+ lm == 't' ? Format_td :
+ Format_d;
+ break;
+
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ if (lm == 'L')
+ specifier = Format_error;
+ else
+ specifier = lm == 'h' && lm2 ? Format_hhu :
+ lm == 'h' ? Format_hu :
+ lm == 'l' && lm2 ? Format_llu :
+ lm == 'l' ? Format_lu :
+ lm == 'j' ? Format_ju :
+ lm == 'z' ? Format_zd :
+ lm == 't' ? Format_td :
+ Format_u;
+ break;
+
+ case 'a':
+ if (useGNUExts)
+ {
+ // https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
+ specifier = Format_GNU_a;
+ break;
+ }
+ /* fall through */
+
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'A':
+ if (lm == 'L')
+ specifier = Format_Lg;
+ else if (lm1 || lm2 || lm == 'h')
+ specifier = Format_error;
+ else
+ specifier = lm == 'l' ? Format_lg : Format_g;
+ break;
+
+ case 'c':
+ if (lm1 || lm2 || lm == 'h')
+ specifier = Format_error;
+ else
+ specifier = lm == 'l' ? Format_lc : Format_c;
+ break;
+
+ case 's':
+ if (lm1 || lm2 || lm == 'h')
+ specifier = Format_error;
+ else
+ specifier = lm == 'l' ? Format_ls : Format_s;
+ break;
+
+ case 'p':
+ if (lm1 || lm2 || lm == 'h' || lm == 'l')
+ specifier = Format_error;
+ else
+ specifier = Format_p;
+ break;
+
+ case 'n':
+ if (lm == 'L')
+ specifier = Format_error;
+ else
+ specifier = lm == 'l' && lm2 ? Format_lln :
+ lm == 'l' ? Format_ln :
+ lm == 'h' && lm2 ? Format_hhn :
+ lm == 'h' ? Format_hn :
+ lm == 'j' ? Format_jn :
+ lm == 'z' ? Format_zn :
+ lm == 't' ? Format_tn :
+ Format_n;
+ break;
+
+ case 'm':
+ if (useGNUExts)
+ {
+ // http://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
+ specifier = Format_GNU_m;
+ break;
+ }
+ goto Ldefault;
+
+ default:
+ Ldefault:
+ specifier = Format_error;
+ break;
+ }
+
+ ++idx;
+ return specifier; // success
+}
+
+Format formatError(size_t &idx, size_t i)
+{
+ idx = i;
+ return Format_error;
+}
+
+/**************************************
+ * Parse the *format specifier* which is of the form:
+ *
+ * `%[*][width][length]specifier`
+ *
+ * Params:
+ * format = format string
+ * idx = index of `%` of start of format specifier,
+ * which gets updated to index past the end of it,
+ * even if `Format_error` is returned
+ * asterisk = set if there is a `*` sub-specifier
+ * Returns:
+ * Format
+ */
+static Format parseScanfFormatSpecifier(const char *format, size_t &idx,
+ bool &asterisk)
+{
+ asterisk = false;
+
+ size_t i = idx;
+ assert(format[i] == '%');
+ const size_t length = strlen(format);
+
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+
+ if (format[i] == '%')
+ {
+ idx = i + 1;
+ return Format_percent;
+ }
+
+ // * sub-specifier
+ if (format[i] == '*')
+ {
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ asterisk = true;
+ }
+
+ // fieldWidth
+ while (isdigit(format[i]))
+ {
+ i++;
+ if (i == length)
+ return formatError(idx, i);
+ }
+
+ /* Read the scanset
+ * A scanset can be anything, so we just check that it is paired
+ */
+ if (format[i] == '[')
+ {
+ while (i < length)
+ {
+ if (format[i] == ']')
+ break;
+ ++i;
+ }
+
+ // no `]` found
+ if (i == length)
+ return formatError(idx, i);
+
+ ++i;
+ // no specifier after `]`
+ // it could be mixed with the one above, but then idx won't have the right index
+ if (i == length)
+ return formatError(idx, i);
+ }
+
+ /* Read the specifier
+ */
+ char genSpec;
+ Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
+ if (specifier == Format_error)
+ return formatError(idx, i);
+
+ idx = i;
+ return specifier; // success
+}
+
+/**************************************
+ * Parse the *format specifier* which is of the form:
+ *
+ * `%[flags][field width][.precision][length modifier]specifier`
+ *
+ * Params:
+ * format = format string
+ * idx = index of `%` of start of format specifier,
+ * which gets updated to index past the end of it,
+ * even if `Format_error` is returned
+ * widthStar = set if * for width
+ * precisionStar = set if * for precision
+ * Returns:
+ * Format
+ */
+static Format parsePrintfFormatSpecifier(const char *format, size_t &idx,
+ bool &widthStar, bool &precisionStar)
+{
+ widthStar = false;
+ precisionStar = false;
+
+ size_t i = idx;
+ assert(format[i] == '%');
+ const size_t format_length = strlen(format);
+ const size_t length = format_length;
+ bool hash = false;
+ bool zero = false;
+ bool flags = false;
+ bool width = false;
+ bool precision = false;
+
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+
+ if (format[i] == '%')
+ {
+ idx = i + 1;
+ return Format_percent;
+ }
+
+ /* Read the `flags`
+ */
+ while (1)
+ {
+ const char c = format[i];
+ if (c == '-' ||
+ c == '+' ||
+ c == ' ')
+ {
+ flags = true;
+ }
+ else if (c == '#')
+ {
+ hash = true;
+ }
+ else if (c == '0')
+ {
+ zero = true;
+ }
+ else
+ break;
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ }
+
+ /* Read the `field width`
+ */
+ {
+ const char c = format[i];
+ if (c == '*')
+ {
+ width = true;
+ widthStar = true;
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ }
+ else if ('1' <= c && c <= '9')
+ {
+ width = true;
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ while ('0' <= format[i] && format[i] <= '9')
+ {
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ }
+ }
+ }
+
+ /* Read the `precision`
+ */
+ if (format[i] == '.')
+ {
+ precision = true;
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ const char c = format[i];
+ if (c == '*')
+ {
+ precisionStar = true;
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ }
+ else if ('0' <= c && c <= '9')
+ {
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ while ('0' <= format[i] && format[i] <= '9')
+ {
+ ++i;
+ if (i == length)
+ return formatError(idx, i);
+ }
+ }
+ }
+
+ /* Read the specifier
+ */
+ char genSpec;
+ Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
+ if (specifier == Format_error)
+ return formatError(idx, i);
+
+ switch (genSpec)
+ {
+ case 'c':
+ case 's':
+ if (hash || zero)
+ return formatError(idx, i);
+ break;
+
+ case 'd':
+ case 'i':
+ if (hash)
+ return formatError(idx, i);
+ break;
+
+ case 'n':
+ if (hash || zero || precision || width || flags)
+ return formatError(idx, i);
+ break;
+
+ default:
+ break;
+ }
+
+ idx = i;
+ return specifier; // success
+}
+
+/*******************************************/
+
+static Expression *getNextPrintfArg(const Loc &loc, Expressions &args, size_t &n,
+ size_t gnu_m_count, bool &skip)
+{
+ if (n == args.length)
+ {
+ if (args.length < (n + 1) - gnu_m_count)
+ deprecation(loc, "more format specifiers than %d arguments", (int)n);
+ else
+ skip = true;
+ return NULL;
+ }
+ return args[n++];
+}
+
+static void errorPrintfFormat(const char *prefix, DString &slice, Expression *arg,
+ const char *texpect, Type *tactual)
+{
+ deprecation(arg->loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+ prefix ? prefix : "", arg->toChars(), (int)slice.length, slice.ptr, texpect, tactual->toChars());
+}
+
+/******************************************
+ * Check that arguments to a printf format string are compatible
+ * with that string. Issue errors for incompatibilities.
+ *
+ * Follows the C99 specification for printf.
+ *
+ * Takes a generous, rather than strict, view of compatiblity.
+ * For example, an unsigned value can be formatted with a signed specifier.
+ *
+ * Diagnosed incompatibilities are:
+ *
+ * 1. incompatible sizes which will cause argument misalignment
+ * 2. deferencing arguments that are not pointers
+ * 3. insufficient number of arguments
+ * 4. struct arguments
+ * 5. array and slice arguments
+ * 6. non-pointer arguments to `s` specifier
+ * 7. non-standard formats
+ * 8. undefined behavior per C99
+ *
+ * Per the C Standard, extra arguments are ignored.
+ *
+ * No attempt is made to fix the arguments or the format string.
+ *
+ * Params:
+ * loc = location for error messages
+ * format = format string
+ * args = arguments to match with format string
+ * isVa_list = if a "v" function (format check only)
+ *
+ * Returns:
+ * `true` if errors occurred
+ * References:
+ * C99 7.19.6.1
+ * http://www.cplusplus.com/reference/cstdio/printf/
+ */
+bool checkPrintfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list)
+{
+ //printf("checkPrintFormat('%s')\n", format);
+ size_t n = 0; // index in args
+ size_t gnu_m_count = 0; // number of Format_GNU_m
+ const size_t format_length = strlen(format);
+ for (size_t i = 0; i < format_length;)
+ {
+ if (format[i] != '%')
+ {
+ ++i;
+ continue;
+ }
+ bool widthStar = false;
+ bool precisionStar = false;
+ size_t j = i;
+ const Format fmt = parsePrintfFormatSpecifier(format, j, widthStar, precisionStar);
+ DString slice = DString(j - i, format + i);
+ i = j;
+
+ if (fmt == Format_percent)
+ continue; // "%%", no arguments
+
+ if (isVa_list)
+ {
+ // format check only
+ if (fmt == Format_error)
+ deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+ continue;
+ }
+
+ if (fmt == Format_GNU_m)
+ ++gnu_m_count;
+
+ if (widthStar)
+ {
+ bool skip = false;
+ Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+ if (skip)
+ continue;
+ if (!e)
+ return true;
+ Type *t = e->type->toBasetype();
+ if (t->ty != Tint32 && t->ty != Tuns32)
+ errorPrintfFormat("width ", slice, e, "int", t);
+ }
+
+ if (precisionStar)
+ {
+ bool skip = false;
+ Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+ if (skip)
+ continue;
+ if (!e)
+ return true;
+ Type *t = e->type->toBasetype();
+ if (t->ty != Tint32 && t->ty != Tuns32)
+ errorPrintfFormat("precision ", slice, e, "int", t);
+ }
+
+ bool skip = false;
+ Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+ if (skip)
+ continue;
+ if (!e)
+ return true;
+ Type *t = e->type->toBasetype();
+ Type *tnext = t->nextOf();
+ const unsigned c_longsize = target.c.longsize;
+ const bool is64bit = global.params.is64bit;
+
+ // Types which are promoted to int are allowed.
+ // Spec: C99 6.5.2.2.7
+ switch (fmt)
+ {
+ case Format_u: // unsigned int
+ case Format_d: // int
+ if (t->ty != Tint32 && t->ty != Tuns32)
+ errorPrintfFormat(NULL, slice, e, "int", t);
+ break;
+
+ case Format_hhu: // unsigned char
+ case Format_hhd: // signed char
+ if (t->ty != Tint32 && t->ty != Tuns32 && t->ty != Tint8 && t->ty != Tuns8)
+ errorPrintfFormat(NULL, slice, e, "byte", t);
+ break;
+
+ case Format_hu: // unsigned short int
+ case Format_hd: // short int
+ if (t->ty != Tint32 && t->ty != Tuns32 && t->ty != Tint16 && t->ty != Tuns16)
+ errorPrintfFormat(NULL, slice, e, "short", t);
+ break;
+
+ case Format_lu: // unsigned long int
+ case Format_ld: // long int
+ if (!(t->isintegral() && t->size() == c_longsize))
+ errorPrintfFormat(NULL, slice, e, (c_longsize == 4 ? "int" : "long"), t);
+ break;
+
+ case Format_llu: // unsigned long long int
+ case Format_lld: // long long int
+ if (t->ty != Tint64 && t->ty != Tuns64)
+ errorPrintfFormat(NULL, slice, e, "long", t);
+ break;
+
+ case Format_ju: // uintmax_t
+ case Format_jd: // intmax_t
+ if (t->ty != Tint64 && t->ty != Tuns64)
+ errorPrintfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t", t);
+ break;
+
+ case Format_zd: // size_t
+ if (!(t->isintegral() && t->size() == (is64bit ? 8 : 4)))
+ errorPrintfFormat(NULL, slice, e, "size_t", t);
+ break;
+
+ case Format_td: // ptrdiff_t
+ if (!(t->isintegral() && t->size() == (is64bit ? 8 : 4)))
+ errorPrintfFormat(NULL, slice, e, "ptrdiff_t", t);
+ break;
+
+ case Format_GNU_a: // Format_GNU_a is only for scanf
+ case Format_lg:
+ case Format_g: // double
+ if (t->ty != Tfloat64 && t->ty != Timaginary64)
+ errorPrintfFormat(NULL, slice, e, "double", t);
+ break;
+
+ case Format_Lg: // long double
+ if (t->ty != Tfloat80 && t->ty != Timaginary80)
+ errorPrintfFormat(NULL, slice, e, "real", t);
+ break;
+
+ case Format_p: // pointer
+ if (t->ty != Tpointer && t->ty != Tnull && t->ty != Tclass && t->ty != Tdelegate && t->ty != Taarray)
+ errorPrintfFormat(NULL, slice, e, "void*", t);
+ break;
+
+ case Format_n: // pointer to int
+ if (!(t->ty == Tpointer && tnext->ty == Tint32))
+ errorPrintfFormat(NULL, slice, e, "int*", t);
+ break;
+
+ case Format_ln: // pointer to long int
+ if (!(t->ty == Tpointer && tnext->isintegral() && tnext->size() == c_longsize))
+ errorPrintfFormat(NULL, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+ break;
+
+ case Format_lln: // pointer to long long int
+ if (!(t->ty == Tpointer && tnext->ty == Tint64))
+ errorPrintfFormat(NULL, slice, e, "long*", t);
+ break;
+
+ case Format_hn: // pointer to short
+ if (!(t->ty == Tpointer && tnext->ty == Tint16))
+ errorPrintfFormat(NULL, slice, e, "short*", t);
+ break;
+
+ case Format_hhn: // pointer to signed char
+ if (!(t->ty == Tpointer && tnext->ty == Tint16))
+ errorPrintfFormat(NULL, slice, e, "byte*", t);
+ break;
+
+ case Format_jn: // pointer to intmax_t
+ if (!(t->ty == Tpointer && tnext->ty == Tint64))
+ errorPrintfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t*", t);
+ break;
+
+ case Format_zn: // pointer to size_t
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+ errorPrintfFormat(NULL, slice, e, "size_t*", t);
+ break;
+
+ case Format_tn: // pointer to ptrdiff_t
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tint64 : Tint32)))
+ errorPrintfFormat(NULL, slice, e, "ptrdiff_t*", t);
+ break;
+
+ case Format_c: // char
+ if (t->ty != Tint32 && t->ty != Tuns32)
+ errorPrintfFormat(NULL, slice, e, "char", t);
+ break;
+
+ case Format_lc: // wint_t
+ if (t->ty != Tint32 && t->ty != Tuns32)
+ errorPrintfFormat(NULL, slice, e, "wchar_t", t);
+ break;
+
+ case Format_s: // pointer to char string
+ if (!(t->ty == Tpointer && (tnext->ty == Tchar || tnext->ty == Tint8 || tnext->ty == Tuns8)))
+ errorPrintfFormat(NULL, slice, e, "char*", t);
+ break;
+
+ case Format_ls: // pointer to wchar_t string
+ {
+ if (!(t->ty == Tpointer && tnext == target.c.twchar_t))
+ errorPrintfFormat(NULL, slice, e, "wchar_t*", t);
+ break;
+ }
+ case Format_error:
+ deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+ break;
+
+ case Format_GNU_m:
+ break; // not assert(0) because it may go through it if there are extra arguments
+
+ case Format_percent:
+ default:
+ assert(0);
+ }
+ }
+ return false;
+}
+
+/*******************************************/
+
+static Expression *getNextScanfArg(const Loc &loc, Expressions &args, size_t &n, bool asterisk)
+{
+ if (n == args.length)
+ {
+ if (!asterisk)
+ deprecation(loc, "more format specifiers than %d arguments", (int)n);
+ return NULL;
+ }
+ return args[n++];
+}
+
+static void errorScanfFormat(const char *prefix, DString &slice,
+ Expression *arg, const char *texpect, Type *tactual)
+{
+ deprecation(arg->loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+ prefix ? prefix : "", arg->toChars(), (int)slice.length, slice.ptr, texpect, tactual->toChars());
+}
+
+/******************************************
+ * Check that arguments to a scanf format string are compatible
+ * with that string. Issue errors for incompatibilities.
+ *
+ * Follows the C99 specification for scanf.
+ *
+ * Takes a generous, rather than strict, view of compatiblity.
+ * For example, an unsigned value can be formatted with a signed specifier.
+ *
+ * Diagnosed incompatibilities are:
+ *
+ * 1. incompatible sizes which will cause argument misalignment
+ * 2. deferencing arguments that are not pointers
+ * 3. insufficient number of arguments
+ * 4. struct arguments
+ * 5. array and slice arguments
+ * 6. non-standard formats
+ * 7. undefined behavior per C99
+ *
+ * Per the C Standard, extra arguments are ignored.
+ *
+ * No attempt is made to fix the arguments or the format string.
+ *
+ * Params:
+ * loc = location for error messages
+ * format = format string
+ * args = arguments to match with format string
+ * isVa_list = if a "v" function (format check only)
+ *
+ * Returns:
+ * `true` if errors occurred
+ * References:
+ * C99 7.19.6.2
+ * http://www.cplusplus.com/reference/cstdio/scanf/
+ */
+bool checkScanfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list)
+{
+ size_t n = 0;
+ const size_t format_length = strlen(format);
+ for (size_t i = 0; i < format_length;)
+ {
+ if (format[i] != '%')
+ {
+ ++i;
+ continue;
+ }
+ bool asterisk = false;
+ size_t j = i;
+ const Format fmt = parseScanfFormatSpecifier(format, j, asterisk);
+ DString slice = DString(j - i, format + i);
+ i = j;
+
+ if (fmt == Format_percent || asterisk)
+ continue; // "%%", "%*": no arguments
+
+ if (isVa_list)
+ {
+ // format check only
+ if (fmt == Format_error)
+ deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+ continue;
+ }
+
+ Expression *e = getNextScanfArg(loc, args, n, asterisk);
+ if (!e)
+ return true;
+
+ Type *t = e->type->toBasetype();
+ Type *tnext = t->nextOf();
+ const unsigned c_longsize = target.c.longsize;
+ const bool is64bit = global.params.is64bit;
+
+ switch (fmt)
+ {
+ case Format_n:
+ case Format_d: // pointer to int
+ if (!(t->ty == Tpointer && tnext->ty == Tint32))
+ errorScanfFormat(NULL, slice, e, "int*", t);
+ break;
+
+ case Format_hhn:
+ case Format_hhd: // pointer to signed char
+ if (!(t->ty == Tpointer && tnext->ty == Tint16))
+ errorScanfFormat(NULL, slice, e, "byte*", t);
+ break;
+
+ case Format_hn:
+ case Format_hd: // pointer to short
+ if (!(t->ty == Tpointer && tnext->ty == Tint16))
+ errorScanfFormat(NULL, slice, e, "short*", t);
+ break;
+
+ case Format_ln:
+ case Format_ld: // pointer to long int
+ if (!(t->ty == Tpointer && tnext->isintegral() && tnext->size() == c_longsize))
+ errorScanfFormat(NULL, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+ break;
+
+ case Format_lln:
+ case Format_lld: // pointer to long long int
+ if (!(t->ty == Tpointer && tnext->ty == Tint64))
+ errorScanfFormat(NULL, slice, e, "long*", t);
+ break;
+
+ case Format_jn:
+ case Format_jd: // pointer to intmax_t
+ if (!(t->ty == Tpointer && tnext->ty == Tint64))
+ errorScanfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t*", t);
+ break;
+
+ case Format_zn:
+ case Format_zd: // pointer to size_t
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+ errorScanfFormat(NULL, slice, e, "size_t*", t);
+ break;
+
+ case Format_tn:
+ case Format_td: // pointer to ptrdiff_t
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tint64 : Tint32)))
+ errorScanfFormat(NULL, slice, e, "ptrdiff_t*", t);
+ break;
+
+ case Format_u: // pointer to unsigned int
+ if (!(t->ty == Tpointer && tnext->ty == Tuns32))
+ errorScanfFormat(NULL, slice, e, "uint*", t);
+ break;
+
+ case Format_hhu: // pointer to unsigned char
+ if (!(t->ty == Tpointer && tnext->ty == Tuns8))
+ errorScanfFormat(NULL, slice, e, "ubyte*", t);
+ break;
+
+ case Format_hu: // pointer to unsigned short int
+ if (!(t->ty == Tpointer && tnext->ty == Tuns16))
+ errorScanfFormat(NULL, slice, e, "ushort*", t);
+ break;
+
+ case Format_lu: // pointer to unsigned long int
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+ errorScanfFormat(NULL, slice, e, (c_longsize == 4 ? "uint*" : "ulong*"), t);
+ break;
+
+ case Format_llu: // pointer to unsigned long long int
+ if (!(t->ty == Tpointer && tnext->ty == Tuns64))
+ errorScanfFormat(NULL, slice, e, "ulong*", t);
+ break;
+
+ case Format_ju: // pointer to uintmax_t
+ if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+ errorScanfFormat(NULL, slice, e, "ulong*", t);
+ break;
+
+ case Format_g: // pointer to float
+ if (!(t->ty == Tpointer && tnext->ty == Tfloat32))
+ errorScanfFormat(NULL, slice, e, "float*", t);
+ break;
+
+ case Format_lg: // pointer to double
+ if (!(t->ty == Tpointer && tnext->ty == Tfloat64))
+ errorScanfFormat(NULL, slice, e, "double*", t);
+ break;
+
+ case Format_Lg: // pointer to long double
+ if (!(t->ty == Tpointer && tnext->ty == Tfloat80))
+ errorScanfFormat(NULL, slice, e, "real*", t);
+ break;
+
+ case Format_GNU_a:
+ case Format_GNU_m:
+ case Format_c:
+ case Format_s: // pointer to char string
+ if (!(t->ty == Tpointer && (tnext->ty == Tchar || tnext->ty == Tint8 || tnext->ty == Tuns8)))
+ errorScanfFormat(NULL, slice, e, "char*", t);
+ break;
+
+ case Format_lc:
+ case Format_ls: // pointer to wchar_t string
+ {
+ if (!(t->ty == Tpointer && tnext == target.c.twchar_t))
+ errorScanfFormat(NULL, slice, e, "wchar_t*", t);
+ break;
+ }
+ case Format_p: // double pointer
+ if (!(t->ty == Tpointer && tnext->ty == Tpointer))
+ errorScanfFormat(NULL, slice, e, "void**", t);
+ break;
+
+ case Format_error:
+ deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+ break;
+
+ case Format_percent:
+ default:
+ assert(0);
+ }
+ }
+ return false;
+}
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index a0e0b5f..baf64c5 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -806,6 +806,14 @@ public:
writeBasicType(t, 'D', 'n');
}
+ void visit(TypeNoreturn *t)
+ {
+ if (t->isImmutable() || t->isShared())
+ return error(t);
+
+ writeBasicType(t, 0, 'v'); // mangle like `void`
+ }
+
void visit(TypeBasic *t)
{
if (t->isImmutable() || t->isShared())
@@ -1012,7 +1020,7 @@ public:
if (t->isImmutable() || t->isShared())
return error(t);
- /* __c_(u)long(long) get special mangling
+ /* __c_(u)long(long) and others get special mangling
*/
Identifier *id = t->sym->ident;
//printf("enum id = '%s'\n", id->toChars());
@@ -1020,10 +1028,18 @@ public:
return writeBasicType(t, 0, 'l');
else if (id == Id::__c_ulong)
return writeBasicType(t, 0, 'm');
+ else if (id == Id::__c_wchar_t)
+ return writeBasicType(t, 0, 'w');
else if (id == Id::__c_longlong)
return writeBasicType(t, 0, 'x');
else if (id == Id::__c_ulonglong)
return writeBasicType(t, 0, 'y');
+ else if (id == Id::__c_complex_float)
+ return writeBasicType(t, 'C', 'f');
+ else if (id == Id::__c_complex_double)
+ return writeBasicType(t, 'C', 'd');
+ else if (id == Id::__c_complex_real)
+ return writeBasicType(t, 'C', 'e');
doSymbol(t);
}
diff --git a/gcc/d/dmd/ctfeexpr.c b/gcc/d/dmd/ctfeexpr.c
index 1d669e5..a8e9783 100644
--- a/gcc/d/dmd/ctfeexpr.c
+++ b/gcc/d/dmd/ctfeexpr.c
@@ -162,7 +162,7 @@ const char *CTFEExp::toChars()
switch (op)
{
case TOKcantexp: return "<cant>";
- case TOKvoidexp: return "<void>";
+ case TOKvoidexp: return "cast(void)0";
case TOKbreak: return "<break>";
case TOKcontinue: return "<continue>";
case TOKgoto: return "<goto>";
diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c
index 61e28fe..4dd648b 100644
--- a/gcc/d/dmd/dcast.c
+++ b/gcc/d/dmd/dcast.c
@@ -26,6 +26,7 @@
FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
bool isCommutative(TOK op);
MOD MODmerge(MOD mod1, MOD mod2);
+void toAutoQualChars(const char **result, Type *t1, Type *t2);
/* ==================== implicitCast ====================== */
@@ -90,8 +91,10 @@ Expression *implicitCastTo(Expression *e, Scope *sc, Type *t)
//printf("type %p ty %d deco %p\n", type, type->ty, type->deco);
//type = type->semantic(loc, sc);
//printf("type %s t %s\n", type->deco, t->deco);
+ const char *ts[2];
+ toAutoQualChars(ts, e->type, t);
e->error("cannot implicitly convert expression (%s) of type %s to %s",
- e->toChars(), e->type->toChars(), t->toChars());
+ e->toChars(), ts[0], ts[1]);
}
}
result = new ErrorExp();
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index c7dbbbe..3f33014 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -277,15 +277,10 @@ Scope *ClassDeclaration::newScope(Scope *sc)
Scope *sc2 = AggregateDeclaration::newScope(sc);
if (isCOMclass())
{
- if (global.params.isWindows)
- sc2->linkage = LINKwindows;
- else
- {
- /* This enables us to use COM objects under Linux and
- * work with things like XPCOM
- */
- sc2->linkage = LINKc;
- }
+ /* This enables us to use COM objects under Linux and
+ * work with things like XPCOM
+ */
+ sc2->linkage = target.systemLinkage();
}
return sc2;
}
@@ -491,9 +486,10 @@ void ClassDeclaration::finalizeSize()
assert(baseClass->sizeok == SIZEOKdone);
alignsize = baseClass->alignsize;
- structsize = baseClass->structsize;
- if (isCPPclass() && global.params.isWindows)
- structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+ if (classKind == ClassKind::cpp)
+ structsize = target.cpp.derivedClassOffset(baseClass);
+ else
+ structsize = baseClass->structsize;
}
else if (isInterfaceDeclaration())
{
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 81b563f..55c8142 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -118,7 +118,7 @@ struct Match
FuncDeclaration *anyf; // pick a func, any func, to use for error recovery
};
-void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs);
+void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, const char **pMessage = NULL);
int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *));
void aliasSemantic(AliasDeclaration *ds, Scope *sc);
@@ -551,6 +551,8 @@ void builtin_init();
#define FUNCFLAGreturnInprocess 0x10 // working on inferring 'return' for parameters
#define FUNCFLAGinlineScanned 0x20 // function has been scanned for inline possibilities
#define FUNCFLAGinferScope 0x40 // infer 'scope' for parameters
+#define FUNCFLAGprintf 0x200 // is a printf-like function
+#define FUNCFLAGscanf 0x400 // is a scanf-like function
class FuncDeclaration : public Declaration
{
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index ca1d3bb..bfd3b72 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -22,6 +22,19 @@
#include "declaration.h"
#include "init.h"
+bool isSpecialEnumIdent(const Identifier *ident)
+{
+ return ident == Id::__c_long ||
+ ident == Id::__c_ulong ||
+ ident == Id::__c_longlong ||
+ ident == Id::__c_ulonglong ||
+ ident == Id::__c_long_double ||
+ ident == Id::__c_wchar_t ||
+ ident == Id::__c_complex_float ||
+ ident == Id::__c_complex_double ||
+ ident == Id::__c_complex_real;
+}
+
/********************************* EnumDeclaration ****************************/
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
@@ -187,11 +200,7 @@ Lerrors:
*/
bool EnumDeclaration::isSpecial() const
{
- return (ident == Id::__c_long ||
- ident == Id::__c_ulong ||
- ident == Id::__c_longlong ||
- ident == Id::__c_ulonglong ||
- ident == Id::__c_long_double) && memtype;
+ return isSpecialEnumIdent(ident) && memtype;
}
Expression *EnumDeclaration::getDefaultValue(Loc loc)
diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c
index 0d93ed8..7b63a18 100644
--- a/gcc/d/dmd/dimport.c
+++ b/gcc/d/dmd/dimport.c
@@ -161,37 +161,75 @@ void Import::load(Scope *sc)
if (mod && !mod->importedFrom)
mod->importedFrom = sc ? sc->_module->importedFrom : Module::rootModule;
if (!pkg)
- pkg = mod;
+ {
+ if (mod && mod->isPackageFile)
+ {
+ // one level depth package.d file (import pkg; ./pkg/package.d)
+ // it's necessary to use the wrapping Package already created
+ pkg = mod->pkg;
+ }
+ else
+ pkg = mod;
+ }
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::importAll(Scope *sc)
{
- if (!mod)
+ if (mod) return; // Already done
+ load(sc);
+ if (!mod) return; // Failed
+
+ if (sc->stc & STCstatic)
+ isstatic = true;
+ mod->importAll(NULL);
+ if (mod->md && mod->md->isdeprecated)
{
- load(sc);
- if (mod) // if successfully loaded module
- {
- mod->importAll(NULL);
-
- if (mod->md && mod->md->isdeprecated)
- {
- Expression *msg = mod->md->msg;
- if (StringExp *se = msg ? msg->toStringExp() : NULL)
- mod->deprecation(loc, "is deprecated - %s", se->string);
- else
- mod->deprecation(loc, "is deprecated");
- }
+ Expression *msg = mod->md->msg;
+ if (StringExp *se = msg ? msg->toStringExp() : NULL)
+ mod->deprecation(loc, "is deprecated - %s", se->string);
+ else
+ mod->deprecation(loc, "is deprecated");
+ }
+ if (sc->explicitProtection)
+ protection = sc->protection;
+ if (!isstatic && !aliasId && !names.length)
+ sc->scopesym->importScope(mod, protection);
+ // Enable access to pkgs/mod as soon as posible, because compiler
+ // can traverse them before the import gets semantic (Issue: 21501)
+ if (!aliasId && !names.length)
+ addPackageAccess(sc->scopesym);
+}
- if (sc->explicitProtection)
- protection = sc->protection;
- if (!isstatic && !aliasId && !names.length)
- {
- sc->scopesym->importScope(mod, protection);
- }
+/*******************************
+ * Mark the imported packages as accessible from the current
+ * scope. This access check is necessary when using FQN b/c
+ * we're using a single global package tree.
+ * https://issues.dlang.org/show_bug.cgi?id=313
+ */
+void Import::addPackageAccess(ScopeDsymbol *scopesym)
+{
+ //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
+ if (packages)
+ {
+ // import a.b.c.d;
+ Package *p = pkg; // a
+ scopesym->addAccessiblePackage(p, protection);
+ for (size_t i = 1; i < packages->length; i++) // [b, c]
+ {
+ Identifier *id = (*packages)[i];
+ p = (Package *) p->symtab->lookup(id);
+ // https://issues.dlang.org/show_bug.cgi?id=17991
+ // An import of truly empty file/package can happen
+ // https://issues.dlang.org/show_bug.cgi?id=20151
+ // Package in the path conflicts with a module name
+ if (p == NULL)
+ return;
+ scopesym->addAccessiblePackage(p, protection);
}
}
+ scopesym->addAccessiblePackage(mod, protection); // d
}
Dsymbol *Import::toAlias()
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 303ae61..83f4c18 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -82,6 +82,8 @@ void initTypeMangle()
mangleChar[Treturn] = "@";
mangleChar[Tvector] = "@";
mangleChar[Ttraits] = "@";
+ mangleChar[Tmixin] = "@";
+ mangleChar[Tnoreturn] = "@"; // becomes 'Nn'
mangleChar[Tnull] = "n"; // same as TypeNone
@@ -150,7 +152,7 @@ public:
* using upper case letters for all digits but the last digit which uses
* a lower case letter.
* The decoder has to look up the referenced position to determine
- * whether the back reference is an identifer (starts with a digit)
+ * whether the back reference is an identifier (starts with a digit)
* or a type (starts with a letter).
*
* Params:
@@ -414,6 +416,11 @@ public:
visit((Type *)t);
}
+ void visit(TypeNoreturn *)
+ {
+ buf->writestring("Nn");
+ }
+
////////////////////////////////////////////////////////////////////////////
void mangleDecl(Declaration *sthis)
@@ -1085,3 +1092,31 @@ void mangleToBuffer(TemplateInstance *ti, OutBuffer *buf)
Mangler v(buf);
v.mangleTemplateInstance(ti);
}
+
+/**********************************************
+ * Convert a string representing a type (the deco) and
+ * return its equivalent Type.
+ * Params:
+ * deco = string containing the deco
+ * Returns:
+ * null for failed to convert
+ * Type for succeeded
+ */
+
+Type *decoToType(const char *deco)
+{
+ if (!deco)
+ return NULL;
+
+ //printf("decoToType(): %s\n", deco)
+ if (StringValue *sv = Type::stringtable.lookup(deco, strlen(deco)))
+ {
+ if (sv->ptrvalue)
+ {
+ Type *t = (Type *)sv->ptrvalue;
+ assert(t->deco);
+ return t;
+ }
+ }
+ return NULL;
+}
diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c
index ed01858..472b2b9 100644
--- a/gcc/d/dmd/dmodule.c
+++ b/gcc/d/dmd/dmodule.c
@@ -52,6 +52,7 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
members = NULL;
isDocFile = 0;
isPackageFile = false;
+ pkg = NULL;
needmoduleinfo = 0;
selfimports = 0;
rootimports = 0;
@@ -685,15 +686,27 @@ Module *Module::parse()
*
* To avoid the conflict:
* 1. If preceding package name insertion had occurred by Package::resolve,
- * later package.d loading will change Package::isPkgMod to PKGmodule and set Package::mod.
+ * reuse the previous wrapping 'Package' if it exists
* 2. Otherwise, 'package.d' wrapped by 'Package' is inserted to the internal tree in here.
+ *
+ * Then change Package::isPkgMod to PKGmodule and set Package::mod.
+ *
+ * Note that the 'wrapping Package' is the Package that contains package.d and other submodules,
+ * the one inserted to the symbol table.
*/
- Package *p = new Package(ident);
+ Dsymbol *ps = dst->lookup(ident);
+ Package *p = ps ? ps->isPackage() : NULL;
+ if (p == NULL)
+ {
+ p = new Package(ident);
+ p->tag = this->tag; // reuse the same package tag
+ p->symtab = new DsymbolTable();
+ }
+ this->tag= p->tag; // reuse the 'older' package tag
+ this->pkg = p;
p->parent = this->parent;
p->isPkgMod = PKGmodule;
p->mod = this;
- p->tag = this->tag; // reuse the same package tag
- p->symtab = new DsymbolTable();
s = p;
}
if (!dst->insert(s))
@@ -720,15 +733,9 @@ Module *Module::parse()
}
else if (Package *pkg = prev->isPackage())
{
- if (pkg->isPkgMod == PKGunknown && isPackageFile)
- {
- /* If the previous inserted Package is not yet determined as package.d,
- * link it to the actual module.
- */
- pkg->isPkgMod = PKGmodule;
- pkg->mod = this;
- pkg->tag = this->tag; // reuse the same package tag
- }
+ // 'package.d' loaded after a previous 'Package' insertion
+ if (isPackageFile)
+ amodules.push(this); // Add to global array of all modules
else
error(md ? md->loc : loc, "from file %s conflicts with package name %s",
srcname, pkg->toChars());
diff --git a/gcc/d/dmd/dscope.c b/gcc/d/dmd/dscope.c
index 65e6734..e56f393 100644
--- a/gcc/d/dmd/dscope.c
+++ b/gcc/d/dmd/dscope.c
@@ -24,6 +24,7 @@
#include "aggregate.h"
#include "module.h"
#include "id.h"
+#include "target.h"
#include "template.h"
Scope *Scope::freelist = NULL;
@@ -155,7 +156,8 @@ Scope *Scope::push()
s->nofree = 0;
s->fieldinit = saveFieldInit();
s->flags = (flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe | SCOPEcompile | SCOPEconstraint |
- SCOPEnoaccesscheck | SCOPEignoresymbolvisibility));
+ SCOPEnoaccesscheck | SCOPEignoresymbolvisibility |
+ SCOPEprintf | SCOPEscanf));
s->lastdc = NULL;
assert(this != s);
@@ -637,7 +639,7 @@ const char *Scope::search_correct_C(Identifier *ident)
else if (ident == Id::C_unsigned)
tok = TOKuns32;
else if (ident == Id::C_wchar_t)
- tok = global.params.isWindows ? TOKwchar : TOKdchar;
+ tok = target.c.twchar_t->ty == Twchar ? TOKwchar : TOKdchar;
else
return NULL;
return Token::toChars(tok);
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index 89c5557..f0c1cf6 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -515,7 +515,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
* Returns:
* symbol found, NULL if not
*/
-Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
+Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id, int flags)
{
//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
Dsymbol *s = toAlias();
@@ -533,7 +533,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
switch (id->dyncast())
{
case DYNCAST_IDENTIFIER:
- sm = s->search(loc, (Identifier *)id);
+ sm = s->search(loc, (Identifier *)id, flags);
break;
case DYNCAST_DSYMBOL:
@@ -1801,31 +1801,3 @@ bool Prot::operator==(const Prot& other) const
}
return false;
}
-
-/**
- * Checks if parent defines different access restrictions than this one.
- *
- * Params:
- * parent = protection attribute for scope that hosts this one
- *
- * Returns:
- * 'true' if parent is already more restrictive than this one and thus
- * no differentiation is needed.
- */
-bool Prot::isSubsetOf(const Prot& parent) const
-{
- if (this->kind != parent.kind)
- return false;
-
- if (this->kind == Prot::package_)
- {
- if (!this->pkg)
- return true;
- if (!parent.pkg)
- return false;
- if (parent.pkg->isAncestorPackageOf(this->pkg))
- return true;
- }
-
- return true;
-}
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 1ddfe06..4aabb5d 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -107,7 +107,6 @@ struct Prot
bool isMoreRestrictiveThan(const Prot other) const;
bool operator==(const Prot& other) const;
- bool isSubsetOf(const Prot& other) const;
};
// in hdrgen.c
@@ -207,7 +206,7 @@ public:
virtual void importAll(Scope *sc);
virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
Dsymbol *search_correct(Identifier *id);
- Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id);
+ Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id, int flags);
virtual bool overloadInsert(Dsymbol *s);
virtual d_uns64 size(Loc loc);
virtual bool isforwardRef();
diff --git a/gcc/d/dmd/dsymbolsem.c b/gcc/d/dmd/dsymbolsem.c
index 5d5c9fc..26e23e9 100644
--- a/gcc/d/dmd/dsymbolsem.c
+++ b/gcc/d/dmd/dsymbolsem.c
@@ -42,6 +42,8 @@ VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
Initializer *inferType(Initializer *init, Scope *sc);
void MODtoBuffer(OutBuffer *buf, MOD mod);
bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
+bool symbolIsVisible(Scope *sc, Dsymbol *s);
Objc *objc();
static unsigned setMangleOverride(Dsymbol *s, char *sym)
@@ -1098,22 +1100,7 @@ public:
scopesym->importScope(imp->mod, imp->protection);
}
- // Mark the imported packages as accessible from the current
- // scope. This access check is necessary when using FQN b/c
- // we're using a single global package tree. See Bugzilla 313.
- if (imp->packages)
- {
- // import a.b.c.d;
- Package *p = imp->pkg; // a
- scopesym->addAccessiblePackage(p, imp->protection);
- for (size_t i = 1; i < imp->packages->length; i++) // [b, c]
- {
- Identifier *id = (*imp->packages)[i];
- p = (Package *) p->symtab->lookup(id);
- scopesym->addAccessiblePackage(p, imp->protection);
- }
- }
- scopesym->addAccessiblePackage(imp->mod, imp->protection); // d
+ imp->addPackageAccess(scopesym);
}
dsymbolSemantic(imp->mod, NULL);
@@ -1130,8 +1117,12 @@ public:
{
AliasDeclaration *ad = imp->aliasdecls[i];
//printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), imp->aliases[i]->toChars(), imp->names[i]->toChars(), ad->_scope);
- if (imp->mod->search(imp->loc, imp->names[i]))
+ Dsymbol *sym = imp->mod->search(imp->loc, imp->names[i], IgnorePrivateImports);
+ if (sym)
{
+ if (!symbolIsVisible(sc, sym))
+ imp->mod->error(imp->loc, "member `%s` is not visible from module `%s`",
+ imp->names[i]->toChars(), sc->_module->toChars());
dsymbolSemantic(ad, sc);
// If the import declaration is in non-root module,
// analysis of the aliased symbol is deferred.
@@ -1141,7 +1132,7 @@ public:
{
Dsymbol *s = imp->mod->search_correct(imp->names[i]);
if (s)
- imp->mod->error(imp->loc, "import `%s` not found, did you mean %s `%s`?", imp->names[i]->toChars(), s->kind(), s->toChars());
+ imp->mod->error(imp->loc, "import `%s` not found, did you mean %s `%s`?", imp->names[i]->toChars(), s->kind(), s->toPrettyChars());
else
imp->mod->error(imp->loc, "import `%s` not found", imp->names[i]->toChars());
ad->type = Type::terror;
@@ -1312,8 +1303,6 @@ public:
e = expressionSemantic(e, sc);
e = resolveProperties(sc, e);
sc = sc->endCTFE();
-
- // pragma(msg) is allowed to contain types as well as expressions
e = ctfeInterpretForPragmaMsg(e);
if (e->op == TOKerror)
{
@@ -1458,6 +1447,12 @@ public:
}
}
}
+ else if (pd->ident == Id::printf || pd->ident == Id::scanf)
+ {
+ if (pd->args && pd->args->length != 0)
+ pd->error("takes no argument");
+ goto Ldecl;
+ }
else if (global.params.ignoreUnsupportedPragmas)
{
if (global.params.verbose)
@@ -1547,13 +1542,14 @@ public:
Dsymbols *compileIt(CompileDeclaration *cd)
{
//printf("CompileDeclaration::compileIt(loc = %d) %s\n", cd->loc.linnum, cd->exp->toChars());
- StringExp *se = semanticString(sc, cd->exp, "argument to mixin");
- if (!se)
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, cd->exps))
return NULL;
- se = se->toUTF8(sc);
unsigned errors = global.errors;
- Parser p(cd->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+ const size_t len = buf.length();
+ const char *str = buf.extractChars();
+ Parser p(cd->loc, sc->_module, (const utf8_t *)str, len, false);
p.nextToken();
Dsymbols *d = p.parseDeclDefs(0);
@@ -1562,7 +1558,7 @@ public:
if (p.token.value != TOKeof)
{
- cd->exp->error("incomplete mixin declaration (%s)", se->toChars());
+ cd->error("incomplete mixin declaration (%s)", str);
return NULL;
}
return d;
@@ -1637,7 +1633,7 @@ public:
Scope *sc = m->_scope; // see if already got one from importAll()
if (!sc)
{
- Scope::createGlobal(m); // create root scope
+ sc = Scope::createGlobal(m); // create root scope
}
//printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
@@ -1735,7 +1731,7 @@ public:
// memtype is forward referenced, so try again later
ed->_scope = scx ? scx : sc->copy();
ed->_scope->setNoFree();
- ed->_scope->_module->addDeferredSemantic(ed);
+ Module::addDeferredSemantic(ed);
Module::dprogress = dprogress_save;
//printf("\tdeferring %s\n", ed->toChars());
ed->semanticRun = PASSinit;
@@ -2233,7 +2229,7 @@ public:
//printf("forward reference - deferring\n");
tm->_scope = scx ? scx : sc->copy();
tm->_scope->setNoFree();
- tm->_scope->_module->addDeferredSemantic(tm);
+ Module::addDeferredSemantic(tm);
return;
}
@@ -2457,6 +2453,23 @@ public:
ns->semanticRun = PASSsemanticdone;
}
+
+private:
+ static bool isPointerToChar(Parameter *p)
+ {
+ if (TypePointer *tptr = p->type->isTypePointer())
+ {
+ return tptr->next->ty == Tchar;
+ }
+ return false;
+ }
+
+ static bool isVa_list(Parameter *p, FuncDeclaration *funcdecl, Scope *sc)
+ {
+ return p->type->equals(target.va_listType(funcdecl->loc, sc));
+ }
+
+public:
void funcDeclarationSemantic(FuncDeclaration *funcdecl)
{
TypeFunction *f;
@@ -2771,6 +2784,45 @@ public:
if (funcdecl->isAbstract() && funcdecl->isFinalFunc())
funcdecl->error("cannot be both final and abstract");
+ if (const unsigned pors = sc->flags & (SCOPEprintf | SCOPEscanf))
+ {
+ /* printf/scanf-like functions must be of the form:
+ * extern (C/C++) T printf([parameters...], const(char)* format, ...);
+ * or:
+ * extern (C/C++) T vprintf([parameters...], const(char)* format, va_list);
+ */
+ const size_t nparams = f->parameterList.length();
+ if ((f->linkage == LINKc || f->linkage == LINKcpp) &&
+
+ ((f->parameterList.varargs == VARARGvariadic &&
+ nparams >= 1 &&
+ isPointerToChar(f->parameterList[nparams - 1])) ||
+ (f->parameterList.varargs == VARARGnone &&
+ nparams >= 2 &&
+ isPointerToChar(f->parameterList[nparams - 2]) &&
+ isVa_list(f->parameterList[nparams - 1], funcdecl, sc))
+ )
+ )
+ {
+ funcdecl->flags |= (pors == SCOPEprintf) ? FUNCFLAGprintf : FUNCFLAGscanf;
+ }
+ else
+ {
+ const char *p = (pors == SCOPEprintf ? Id::printf : Id::scanf)->toChars();
+ if (f->parameterList.varargs == VARARGvariadic)
+ {
+ funcdecl->error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, ...)`"
+ " not `%s`",
+ p, f->next->toChars(), funcdecl->toChars(), funcdecl->type->toChars());
+ }
+ else
+ {
+ funcdecl->error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, va_list)`",
+ p, f->next->toChars(), funcdecl->toChars());
+ }
+ }
+ }
+
id = parent->isInterfaceDeclaration();
if (id)
{
@@ -3831,7 +3883,7 @@ public:
sd->_scope = scx ? scx : sc->copy();
sd->_scope->setNoFree();
- sd->_scope->_module->addDeferredSemantic(sd);
+ Module::addDeferredSemantic(sd);
//printf("\tdeferring %s\n", sd->toChars());
return;
@@ -4079,7 +4131,7 @@ public:
{
//printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
if (tc->sym->_scope)
- tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+ Module::addDeferredSemantic(tc->sym);
cldec->baseok = BASEOKnone;
}
L7: ;
@@ -4131,7 +4183,7 @@ public:
{
//printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
if (tc->sym->_scope)
- tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+ Module::addDeferredSemantic(tc->sym);
cldec->baseok = BASEOKnone;
}
i++;
@@ -4141,7 +4193,7 @@ public:
// Forward referencee of one or more bases, try again later
cldec->_scope = scx ? scx : sc->copy();
cldec->_scope->setNoFree();
- cldec->_scope->_module->addDeferredSemantic(cldec);
+ Module::addDeferredSemantic(cldec);
//printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
return;
}
@@ -4254,8 +4306,8 @@ public:
cldec->_scope = scx ? scx : sc->copy();
cldec->_scope->setNoFree();
if (tc->sym->_scope)
- tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
- cldec->_scope->_module->addDeferredSemantic(cldec);
+ Module::addDeferredSemantic(tc->sym);
+ Module::addDeferredSemantic(cldec);
//printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
return;
}
@@ -4359,7 +4411,7 @@ public:
cldec->_scope = scx ? scx : sc->copy();
cldec->_scope->setNoFree();
- cldec->_scope->_module->addDeferredSemantic(cldec);
+ Module::addDeferredSemantic(cldec);
//printf("\tdeferring %s\n", cldec->toChars());
return;
}
@@ -4628,7 +4680,7 @@ public:
{
//printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
if (tc->sym->_scope)
- tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+ Module::addDeferredSemantic(tc->sym);
idec->baseok = BASEOKnone;
}
i++;
@@ -4638,7 +4690,7 @@ public:
// Forward referencee of one or more bases, try again later
idec->_scope = scx ? scx : sc->copy();
idec->_scope->setNoFree();
- idec->_scope->_module->addDeferredSemantic(idec);
+ Module::addDeferredSemantic(idec);
return;
}
idec->baseok = BASEOKdone;
@@ -4682,8 +4734,8 @@ public:
idec->_scope = scx ? scx : sc->copy();
idec->_scope->setNoFree();
if (tc->sym->_scope)
- tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
- idec->_scope->_module->addDeferredSemantic(idec);
+ Module::addDeferredSemantic(tc->sym);
+ Module::addDeferredSemantic(idec);
return;
}
}
@@ -5335,6 +5387,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
ds->userAttribDecl = sc->userAttribDecl;
// TypeTraits needs to know if it's located in an AliasDeclaration
+ const unsigned oldflags = sc->flags;
sc->flags |= SCOPEalias;
if (ds->aliassym)
@@ -5345,7 +5398,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
{
if (fd && fd->semanticRun >= PASSsemanticdone)
{
- sc->flags &= ~SCOPEalias;
+ sc->flags = oldflags;
return;
}
@@ -5361,13 +5414,13 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
ds->aliassym = NULL;
ds->type = Type::terror;
}
- sc->flags &= ~SCOPEalias;
+ sc->flags = oldflags;
return;
}
if (ds->aliassym->isTemplateInstance())
dsymbolSemantic(ds->aliassym, sc);
- sc->flags &= ~SCOPEalias;
+ sc->flags = oldflags;
return;
}
ds->inuse = 1;
@@ -5472,7 +5525,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
if (!ds->overloadInsert(sx))
ScopeDsymbol::multiplyDefined(Loc(), sx, ds);
}
- sc->flags &= ~SCOPEalias;
+ sc->flags = oldflags;
}
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index b868e9a..208b064 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -156,17 +156,14 @@ Dsymbol *getDsymbol(RootObject *oarg)
if (ea)
{
// Try to convert Expression to symbol
- if (ea->op == TOKvar)
- sa = ((VarExp *)ea)->var;
- else if (ea->op == TOKfunction)
- {
- if (((FuncExp *)ea)->td)
- sa = ((FuncExp *)ea)->td;
- else
- sa = ((FuncExp *)ea)->fd;
- }
- else if (ea->op == TOKtemplate)
- sa = ((TemplateExp *)ea)->td;
+ if (VarExp *ve = ea->isVarExp())
+ sa = ve->var;
+ else if (FuncExp *fe = ea->isFuncExp())
+ sa = fe->td ? (Dsymbol *)fe->td : (Dsymbol *)fe->fd;
+ else if (TemplateExp *te = ea->isTemplateExp())
+ sa = te->td;
+ else if (ScopeExp *se = ea->isScopeExp())
+ sa = se->sds;
else
sa = NULL;
}
@@ -536,6 +533,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->isstatic = true;
this->previous = NULL;
this->protection = Prot(Prot::undefined);
+ this->inuse = 0;
this->instances = NULL;
// Compute in advance for Ddoc's use
@@ -770,7 +768,9 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
Declaration *sparam;
//printf("\targument [%d]\n", i);
+ inuse++;
m2 = tp->matchArg(ti->loc, paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
+ inuse--;
//printf("\tm2 = %d\n", m2);
if (m2 == MATCHnomatch)
@@ -1397,7 +1397,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
}
else
{
+ inuse++;
oded = tparam->defaultArg(instLoc, paramscope);
+ inuse--;
if (oded)
(*dedargs)[i] = declareParameter(paramscope, tparam, oded);
}
@@ -1771,7 +1773,9 @@ Lmatch:
}
else
{
+ inuse++;
oded = tparam->defaultArg(instLoc, paramscope);
+ inuse--;
if (!oded)
{
// if tuple parameter and
@@ -1997,18 +2001,19 @@ bool TemplateDeclaration::isOverloadable()
/*************************************************
* Given function arguments, figure out which template function
* to expand, and return matching result.
- * Input:
- * m matching result
- * dstart the root of overloaded function templates
- * loc instantiation location
- * sc instantiation scope
- * tiargs initial list of template arguments
- * tthis if !NULL, the 'this' pointer argument
- * fargs arguments to function
+ * Params:
+ * m = matching result
+ * dstart = the root of overloaded function templates
+ * loc = instantiation location
+ * sc = instantiation scope
+ * tiargs = initial list of template arguments
+ * tthis = if !NULL, the 'this' pointer argument
+ * fargs = arguments to function
+ * pMessage = address to store error message, or null
*/
void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
- Objects *tiargs, Type *tthis, Expressions *fargs)
+ Objects *tiargs, Type *tthis, Expressions *fargs, const char **pMessage)
{
struct ParamDeduce
{
@@ -2018,6 +2023,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
Type *tthis;
Objects *tiargs;
Expressions *fargs;
+ const char **pMessage;
// result
Match *m;
int property; // 0: unintialized
@@ -2093,7 +2099,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
else
return 0; // MATCHnomatch
}
- MATCH mfa = tf->callMatch(tthis_fd, fargs);
+ MATCH mfa = tf->callMatch(tthis_fd, fargs, 0, pMessage);
//printf("test1: mfa = %d\n", mfa);
if (mfa > MATCHnomatch)
{
@@ -2180,8 +2186,12 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
int applyTemplate(TemplateDeclaration *td)
{
//printf("applyTemplate()\n");
- // skip duplicates
- if (td == td_best)
+ if (td->inuse)
+ {
+ td->error(loc, "recursive template expansion");
+ return 1;
+ }
+ if (td == td_best) // skip duplicates
return 0;
if (!sc)
@@ -2431,6 +2441,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
p.tthis = tthis;
p.tiargs = tiargs;
p.fargs = fargs;
+ p.pMessage = pMessage;
// result
p.m = m;
@@ -5165,6 +5176,16 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
* template X(T) {} // T => sa
*/
}
+ else if (ta && ta->ty != Tident)
+ {
+ /* Match any type that's not a TypeIdentifier to alias parameters,
+ * but prefer type parameter.
+ * template X(alias a) { } // a == ta
+ *
+ * TypeIdentifiers are excluded because they might be not yet resolved aliases.
+ */
+ m = MATCHconvert;
+ }
else
goto Lnomatch;
}
@@ -5485,12 +5506,15 @@ RootObject *TemplateValueParameter::defaultArg(Loc instLoc, Scope *sc)
if (e)
{
e = e->syntaxCopy();
+ unsigned olderrs = global.errors;
if ((e = expressionSemantic(e, sc)) == NULL)
return NULL;
if ((e = resolveProperties(sc, e)) == NULL)
return NULL;
e = e->resolveLoc(instLoc, sc); // use the instantiated loc
e = e->optimize(WANTvalue);
+ if (global.errors != olderrs)
+ e = new ErrorExp();
}
return e;
}
@@ -6049,6 +6073,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
if (ta)
{
//printf("type %s\n", ta->toChars());
+
// It might really be an Expression or an Alias
ta->resolve(loc, sc, &ea, &ta, &sa, (flags & 1) != 0);
if (ea) goto Lexpr;
@@ -6270,6 +6295,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
}
unsigned errs = global.errors;
+ TemplateDeclaration *td_last = NULL;
struct ParamBest
{
@@ -6291,7 +6317,11 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
TemplateDeclaration *td = s->isTemplateDeclaration();
if (!td)
return 0;
-
+ if (td->inuse)
+ {
+ td->error(ti->loc, "recursive template expansion");
+ return 1;
+ }
if (td == td_best) // skip duplicates
return 0;
@@ -6349,8 +6379,6 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
/* Since there can be multiple TemplateDeclaration's with the same
* name, look for the best match.
*/
- TemplateDeclaration *td_last = NULL;
-
OverloadSet *tovers = tempdecl->isOverloadSet();
size_t overs_dim = tovers ? tovers->a.length : 1;
for (size_t oi = 0; oi < overs_dim; oi++)
@@ -6359,7 +6387,9 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
p.td_best = NULL;
p.td_ambig = NULL;
p.m_best = MATCHnomatch;
- overloadApply(tovers ? tovers->a[oi] : tempdecl, &p, &ParamBest::fp);
+
+ Dsymbol *dstart = tovers ? tovers->a[oi] : tempdecl;
+ overloadApply(dstart, &p, &ParamBest::fp);
if (p.td_ambig)
{
@@ -6481,8 +6511,11 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag)
{
TemplateDeclaration *td = s->isTemplateDeclaration();
if (!td)
- {
return 0;
+ if (td->inuse)
+ {
+ td->error(ti->loc, "recursive template expansion");
+ return 1;
}
/* If any of the overloaded template declarations need inference,
@@ -7128,6 +7161,68 @@ void unSpeculative(Scope *sc, RootObject *o)
unSpeculative(sc, ti);
}
+/**
+ Returns: true if the instances' innards are discardable.
+
+ The idea of this function is to see if the template instantiation
+ can be 100% replaced with its eponymous member. All other members
+ can be discarded, even in the compiler to free memory (for example,
+ the template could be expanded in a region allocator, deemed trivial,
+ the end result copied back out independently and the entire region freed),
+ and can be elided entirely from the binary.
+
+ The current implementation affects code that generally looks like:
+
+ ---
+ template foo(args...) {
+ some_basic_type_or_string helper() { .... }
+ enum foo = helper();
+ }
+ ---
+
+ since it was the easiest starting point of implementation but it can and
+ should be expanded more later.
+*/
+static bool isDiscardable(TemplateInstance *ti)
+{
+ if (ti->aliasdecl == NULL)
+ return false;
+
+ VarDeclaration *v = ti->aliasdecl->isVarDeclaration();
+ if (v == NULL)
+ return false;
+
+ if (!(v->storage_class & STCmanifest))
+ return false;
+
+ // Currently only doing basic types here because it is the easiest proof-of-concept
+ // implementation with minimal risk of side effects, but it could likely be
+ // expanded to any type that already exists outside this particular instance.
+ if (!(v->type->equals(Type::tstring) || (v->type->isTypeBasic() != NULL)))
+ return false;
+
+ // Static ctors and dtors, even in an eponymous enum template, are still run,
+ // so if any of them are in here, we'd better not assume it is trivial lest
+ // we break useful code
+ for (size_t i = 0; i < ti->members->length; i++)
+ {
+ Dsymbol *member = (*ti->members)[i];
+ if (member->hasStaticCtorOrDtor())
+ return false;
+ if (member->isStaticDtorDeclaration())
+ return false;
+ if (member->isStaticCtorDeclaration())
+ return false;
+ }
+
+ // but if it passes through this gauntlet... it should be fine. D code will
+ // see only the eponymous member, outside stuff can never access it, even through
+ // reflection; the outside world ought to be none the wiser. Even dmd should be
+ // able to simply free the memory of everything except the final result.
+
+ return true;
+}
+
/***********************************************
* Returns true if this is not instantiated in non-root module, and
* is a part of non-speculative instantiatiation.
@@ -7137,38 +7232,6 @@ void unSpeculative(Scope *sc, RootObject *o)
*/
bool TemplateInstance::needsCodegen()
{
- // Now -allInst is just for the backward compatibility.
- if (global.params.allInst)
- {
- //printf("%s minst = %s, enclosing (%s)->isNonRoot = %d\n",
- // toPrettyChars(), minst ? minst->toChars() : NULL,
- // enclosing ? enclosing->toPrettyChars() : NULL, enclosing && enclosing->inNonRoot());
- if (enclosing)
- {
- // Bugzilla 14588: If the captured context is not a function
- // (e.g. class), the instance layout determination is guaranteed,
- // because the semantic/semantic2 pass will be executed
- // even for non-root instances.
- if (!enclosing->isFuncDeclaration())
- return true;
-
- // Bugzilla 14834: If the captured context is a function,
- // this excessive instantiation may cause ODR violation, because
- // -allInst and others doesn't guarantee the semantic3 execution
- // for that function.
-
- // If the enclosing is also an instantiated function,
- // we have to rely on the ancestor's needsCodegen() result.
- if (TemplateInstance *ti = enclosing->isInstantiated())
- return ti->needsCodegen();
-
- // Bugzilla 13415: If and only if the enclosing scope needs codegen,
- // this nested templates would also need code generation.
- return !enclosing->inNonRoot();
- }
- return true;
- }
-
if (!minst)
{
// If this is a speculative instantiation,
@@ -7185,6 +7248,10 @@ bool TemplateInstance::needsCodegen()
if (tinst && tinst->needsCodegen())
{
minst = tinst->minst; // cache result
+ if (global.params.allInst && minst)
+ {
+ return true;
+ }
assert(minst);
assert(minst->isRoot() || minst->rootImports());
return true;
@@ -7192,6 +7259,10 @@ bool TemplateInstance::needsCodegen()
if (tnext && (tnext->needsCodegen() || tnext->minst))
{
minst = tnext->minst; // cache result
+ if (global.params.allInst && minst)
+ {
+ return true;
+ }
assert(minst);
return minst->isRoot() || minst->rootImports();
}
@@ -7200,6 +7271,16 @@ bool TemplateInstance::needsCodegen()
return false;
}
+ if (global.params.allInst)
+ {
+ return true;
+ }
+
+ if (isDiscardable(this))
+ {
+ return false;
+ }
+
/* Even when this is reached to the codegen pass,
* a non-root nested template should not generate code,
* due to avoid ODR violation.
@@ -7221,14 +7302,7 @@ bool TemplateInstance::needsCodegen()
return false;
}
- /* The issue is that if the importee is compiled with a different -debug
- * setting than the importer, the importer may believe it exists
- * in the compiled importee when it does not, when the instantiation
- * is behind a conditional debug declaration.
- */
- // workaround for Bugzilla 11239
- if (global.params.useUnitTests ||
- global.params.debuglevel)
+ if (global.params.useUnitTests)
{
// Prefer instantiations from root modules, to maximize link-ability.
if (minst->isRoot())
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index c90392d..2592b38 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -43,110 +43,10 @@ VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
char *MODtoChars(MOD mod);
bool MODimplicitConv(MOD modfrom, MOD modto);
-MOD MODmerge(MOD mod1, MOD mod2);
void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
-
-/*************************************************************
- * Given var, we need to get the
- * right 'this' pointer if var is in an outer class, but our
- * existing 'this' pointer is in an inner class.
- * Input:
- * e1 existing 'this'
- * ad struct or class we need the correct 'this' for
- * var the specific member of ad we're accessing
- */
-
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
- Expression *e1, Declaration *var, int flag = 0)
-{
- //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
- L1:
- Type *t = e1->type->toBasetype();
- //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
-
- /* If e1 is not the 'this' pointer for ad
- */
- if (ad &&
- !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
- ((TypeStruct *)t->nextOf())->sym == ad)
- &&
- !(t->ty == Tstruct &&
- ((TypeStruct *)t)->sym == ad)
- )
- {
- ClassDeclaration *cd = ad->isClassDeclaration();
- ClassDeclaration *tcd = t->isClassHandle();
-
- /* e1 is the right this if ad is a base class of e1
- */
- if (!cd || !tcd ||
- !(tcd == cd || cd->isBaseOf(tcd, NULL))
- )
- {
- /* Only classes can be inner classes with an 'outer'
- * member pointing to the enclosing class instance
- */
- if (tcd && tcd->isNested())
- {
- /* e1 is the 'this' pointer for an inner class: tcd.
- * Rewrite it as the 'this' pointer for the outer class.
- */
-
- e1 = new DotVarExp(loc, e1, tcd->vthis);
- e1->type = tcd->vthis->type;
- e1->type = e1->type->addMod(t->mod);
- // Do not call checkNestedRef()
- //e1 = expressionSemantic(e1, sc);
-
- // Skip up over nested functions, and get the enclosing
- // class type.
- int n = 0;
- Dsymbol *s;
- for (s = tcd->toParent();
- s && s->isFuncDeclaration();
- s = s->toParent())
- {
- FuncDeclaration *f = s->isFuncDeclaration();
- if (f->vthis)
- {
- //printf("rewriting e1 to %s's this\n", f->toChars());
- n++;
- e1 = new VarExp(loc, f->vthis);
- }
- else
- {
- e1->error("need `this` of type %s to access member %s"
- " from static function %s",
- ad->toChars(), var->toChars(), f->toChars());
- e1 = new ErrorExp();
- return e1;
- }
- }
- if (s && s->isClassDeclaration())
- {
- e1->type = s->isClassDeclaration()->type;
- e1->type = e1->type->addMod(t->mod);
- if (n > 1)
- e1 = expressionSemantic(e1, sc);
- }
- else
- e1 = expressionSemantic(e1, sc);
- goto L1;
- }
-
- /* Can't find a path from e1 to ad
- */
- if (flag)
- return NULL;
- e1->error("this for %s needs to be type %s not type %s",
- var->toChars(), ad->toChars(), t->toChars());
- return new ErrorExp();
- }
- }
- return e1;
-}
+void toAutoQualChars(const char **result, Type *t1, Type *t2);
/*****************************************
* Determine if 'this' is available.
@@ -230,497 +130,6 @@ bool isNeedThisScope(Scope *sc, Declaration *d)
return true;
}
-/***************************************
- * Pull out any properties.
- */
-
-Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
-{
- //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
- Loc loc = e1->loc;
-
- OverloadSet *os;
- Dsymbol *s;
- Objects *tiargs;
- Type *tthis;
- if (e1->op == TOKdot)
- {
- DotExp *de = (DotExp *)e1;
- if (de->e2->op == TOKoverloadset)
- {
- tiargs = NULL;
- tthis = de->e1->type;
- os = ((OverExp *)de->e2)->vars;
- goto Los;
- }
- }
- else if (e1->op == TOKoverloadset)
- {
- tiargs = NULL;
- tthis = NULL;
- os = ((OverExp *)e1)->vars;
- Los:
- assert(os);
- FuncDeclaration *fd = NULL;
- if (e2)
- {
- e2 = expressionSemantic(e2, sc);
- if (e2->op == TOKerror)
- return new ErrorExp();
- e2 = resolveProperties(sc, e2);
-
- Expressions a;
- a.push(e2);
-
- for (size_t i = 0; i < os->a.length; i++)
- {
- FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
- if (f)
- {
- if (f->errors)
- return new ErrorExp();
- fd = f;
- assert(fd->type->ty == Tfunction);
- }
- }
- if (fd)
- {
- Expression *e = new CallExp(loc, e1, e2);
- return expressionSemantic(e, sc);
- }
- }
- {
- for (size_t i = 0; i < os->a.length; i++)
- {
- FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
- if (f)
- {
- if (f->errors)
- return new ErrorExp();
- fd = f;
- assert(fd->type->ty == Tfunction);
- TypeFunction *tf = (TypeFunction *)fd->type;
- if (!tf->isref && e2)
- goto Leproplvalue;
- }
- }
- if (fd)
- {
- Expression *e = new CallExp(loc, e1);
- if (e2)
- e = new AssignExp(loc, e, e2);
- return expressionSemantic(e, sc);
- }
- }
- if (e2)
- goto Leprop;
- }
- else if (e1->op == TOKdotti)
- {
- DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
- if (!dti->findTempDecl(sc))
- goto Leprop;
- if (!dti->ti->semanticTiargs(sc))
- goto Leprop;
- tiargs = dti->ti->tiargs;
- tthis = dti->e1->type;
- if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL)
- goto Los;
- if ((s = dti->ti->tempdecl) != NULL)
- goto Lfd;
- }
- else if (e1->op == TOKdottd)
- {
- DotTemplateExp *dte = (DotTemplateExp *)e1;
- s = dte->td;
- tiargs = NULL;
- tthis = dte->e1->type;
- goto Lfd;
- }
- else if (e1->op == TOKscope)
- {
- s = ((ScopeExp *)e1)->sds;
- TemplateInstance *ti = s->isTemplateInstance();
- if (ti && !ti->semanticRun && ti->tempdecl)
- {
- //assert(ti->needsTypeInference(sc));
- if (!ti->semanticTiargs(sc))
- goto Leprop;
- tiargs = ti->tiargs;
- tthis = NULL;
- if ((os = ti->tempdecl->isOverloadSet()) != NULL)
- goto Los;
- if ((s = ti->tempdecl) != NULL)
- goto Lfd;
- }
- }
- else if (e1->op == TOKtemplate)
- {
- s = ((TemplateExp *)e1)->td;
- tiargs = NULL;
- tthis = NULL;
- goto Lfd;
- }
- else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
- {
- DotVarExp *dve = (DotVarExp *)e1;
- s = dve->var->isFuncDeclaration();
- tiargs = NULL;
- tthis = dve->e1->type;
- goto Lfd;
- }
- else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
- {
- s = ((VarExp *)e1)->var->isFuncDeclaration();
- tiargs = NULL;
- tthis = NULL;
- Lfd:
- assert(s);
- if (e2)
- {
- e2 = expressionSemantic(e2, sc);
- if (e2->op == TOKerror)
- return new ErrorExp();
- e2 = resolveProperties(sc, e2);
-
- Expressions a;
- a.push(e2);
-
- FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
- if (fd && fd->type)
- {
- if (fd->errors)
- return new ErrorExp();
- assert(fd->type->ty == Tfunction);
- Expression *e = new CallExp(loc, e1, e2);
- return expressionSemantic(e, sc);
- }
- }
- {
- FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
- if (fd && fd->type)
- {
- if (fd->errors)
- return new ErrorExp();
- assert(fd->type->ty == Tfunction);
- TypeFunction *tf = (TypeFunction *)fd->type;
- if (!e2 || tf->isref)
- {
- Expression *e = new CallExp(loc, e1);
- if (e2)
- e = new AssignExp(loc, e, e2);
- return expressionSemantic(e, sc);
- }
- }
- }
- if (FuncDeclaration *fd = s->isFuncDeclaration())
- {
- // Keep better diagnostic message for invalid property usage of functions
- assert(fd->type->ty == Tfunction);
- Expression *e = new CallExp(loc, e1, e2);
- return expressionSemantic(e, sc);
- }
- if (e2)
- goto Leprop;
- }
- if (e1->op == TOKvar)
- {
- VarExp *ve = (VarExp *)e1;
- VarDeclaration *v = ve->var->isVarDeclaration();
- if (v && ve->checkPurity(sc, v))
- return new ErrorExp();
- }
- if (e2)
- return NULL;
-
- if (e1->type &&
- e1->op != TOKtype) // function type is not a property
- {
- /* Look for e1 being a lazy parameter; rewrite as delegate call
- */
- if (e1->op == TOKvar)
- {
- VarExp *ve = (VarExp *)e1;
-
- if (ve->var->storage_class & STClazy)
- {
- Expression *e = new CallExp(loc, e1);
- return expressionSemantic(e, sc);
- }
- }
- else if (e1->op == TOKdotvar)
- {
- // Check for reading overlapped pointer field in @safe code.
- if (checkUnsafeAccess(sc, e1, true, true))
- return new ErrorExp();
- }
- else if (e1->op == TOKdot)
- {
- e1->error("expression has no value");
- return new ErrorExp();
- }
- else if (e1->op == TOKcall)
- {
- CallExp *ce = (CallExp *)e1;
- // Check for reading overlapped pointer field in @safe code.
- if (checkUnsafeAccess(sc, ce->e1, true, true))
- return new ErrorExp();
- }
- }
-
- if (!e1->type)
- {
- error(loc, "cannot resolve type for %s", e1->toChars());
- e1 = new ErrorExp();
- }
- return e1;
-
-Leprop:
- error(loc, "not a property %s", e1->toChars());
- return new ErrorExp();
-
-Leproplvalue:
- error(loc, "%s is not an lvalue", e1->toChars());
- return new ErrorExp();
-}
-
-Expression *resolveProperties(Scope *sc, Expression *e)
-{
- //printf("resolveProperties(%s)\n", e->toChars());
-
- e = resolvePropertiesX(sc, e);
- if (e->checkRightThis(sc))
- return new ErrorExp();
- return e;
-}
-
-/******************************
- * Check the tail CallExp is really property function call.
- */
-static bool checkPropertyCall(Expression *e)
-{
- while (e->op == TOKcomma)
- e = ((CommaExp *)e)->e2;
-
- if (e->op == TOKcall)
- {
- CallExp *ce = (CallExp *)e;
- TypeFunction *tf;
- if (ce->f)
- {
- tf = (TypeFunction *)ce->f->type;
- /* If a forward reference to ce->f, try to resolve it
- */
- if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
- {
- dsymbolSemantic(ce->f, NULL);
- tf = (TypeFunction *)ce->f->type;
- }
- }
- else if (ce->e1->type->ty == Tfunction)
- tf = (TypeFunction *)ce->e1->type;
- else if (ce->e1->type->ty == Tdelegate)
- tf = (TypeFunction *)ce->e1->type->nextOf();
- else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction)
- tf = (TypeFunction *)ce->e1->type->nextOf();
- else
- assert(0);
- }
- return false;
-}
-
-/******************************
- * If e1 is a property function (template), resolve it.
- */
-
-Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
-{
- //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
- OverloadSet *os;
- FuncDeclaration *fd;
- TemplateDeclaration *td;
-
- if (e1->op == TOKdot)
- {
- DotExp *de = (DotExp *)e1;
- if (de->e2->op == TOKoverloadset)
- {
- os = ((OverExp *)de->e2)->vars;
- goto Los;
- }
- }
- else if (e1->op == TOKoverloadset)
- {
- os = ((OverExp *)e1)->vars;
- Los:
- assert(os);
- for (size_t i = 0; i < os->a.length; i++)
- {
- Dsymbol *s = os->a[i];
- fd = s->isFuncDeclaration();
- td = s->isTemplateDeclaration();
- if (fd)
- {
- if (((TypeFunction *)fd->type)->isproperty)
- return resolveProperties(sc, e1);
- }
- else if (td && td->onemember &&
- (fd = td->onemember->isFuncDeclaration()) != NULL)
- {
- if (((TypeFunction *)fd->type)->isproperty ||
- (fd->storage_class2 & STCproperty) ||
- (td->_scope->stc & STCproperty))
- {
- return resolveProperties(sc, e1);
- }
- }
- }
- }
- else if (e1->op == TOKdotti)
- {
- DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
- if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
- goto Ltd;
- }
- else if (e1->op == TOKdottd)
- {
- td = ((DotTemplateExp *)e1)->td;
- goto Ltd;
- }
- else if (e1->op == TOKscope)
- {
- Dsymbol *s = ((ScopeExp *)e1)->sds;
- TemplateInstance *ti = s->isTemplateInstance();
- if (ti && !ti->semanticRun && ti->tempdecl)
- {
- if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
- goto Ltd;
- }
- }
- else if (e1->op == TOKtemplate)
- {
- td = ((TemplateExp *)e1)->td;
- Ltd:
- assert(td);
- if (td->onemember &&
- (fd = td->onemember->isFuncDeclaration()) != NULL)
- {
- if (((TypeFunction *)fd->type)->isproperty ||
- (fd->storage_class2 & STCproperty) ||
- (td->_scope->stc & STCproperty))
- {
- return resolveProperties(sc, e1);
- }
- }
- }
- else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
- {
- DotVarExp *dve = (DotVarExp *)e1;
- fd = dve->var->isFuncDeclaration();
- goto Lfd;
- }
- else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
- (sc->intypeof || !((VarExp *)e1)->var->needThis()))
- {
- fd = ((VarExp *)e1)->var->isFuncDeclaration();
- Lfd:
- assert(fd);
- if (((TypeFunction *)fd->type)->isproperty)
- return resolveProperties(sc, e1);
- }
- return e1;
-}
-
-
-// TODO: merge with Scope::search::searchScopes()
-static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
-{
- Dsymbol *s = NULL;
- for (Scope *scx = sc; scx; scx = scx->enclosing)
- {
- if (!scx->scopesym)
- continue;
- if (scx->scopesym->isModule())
- flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
- s = scx->scopesym->search(loc, ident, flags);
- if (s)
- {
- // overload set contains only module scope symbols.
- if (s->isOverloadSet())
- break;
- // selective/renamed imports also be picked up
- if (AliasDeclaration *ad = s->isAliasDeclaration())
- {
- if (ad->_import)
- break;
- }
- // See only module scope symbols for UFCS target.
- Dsymbol *p = s->toParent2();
- if (p && p->isModule())
- break;
- }
- s = NULL;
-
- // Stop when we hit a module, but keep going if that is not just under the global scope
- if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing))
- break;
- }
- return s;
-}
-
-/******************************
- * Find symbol in accordance with the UFCS name look up rule
- */
-
-static Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
-{
- //printf("searchUFCS(ident = %s)\n", ident->toChars());
- Loc loc = ue->loc;
- int flags = 0;
- Dsymbol *s = NULL;
-
- if (sc->flags & SCOPEignoresymbolvisibility)
- flags |= IgnoreSymbolVisibility;
-
- // First look in local scopes
- s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
- if (!s)
- {
- // Second look in imported modules
- s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
- }
-
- if (!s)
- return ue->e1->type->Type::getProperty(loc, ident, 0);
-
- FuncDeclaration *f = s->isFuncDeclaration();
- if (f)
- {
- TemplateDeclaration *td = getFuncTemplateDecl(f);
- if (td)
- {
- if (td->overroot)
- td = td->overroot;
- s = td;
- }
- }
-
- if (ue->op == TOKdotti)
- {
- DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue;
- TemplateInstance *ti = new TemplateInstance(loc, s->ident);
- ti->tiargs = dti->ti->tiargs; // for better diagnostic message
- if (!ti->updateTempDecl(sc, s))
- return new ErrorExp();
- return new ScopeExp(loc, ti);
- }
- else
- {
- //printf("-searchUFCS() %s\n", s->toChars());
- return new DsymbolExp(loc, s);
- }
-}
-
/******************************
* check e is exp.opDispatch!(tiargs) or not
* It's used to switch to UFCS the semantic analysis path
@@ -732,220 +141,6 @@ bool isDotOpDispatch(Expression *e)
((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch;
}
-/******************************
- * Pull out callable entity with UFCS.
- */
-
-Expression *resolveUFCS(Scope *sc, CallExp *ce)
-{
- Loc loc = ce->loc;
- Expression *eleft;
- Expression *e;
-
- if (ce->e1->op == TOKdotid)
- {
- DotIdExp *die = (DotIdExp *)ce->e1;
- Identifier *ident = die->ident;
-
- Expression *ex = semanticX(die, sc);
- if (ex != die)
- {
- ce->e1 = ex;
- return NULL;
- }
- eleft = die->e1;
-
- Type *t = eleft->type->toBasetype();
- if (t->ty == Tarray || t->ty == Tsarray ||
- t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid))
- {
- /* Built-in types and arrays have no callable properties, so do shortcut.
- * It is necessary in: e.init()
- */
- }
- else if (t->ty == Taarray)
- {
- if (ident == Id::remove)
- {
- /* Transform:
- * aa.remove(arg) into delete aa[arg]
- */
- if (!ce->arguments || ce->arguments->length != 1)
- {
- ce->error("expected key as argument to aa.remove()");
- return new ErrorExp();
- }
- if (!eleft->type->isMutable())
- {
- ce->error("cannot remove key from %s associative array %s",
- MODtoChars(t->mod), eleft->toChars());
- return new ErrorExp();
- }
- Expression *key = (*ce->arguments)[0];
- key = expressionSemantic(key, sc);
- key = resolveProperties(sc, key);
-
- TypeAArray *taa = (TypeAArray *)t;
- key = key->implicitCastTo(sc, taa->index);
-
- if (key->checkValue())
- return new ErrorExp();
-
- semanticTypeInfo(sc, taa->index);
-
- return new RemoveExp(loc, eleft, key);
- }
- }
- else
- {
- if (Expression *ey = semanticY(die, sc, 1))
- {
- if (ey->op == TOKerror)
- return ey;
- ce->e1 = ey;
- if (isDotOpDispatch(ey))
- {
- unsigned errors = global.startGagging();
- e = expressionSemantic(ce->syntaxCopy(), sc);
- if (!global.endGagging(errors))
- return e;
- /* fall down to UFCS */
- }
- else
- return NULL;
- }
- }
- e = searchUFCS(sc, die, ident);
- }
- else if (ce->e1->op == TOKdotti)
- {
- DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
- if (Expression *ey = semanticY(dti, sc, 1))
- {
- ce->e1 = ey;
- return NULL;
- }
- eleft = dti->e1;
- e = searchUFCS(sc, dti, dti->ti->name);
- }
- else
- return NULL;
-
- // Rewrite
- ce->e1 = e;
- if (!ce->arguments)
- ce->arguments = new Expressions();
- ce->arguments->shift(eleft);
-
- return NULL;
-}
-
-/******************************
- * Pull out property with UFCS.
- */
-
-Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
-{
- Loc loc = e1->loc;
- Expression *eleft;
- Expression *e;
-
- if (e1->op == TOKdotid)
- {
- DotIdExp *die = (DotIdExp *)e1;
- eleft = die->e1;
- e = searchUFCS(sc, die, die->ident);
- }
- else if (e1->op == TOKdotti)
- {
- DotTemplateInstanceExp *dti;
- dti = (DotTemplateInstanceExp *)e1;
- eleft = dti->e1;
- e = searchUFCS(sc, dti, dti->ti->name);
- }
- else
- return NULL;
-
- if (e == NULL)
- return NULL;
-
- // Rewrite
- if (e2)
- {
- // run semantic without gagging
- e2 = expressionSemantic(e2, sc);
-
- /* f(e1) = e2
- */
- Expression *ex = e->copy();
- Expressions *a1 = new Expressions();
- a1->setDim(1);
- (*a1)[0] = eleft;
- ex = new CallExp(loc, ex, a1);
- ex = trySemantic(ex, sc);
-
- /* f(e1, e2)
- */
- Expressions *a2 = new Expressions();
- a2->setDim(2);
- (*a2)[0] = eleft;
- (*a2)[1] = e2;
- e = new CallExp(loc, e, a2);
- if (ex)
- { // if fallback setter exists, gag errors
- e = trySemantic(e, sc);
- if (!e)
- { checkPropertyCall(ex);
- ex = new AssignExp(loc, ex, e2);
- return expressionSemantic(ex, sc);
- }
- }
- else
- { // strict setter prints errors if fails
- e = expressionSemantic(e, sc);
- }
- checkPropertyCall(e);
- return e;
- }
- else
- {
- /* f(e1)
- */
- Expressions *arguments = new Expressions();
- arguments->setDim(1);
- (*arguments)[0] = eleft;
- e = new CallExp(loc, e, arguments);
- e = expressionSemantic(e, sc);
- checkPropertyCall(e);
- return expressionSemantic(e, sc);
- }
-}
-
-/******************************
- * Perform semantic() on an array of Expressions.
- */
-
-bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
-{
- bool err = false;
- if (exps)
- {
- for (size_t i = 0; i < exps->length; i++)
- {
- Expression *e = (*exps)[i];
- if (e)
- {
- e = expressionSemantic(e, sc);
- if (e->op == TOKerror)
- err = true;
- if (preserveErrors || e->op != TOKerror)
- (*exps)[i] = e;
- }
- }
- }
- return err;
-}
-
/****************************************
* Expand tuples.
* Input:
@@ -1065,120 +260,6 @@ int expandAliasThisTuples(Expressions *exps, size_t starti)
}
/****************************************
- * The common type is determined by applying ?: to each pair.
- * Output:
- * exps[] properties resolved, implicitly cast to common type, rewritten in place
- * *pt if pt is not NULL, set to the common type
- * Returns:
- * true a semantic error was detected
- */
-
-bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
-{
- /* Still have a problem with:
- * ubyte[][] = [ cast(ubyte[])"hello", [1]];
- * which works if the array literal is initialized top down with the ubyte[][]
- * type, but fails with this function doing bottom up typing.
- */
- //printf("arrayExpressionToCommonType()\n");
- IntegerExp integerexp(0);
- CondExp condexp(Loc(), &integerexp, NULL, NULL);
-
- Type *t0 = NULL;
- Expression *e0 = NULL; // dead-store to prevent spurious warning
- size_t j0 = ~0; // dead-store to prevent spurious warning
- bool foundType = false;
-
- for (size_t i = 0; i < exps->length; i++)
- {
- Expression *e = (*exps)[i];
- if (!e)
- continue;
-
- e = resolveProperties(sc, e);
- if (!e->type)
- {
- e->error("%s has no value", e->toChars());
- t0 = Type::terror;
- continue;
- }
- if (e->op == TOKtype)
- {
- foundType = true; // do not break immediately, there might be more errors
- e->checkValue(); // report an error "type T has no value"
- t0 = Type::terror;
- continue;
- }
- if (e->type->ty == Tvoid)
- {
- // void expressions do not concur to the determination of the common
- // type.
- continue;
- }
- if (checkNonAssignmentArrayOp(e))
- {
- t0 = Type::terror;
- continue;
- }
-
- e = doCopyOrMove(sc, e);
-
- if (!foundType && t0 && !t0->equals(e->type))
- {
- /* This applies ?: to merge the types. It's backwards;
- * ?: should call this function to merge types.
- */
- condexp.type = NULL;
- condexp.e1 = e0;
- condexp.e2 = e;
- condexp.loc = e->loc;
- Expression *ex = expressionSemantic(&condexp, sc);
- if (ex->op == TOKerror)
- e = ex;
- else
- {
- (*exps)[j0] = condexp.e1;
- e = condexp.e2;
- }
- }
- j0 = i;
- e0 = e;
- t0 = e->type;
- if (e->op != TOKerror)
- (*exps)[i] = e;
- }
-
- if (!t0)
- t0 = Type::tvoid; // [] is typed as void[]
- else if (t0->ty != Terror)
- {
- for (size_t i = 0; i < exps->length; i++)
- {
- Expression *e = (*exps)[i];
- if (!e)
- continue;
-
- e = e->implicitCastTo(sc, t0);
- //assert(e->op != TOKerror);
- if (e->op == TOKerror)
- {
- /* Bugzilla 13024: a workaround for the bug in typeMerge -
- * it should paint e1 and e2 by deduced common type,
- * but doesn't in this particular case.
- */
- t0 = Type::terror;
- break;
- }
- (*exps)[i] = e;
- }
- }
- if (pt)
- *pt = t0;
-
- return (t0 == Type::terror);
-}
-
-/****************************************
* Get TemplateDeclaration enclosing FuncDeclaration.
*/
@@ -1249,27 +330,6 @@ Expression *valueNoDtor(Expression *e)
return e;
}
-/********************************************
- * Issue an error if default construction is disabled for type t.
- * Default construction is required for arrays and 'out' parameters.
- * Returns:
- * true an error was issued
- */
-bool checkDefCtor(Loc loc, Type *t)
-{
- t = t->baseElemOf();
- if (t->ty == Tstruct)
- {
- StructDeclaration *sd = ((TypeStruct *)t)->sym;
- if (sd->noDefaultCtor)
- {
- sd->error(loc, "default construction is disabled");
- return true;
- }
- }
- return false;
-}
-
/*********************************************
* If e is an instance of a struct, and that struct has a copy constructor,
* rewrite e as:
@@ -1322,648 +382,6 @@ Expression *doCopyOrMove(Scope *sc, Expression *e)
return e;
}
-/****************************************
- * Now that we know the exact type of the function we're calling,
- * the arguments[] need to be adjusted:
- * 1. implicitly convert argument to the corresponding parameter type
- * 2. add default arguments for any missing arguments
- * 3. do default promotions on arguments corresponding to ...
- * 4. add hidden _arguments[] argument
- * 5. call copy constructor for struct value arguments
- * Input:
- * tf type of the function
- * fd the function being called, NULL if called indirectly
- * Output:
- * *prettype return type of function
- * *peprefix expression to execute before arguments[] are evaluated, NULL if none
- * Returns:
- * true errors happened
- */
-
-bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
- Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
-{
- //printf("functionParameters()\n");
- assert(arguments);
- assert(fd || tf->next);
- size_t nargs = arguments ? arguments->length : 0;
- size_t nparams = tf->parameterList.length();
- unsigned olderrors = global.errors;
- bool err = false;
- *prettype = Type::terror;
- Expression *eprefix = NULL;
- *peprefix = NULL;
-
- if (nargs > nparams && tf->parameterList.varargs == VARARGnone)
- {
- error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
- return true;
- }
-
- // If inferring return type, and semantic3() needs to be run if not already run
- if (!tf->next && fd->inferRetType)
- {
- fd->functionSemantic();
- }
- else if (fd && fd->parent)
- {
- TemplateInstance *ti = fd->parent->isTemplateInstance();
- if (ti && ti->tempdecl)
- {
- fd->functionSemantic3();
- }
- }
- bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
-
- size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
-
- /* If the function return type has wildcards in it, we'll need to figure out the actual type
- * based on the actual argument types.
- */
- MOD wildmatch = 0;
- if (tthis && tf->isWild() && !isCtorCall)
- {
- Type *t = tthis;
- if (t->isImmutable())
- wildmatch = MODimmutable;
- else if (t->isWildConst())
- wildmatch = MODwildconst;
- else if (t->isWild())
- wildmatch = MODwild;
- else if (t->isConst())
- wildmatch = MODconst;
- else
- wildmatch = MODmutable;
- }
-
- int done = 0;
- for (size_t i = 0; i < n; i++)
- {
- Expression *arg;
-
- if (i < nargs)
- arg = (*arguments)[i];
- else
- arg = NULL;
-
- if (i < nparams)
- {
- Parameter *p = tf->parameterList[i];
-
- if (!arg)
- {
- if (!p->defaultArg)
- {
- if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
- goto L2;
- error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
- return true;
- }
- arg = p->defaultArg;
- arg = inlineCopy(arg, sc);
- // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
- arg = arg->resolveLoc(loc, sc);
- arguments->push(arg);
- nargs++;
- }
-
- if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
- {
- //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
- {
- MATCH m;
- if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
- {
- if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
- goto L2;
- else if (nargs != nparams)
- { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
- return true;
- }
- goto L1;
- }
- }
- L2:
- Type *tb = p->type->toBasetype();
- Type *tret = p->isLazyArray();
- switch (tb->ty)
- {
- case Tsarray:
- case Tarray:
- {
- /* Create a static array variable v of type arg->type:
- * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
- *
- * The array literal in the initializer of the hidden variable
- * is now optimized. See Bugzilla 2356.
- */
- Type *tbn = ((TypeArray *)tb)->next;
-
- Expressions *elements = new Expressions();
- elements->setDim(nargs - i);
- for (size_t u = 0; u < elements->length; u++)
- {
- Expression *a = (*arguments)[i + u];
- if (tret && a->implicitConvTo(tret))
- {
- a = a->implicitCastTo(sc, tret);
- a = a->optimize(WANTvalue);
- a = toDelegate(a, a->type, sc);
- }
- else
- a = a->implicitCastTo(sc, tbn);
- (*elements)[u] = a;
- }
- // Bugzilla 14395: Convert to a static array literal, or its slice.
- arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
- if (tb->ty == Tarray)
- {
- arg = new SliceExp(loc, arg, NULL, NULL);
- arg->type = p->type;
- }
- break;
- }
- case Tclass:
- {
- /* Set arg to be:
- * new Tclass(arg0, arg1, ..., argn)
- */
- Expressions *args = new Expressions();
- args->setDim(nargs - i);
- for (size_t u = i; u < nargs; u++)
- (*args)[u - i] = (*arguments)[u];
- arg = new NewExp(loc, NULL, NULL, p->type, args);
- break;
- }
- default:
- if (!arg)
- {
- error(loc, "not enough arguments");
- return true;
- }
- break;
- }
- arg = expressionSemantic(arg, sc);
- //printf("\targ = '%s'\n", arg->toChars());
- arguments->setDim(i + 1);
- (*arguments)[i] = arg;
- nargs = i + 1;
- done = 1;
- }
-
- L1:
- if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
- {
- bool isRef = (p->storageClass & (STCref | STCout)) != 0;
- if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
- {
- if (wildmatch)
- wildmatch = MODmerge(wildmatch, wm);
- else
- wildmatch = wm;
- //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
- }
- }
- }
- if (done)
- break;
- }
- if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
- tf->next->hasWild() &&
- (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
- {
- if (fd)
- {
- /* If the called function may return the reference to
- * outer inout data, it should be rejected.
- *
- * void foo(ref inout(int) x) {
- * ref inout(int) bar(inout(int)) { return x; }
- * struct S { ref inout(int) bar() inout { return x; } }
- * bar(int.init) = 1; // bad!
- * S().bar() = 1; // bad!
- * }
- */
- Dsymbol *s = NULL;
- if (fd->isThis() || fd->isNested())
- s = fd->toParent2();
- for (; s; s = s->toParent2())
- {
- if (AggregateDeclaration *ad = s->isAggregateDeclaration())
- {
- if (ad->isNested())
- continue;
- break;
- }
- if (FuncDeclaration *ff = s->isFuncDeclaration())
- {
- if (((TypeFunction *)ff->type)->iswild)
- goto Linouterr;
-
- if (ff->isNested() || ff->isThis())
- continue;
- }
- break;
- }
- }
- else if (tf->isWild())
- {
- Linouterr:
- const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
- error(loc, "modify inout to %s is not allowed inside inout function", s);
- return true;
- }
- }
-
- assert(nargs >= nparams);
- for (size_t i = 0; i < nargs; i++)
- {
- Expression *arg = (*arguments)[i];
- assert(arg);
- if (i < nparams)
- {
- Parameter *p = tf->parameterList[i];
-
- if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
- {
- Type *tprm = p->type;
- if (p->type->hasWild())
- tprm = p->type->substWildTo(wildmatch);
- if (!tprm->equals(arg->type))
- {
- //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
- arg = arg->implicitCastTo(sc, tprm);
- arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
- }
- }
- if (p->storageClass & STCref)
- {
- arg = arg->toLvalue(sc, arg);
-
- // Look for mutable misaligned pointer, etc., in @safe mode
- err |= checkUnsafeAccess(sc, arg, false, true);
- }
- else if (p->storageClass & STCout)
- {
- Type *t = arg->type;
- if (!t->isMutable() || !t->isAssignable()) // check blit assignable
- {
- arg->error("cannot modify struct %s with immutable members", arg->toChars());
- err = true;
- }
- else
- {
- // Look for misaligned pointer, etc., in @safe mode
- err |= checkUnsafeAccess(sc, arg, false, true);
- err |= checkDefCtor(arg->loc, t); // t must be default constructible
- }
- arg = arg->toLvalue(sc, arg);
- }
- else if (p->storageClass & STClazy)
- {
- // Convert lazy argument to a delegate
- if (p->type->ty == Tvoid)
- arg = toDelegate(arg, p->type, sc);
- else
- arg = toDelegate(arg, arg->type, sc);
- }
-
- //printf("arg: %s\n", arg->toChars());
- //printf("type: %s\n", arg->type->toChars());
- if (tf->parameterEscapes(p))
- {
- /* Argument value can escape from the called function.
- * Check arg to see if it matters.
- */
- if (global.params.vsafe)
- err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
- }
- else
- {
- /* Argument value cannot escape from the called function.
- */
- Expression *a = arg;
- if (a->op == TOKcast)
- a = ((CastExp *)a)->e1;
-
- if (a->op == TOKfunction)
- {
- /* Function literals can only appear once, so if this
- * appearance was scoped, there cannot be any others.
- */
- FuncExp *fe = (FuncExp *)a;
- fe->fd->tookAddressOf = 0;
- }
- else if (a->op == TOKdelegate)
- {
- /* For passing a delegate to a scoped parameter,
- * this doesn't count as taking the address of it.
- * We only worry about 'escaping' references to the function.
- */
- DelegateExp *de = (DelegateExp *)a;
- if (de->e1->op == TOKvar)
- { VarExp *ve = (VarExp *)de->e1;
- FuncDeclaration *f = ve->var->isFuncDeclaration();
- if (f)
- { f->tookAddressOf--;
- //printf("tookAddressOf = %d\n", f->tookAddressOf);
- }
- }
- }
- }
- arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
- }
- else
- {
- // These will be the trailing ... arguments
-
- // If not D linkage, do promotions
- if (tf->linkage != LINKd)
- {
- // Promote bytes, words, etc., to ints
- arg = integralPromotions(arg, sc);
-
- // Promote floats to doubles
- switch (arg->type->ty)
- {
- case Tfloat32:
- arg = arg->castTo(sc, Type::tfloat64);
- break;
-
- case Timaginary32:
- arg = arg->castTo(sc, Type::timaginary64);
- break;
- }
-
- if (tf->parameterList.varargs == VARARGvariadic)
- {
- const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
- if (arg->type->ty == Tarray)
- {
- arg->error("cannot pass dynamic arrays to %s vararg functions", p);
- err = true;
- }
- if (arg->type->ty == Tsarray)
- {
- arg->error("cannot pass static arrays to %s vararg functions", p);
- err = true;
- }
- }
- }
-
- // Do not allow types that need destructors
- if (arg->type->needsDestruction())
- {
- arg->error("cannot pass types that need destruction as variadic arguments");
- err = true;
- }
-
- // Convert static arrays to dynamic arrays
- // BUG: I don't think this is right for D2
- Type *tb = arg->type->toBasetype();
- if (tb->ty == Tsarray)
- {
- TypeSArray *ts = (TypeSArray *)tb;
- Type *ta = ts->next->arrayOf();
- if (ts->size(arg->loc) == 0)
- arg = new NullExp(arg->loc, ta);
- else
- arg = arg->castTo(sc, ta);
- }
- if (tb->ty == Tstruct)
- {
- //arg = callCpCtor(sc, arg);
- }
-
- // Give error for overloaded function addresses
- if (arg->op == TOKsymoff)
- { SymOffExp *se = (SymOffExp *)arg;
- if (se->hasOverloads &&
- !se->var->isFuncDeclaration()->isUnique())
- { arg->error("function %s is overloaded", arg->toChars());
- err = true;
- }
- }
- if (arg->checkValue())
- err = true;
- arg = arg->optimize(WANTvalue);
- }
- (*arguments)[i] = arg;
- }
-
- /* Remaining problems:
- * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
- * implemented by calling a function) we'll defer this for now.
- * 2. value structs (or static arrays of them) that need to be copy constructed
- * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
- * function gets called (functions normally destroy their parameters)
- * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
- * up properly. Pushing arguments on the stack then cannot fail.
- */
- if (1)
- {
- /* TODO: tackle problem 1)
- */
- const bool leftToRight = true; // TODO: something like !fd.isArrayOp
- if (!leftToRight)
- assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
-
- const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
- const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
- const ptrdiff_t step = (leftToRight ? 1 : -1);
-
- /* Compute indices of last throwing argument and first arg needing destruction.
- * Used to not set up destructors unless an arg needs destruction on a throw
- * in a later argument.
- */
- ptrdiff_t lastthrow = -1;
- ptrdiff_t firstdtor = -1;
- for (ptrdiff_t i = start; i != end; i += step)
- {
- Expression *arg = (*arguments)[i];
- if (canThrow(arg, sc->func, false))
- lastthrow = i;
- if (firstdtor == -1 && arg->type->needsDestruction())
- {
- Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
- if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
- firstdtor = i;
- }
- }
-
- /* Does problem 3) apply to this call?
- */
- const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
- && (lastthrow - firstdtor) * step > 0);
-
- /* If so, initialize 'eprefix' by declaring the gate
- */
- VarDeclaration *gate = NULL;
- if (needsPrefix)
- {
- // eprefix => bool __gate [= false]
- Identifier *idtmp = Identifier::generateId("__gate");
- gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
- gate->storage_class |= STCtemp | STCctfe | STCvolatile;
- dsymbolSemantic(gate, sc);
-
- Expression *ae = new DeclarationExp(loc, gate);
- eprefix = expressionSemantic(ae, sc);
- }
-
- for (ptrdiff_t i = start; i != end; i += step)
- {
- Expression *arg = (*arguments)[i];
-
- Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
- const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
- const bool isLazy = (parameter && (parameter->storageClass & STClazy));
-
- /* Skip lazy parameters
- */
- if (isLazy)
- continue;
-
- /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
- * Declare a temporary variable for this arg and append that declaration to 'eprefix',
- * which will implicitly take care of potential problem 2) for this arg.
- * 'eprefix' will therefore finally contain all args up to and including the last
- * potentially throwing arg, excluding all lazy parameters.
- */
- if (gate)
- {
- const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
-
- /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
- */
- VarDeclaration *tmp = copyToTemp(0,
- needsDtor ? "__pfx" : "__pfy",
- !isRef ? arg : arg->addressOf());
- dsymbolSemantic(tmp, sc);
-
- /* Modify the destructor so it only runs if gate==false, i.e.,
- * only if there was a throw while constructing the args
- */
- if (!needsDtor)
- {
- if (tmp->edtor)
- {
- assert(i == lastthrow);
- tmp->edtor = NULL;
- }
- }
- else
- {
- // edtor => (__gate || edtor)
- assert(tmp->edtor);
- Expression *e = tmp->edtor;
- e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
- tmp->edtor = expressionSemantic(e, sc);
- //printf("edtor: %s\n", tmp->edtor->toChars());
- }
-
- // eprefix => (eprefix, auto __pfx/y = arg)
- DeclarationExp *ae = new DeclarationExp(loc, tmp);
- eprefix = Expression::combine(eprefix, expressionSemantic(ae, sc));
-
- // arg => __pfx/y
- arg = new VarExp(loc, tmp);
- arg = expressionSemantic(arg, sc);
- if (isRef)
- {
- arg = new PtrExp(loc, arg);
- arg = expressionSemantic(arg, sc);
- }
-
- /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
- * i.e., disable the dtors right after constructing the last throwing arg.
- * From now on, the callee will take care of destructing the args because
- * the args are implicitly moved into function parameters.
- *
- * Set gate to null to let the next iterations know they don't need to
- * append to eprefix anymore.
- */
- if (i == lastthrow)
- {
- Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
- eprefix = Expression::combine(eprefix, expressionSemantic(e, sc));
- gate = NULL;
- }
- }
- else
- {
- /* No gate, no prefix to append to.
- * Handle problem 2) by calling the copy constructor for value structs
- * (or static arrays of them) if appropriate.
- */
- Type *tv = arg->type->baseElemOf();
- if (!isRef && tv->ty == Tstruct)
- arg = doCopyOrMove(sc, arg);
- }
-
- (*arguments)[i] = arg;
- }
- }
- //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
-
- // If D linkage and variadic, add _arguments[] as first argument
- if (tf->isDstyleVariadic())
- {
- assert(arguments->length >= nparams);
-
- Parameters *args = new Parameters;
- args->setDim(arguments->length - nparams);
- for (size_t i = 0; i < arguments->length - nparams; i++)
- {
- Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL, NULL);
- (*args)[i] = arg;
- }
-
- TypeTuple *tup = new TypeTuple(args);
- Expression *e = new TypeidExp(loc, tup);
- e = expressionSemantic(e, sc);
- arguments->insert(0, e);
- }
-
- Type *tret = tf->next;
- if (isCtorCall)
- {
- //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
- // wildmatch, tf->isWild(), fd->isolateReturn());
- if (!tthis)
- {
- assert(sc->intypeof || global.errors);
- tthis = fd->isThis()->type->addMod(fd->type->mod);
- }
- if (tf->isWild() && !fd->isolateReturn())
- {
- if (wildmatch)
- tret = tret->substWildTo(wildmatch);
- int offset;
- if (!tret->implicitConvTo(tthis) &&
- !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
- {
- const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
- const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
- ::error(loc, "inout constructor %s creates%s object, not%s",
- fd->toPrettyChars(), s1, s2);
- err = true;
- }
- }
- tret = tthis;
- }
- else if (wildmatch && tret)
- {
- /* Adjust function return type based on wildmatch
- */
- //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
- tret = tret->substWildTo(wildmatch);
- }
- *prettype = tret;
- *peprefix = eprefix;
- return (err || olderrors != global.errors);
-}
-
/******************************** Expression **************************/
Expression::Expression(Loc loc, TOK op, int size)
@@ -5288,8 +3706,10 @@ MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
}
else if (!flag)
{
+ const char *ts[2];
+ toAutoQualChars(ts, tx, to);
error("cannot implicitly convert expression (%s) of type %s to %s",
- toChars(), tx->toChars(), to->toChars());
+ toChars(), ts[0], ts[1]);
}
return m;
}
@@ -5644,11 +4064,17 @@ Expression *BinExp::incompatibleTypes()
error("incompatible types for ((%s) %s (%s)): cannot use `%s` with types",
e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
}
+ else if (e1->type->equals(e2->type))
+ {
+ error("incompatible types for ((%s) %s (%s)): both operands are of type `%s`",
+ e1->toChars(), Token::toChars(thisOp), e2->toChars(), e1->type->toChars());
+ }
else
{
+ const char *ts[2];
+ toAutoQualChars(ts, e1->type, e2->type);
error("incompatible types for ((%s) %s (%s)): `%s` and `%s`",
- e1->toChars(), Token::toChars(thisOp), e2->toChars(),
- e1->type->toChars(), e2->type->toChars());
+ e1->toChars(), Token::toChars(thisOp), e2->toChars(), ts[0], ts[1]);
}
return new ErrorExp();
}
@@ -5693,9 +4119,36 @@ Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *)
/************************************************************/
-CompileExp::CompileExp(Loc loc, Expression *e)
- : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
+CompileExp::CompileExp(Loc loc, Expressions *exps)
+ : Expression(loc, TOKmixin, sizeof(CompileExp))
+{
+ this->exps = exps;
+}
+
+Expression *CompileExp::syntaxCopy()
{
+ return new CompileExp(loc, arraySyntaxCopy(exps));
+}
+
+bool CompileExp::equals(RootObject *o)
+{
+ if (this == o)
+ return true;
+ if (o && o->dyncast() == DYNCAST_EXPRESSION && ((Expression *)o)->op == TOKmixin)
+ {
+ CompileExp *ce = (CompileExp *)o;
+ if (exps->length != ce->exps->length)
+ return false;
+ for (size_t i = 0; i < exps->length; i++)
+ {
+ Expression *e1 = (*exps)[i];
+ Expression *e2 = (*ce->exps)[i];
+ if (e1 != e2 && (!e1 || !e2 || !e1->equals(e2)))
+ return false;
+ }
+ return true;
+ }
+ return false;
}
/************************************************************/
@@ -6362,64 +4815,6 @@ ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
{
}
-Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
-{ Expression *e;
-
- switch (op)
- {
- case TOKaddass: e = new AddExp(loc, e1, e2); break;
- case TOKminass: e = new MinExp(loc, e1, e2); break;
- case TOKmulass: e = new MulExp(loc, e1, e2); break;
- case TOKdivass: e = new DivExp(loc, e1, e2); break;
- case TOKmodass: e = new ModExp(loc, e1, e2); break;
- case TOKandass: e = new AndExp(loc, e1, e2); break;
- case TOKorass: e = new OrExp (loc, e1, e2); break;
- case TOKxorass: e = new XorExp(loc, e1, e2); break;
- case TOKshlass: e = new ShlExp(loc, e1, e2); break;
- case TOKshrass: e = new ShrExp(loc, e1, e2); break;
- case TOKushrass: e = new UshrExp(loc, e1, e2); break;
- default: assert(0);
- }
- return e;
-}
-
-/*********************
- * Rewrite:
- * array.length op= e2
- * as:
- * array.length = array.length op e2
- * or:
- * auto tmp = &array;
- * (*tmp).length = (*tmp).length op e2
- */
-
-Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
-{
- Expression *e;
-
- assert(exp->e1->op == TOKarraylength);
- ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
- if (ale->e1->op == TOKvar)
- {
- e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
- e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
- }
- else
- {
- /* auto tmp = &array;
- * (*tmp).length = (*tmp).length op e2
- */
- VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
-
- Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
- Expression *elvalue = e1->syntaxCopy();
- e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
- e = new AssignExp(exp->loc, elvalue, e);
- e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
- }
- return e;
-}
-
/*********************** IntervalExp ********************************/
// Mainly just a placeholder
@@ -7248,203 +5643,6 @@ Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc)
return e;
}
-/****************************************************************/
-
-Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
-{
- Expression *e0;
- Expression *e1 = Expression::extractLast(ue->e1, &e0);
- // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
-
- if (!isTrivialExp(e1))
- {
- /* Even if opDollar is needed, 'e1' should be evaluate only once. So
- * Rewrite:
- * e1.opIndex( ... use of $ ... )
- * e1.opSlice( ... use of $ ... )
- * as:
- * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
- * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
- */
- e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
- assert(e1->op == TOKvar);
- VarExp *ve = (VarExp *)e1;
- ve->var->storage_class |= STCexptemp; // lifetime limited to expression
- }
- ue->e1 = e1;
- return e0;
-}
-
-/**************************************
- * Runs semantic on ae->arguments. Declares temporary variables
- * if '$' was used.
- */
-Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
-{
- assert(!ae->lengthVar);
-
- *pe0 = NULL;
-
- AggregateDeclaration *ad = isAggregate(ae->e1->type);
- Dsymbol *slice = search_function(ad, Id::slice);
- //printf("slice = %s %s\n", slice->kind(), slice->toChars());
-
- for (size_t i = 0; i < ae->arguments->length; i++)
- {
- if (i == 0)
- *pe0 = extractOpDollarSideEffect(sc, ae);
-
- Expression *e = (*ae->arguments)[i];
- if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
- {
- Lfallback:
- if (ae->arguments->length == 1)
- return NULL;
- ae->error("multi-dimensional slicing requires template opSlice");
- return new ErrorExp();
- }
- //printf("[%d] e = %s\n", i, e->toChars());
-
- // Create scope for '$' variable for this dimension
- ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
- sym->loc = ae->loc;
- sym->parent = sc->scopesym;
- sc = sc->push(sym);
- ae->lengthVar = NULL; // Create it only if required
- ae->currentDimension = i; // Dimension for $, if required
-
- e = expressionSemantic(e, sc);
- e = resolveProperties(sc, e);
-
- if (ae->lengthVar && sc->func)
- {
- // If $ was used, declare it now
- Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
- de = expressionSemantic(de, sc);
- *pe0 = Expression::combine(*pe0, de);
- }
- sc = sc->pop();
-
- if (e->op == TOKinterval)
- {
- IntervalExp *ie = (IntervalExp *)e;
-
- Objects *tiargs = new Objects();
- Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
- edim = expressionSemantic(edim, sc);
- tiargs->push(edim);
-
- Expressions *fargs = new Expressions();
- fargs->push(ie->lwr);
- fargs->push(ie->upr);
-
- unsigned xerrors = global.startGagging();
- sc = sc->push();
- FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
- sc = sc->pop();
- global.endGagging(xerrors);
- if (!fslice)
- goto Lfallback;
-
- e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
- e = new CallExp(ae->loc, e, fargs);
- e = expressionSemantic(e, sc);
- }
-
- if (!e->type)
- {
- ae->error("%s has no value", e->toChars());
- e = new ErrorExp();
- }
- if (e->op == TOKerror)
- return e;
-
- (*ae->arguments)[i] = e;
- }
-
- return ae;
-}
-
-/***********************************************************
- * Resolve `exp` as a compile-time known string.
- * Params:
- * sc = scope
- * exp = Expression which expected as a string
- * s = What the string is expected for, will be used in error diagnostic.
- * Returns:
- * String literal, or `null` if error happens.
- */
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
-{
- sc = sc->startCTFE();
- exp = expressionSemantic(exp, sc);
- exp = resolveProperties(sc, exp);
- sc = sc->endCTFE();
-
- if (exp->op == TOKerror)
- return NULL;
-
- Expression *e = exp;
- if (exp->type->isString())
- {
- e = e->ctfeInterpret();
- if (e->op == TOKerror)
- return NULL;
- }
-
- StringExp *se = e->toStringExp();
- if (!se)
- {
- exp->error("string expected for %s, not (%s) of type %s",
- s, exp->toChars(), exp->type->toChars());
- return NULL;
- }
- return se;
-}
-
-/**************************************
- * Runs semantic on se->lwr and se->upr. Declares a temporary variable
- * if '$' was used.
- */
-Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
-{
- //assert(!ae->lengthVar);
- if (!ie)
- return ae;
-
- VarDeclaration *lengthVar = ae->lengthVar;
-
- // create scope for '$'
- ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
- sym->loc = ae->loc;
- sym->parent = sc->scopesym;
- sc = sc->push(sym);
-
- for (size_t i = 0; i < 2; ++i)
- {
- Expression *e = i == 0 ? ie->lwr : ie->upr;
- e = expressionSemantic(e, sc);
- e = resolveProperties(sc, e);
- if (!e->type)
- {
- ae->error("%s has no value", e->toChars());
- return new ErrorExp();
- }
- (i == 0 ? ie->lwr : ie->upr) = e;
- }
-
- if (lengthVar != ae->lengthVar && sc->func)
- {
- // If $ was used, declare it now
- Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
- de = expressionSemantic(de, sc);
- *pe0 = Expression::combine(*pe0, de);
- }
- sc = sc->pop();
-
- return ae;
-}
-
Expression *BinExp::reorderSettingAAElem(Scope *sc)
{
BinExp *be = this;
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index f0ae280..2ed8fac 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -883,10 +883,14 @@ public:
/****************************************************************/
-class CompileExp : public UnaExp
+class CompileExp : public Expression
{
public:
- CompileExp(Loc loc, Expression *e);
+ Expressions *exps;
+
+ CompileExp(Loc loc, Expressions *exps);
+ Expression *syntaxCopy();
+ bool equals(RootObject *o);
void accept(Visitor *v) { v->visit(this); }
};
@@ -1124,7 +1128,6 @@ class ArrayLengthExp : public UnaExp
public:
ArrayLengthExp(Loc loc, Expression *e1);
- static Expression *rewriteOpAssign(BinExp *exp);
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 7cccd95..4a37d0f 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -47,26 +47,1252 @@ bool symbolIsVisible(Scope *sc, Dsymbol *s);
VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
Type *getTypeInfoType(Loc loc, Type *t, Scope *sc);
+char *MODtoChars(MOD mod);
bool MODimplicitConv(MOD modfrom, MOD modto);
+MOD MODmerge(MOD mod1, MOD mod2);
MATCH MODmethodConv(MOD modfrom, MOD modto);
void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
void unSpeculative(Scope *sc, RootObject *o);
-bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt);
-bool checkDefCtor(Loc loc, Type *t);
bool isDotOpDispatch(Expression *e);
-bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix);
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, Expression *e1, Declaration *var, int flag = 0);
bool isNeedThisScope(Scope *sc, Declaration *d);
-Expression *resolveUFCS(Scope *sc, CallExp *ce);
bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
bool isSafeCast(Expression *e, Type *tfrom, Type *tto);
FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
Expression *callCpCtor(Scope *sc, Expression *e);
Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
-Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL);
-Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL);
+
+bool checkPrintfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list);
+bool checkScanfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list);
+
+/********************************************************
+ * Perform semantic analysis and CTFE on expressions to produce
+ * a string.
+ * Params:
+ * buf = append generated string to buffer
+ * sc = context
+ * exps = array of Expressions
+ * Returns:
+ * true on error
+ */
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps)
+{
+ if (!exps)
+ return false;
+
+ for (size_t i = 0; i < exps->length; i++)
+ {
+ Expression *ex = (*exps)[i];
+ if (!ex)
+ continue;
+ Scope *sc2 = sc->startCTFE();
+ Expression *e2 = expressionSemantic(ex, sc2);
+ Expression *e3 = resolveProperties(sc2, e2);
+ sc2->endCTFE();
+
+ // allowed to contain types as well as expressions
+ Expression *e4 = ctfeInterpretForPragmaMsg(e3);
+ if (!e4 || e4->op == TOKerror)
+ return true;
+
+ // expand tuple
+ if (TupleExp *te = e4->isTupleExp())
+ {
+ if (expressionsToString(buf, sc, te->exps))
+ return true;
+ continue;
+ }
+ // char literals exp `.toStringExp` return `null` but we cant override it
+ // because in most contexts we don't want the conversion to succeed.
+ IntegerExp *ie = e4->isIntegerExp();
+ const TY ty = (ie && ie->type) ? ie->type->ty : (TY)Terror;
+ if (ty == Tchar || ty == Twchar || ty == Tdchar)
+ {
+ TypeSArray *tsa = new TypeSArray(ie->type, new IntegerExp(ex->loc, 1, Type::tint32));
+ e4 = new ArrayLiteralExp(ex->loc, tsa, ie);
+ }
+
+ if (StringExp *se = e4->toStringExp())
+ buf.writestring(se->toUTF8(sc)->toPtr());
+ else
+ buf.writestring(e4->toChars());
+ }
+ return false;
+}
+
+/***********************************************************
+ * Resolve `exp` as a compile-time known string.
+ * Params:
+ * sc = scope
+ * exp = Expression which expected as a string
+ * s = What the string is expected for, will be used in error diagnostic.
+ * Returns:
+ * String literal, or `null` if error happens.
+ */
+StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
+{
+ sc = sc->startCTFE();
+ exp = expressionSemantic(exp, sc);
+ exp = resolveProperties(sc, exp);
+ sc = sc->endCTFE();
+
+ if (exp->op == TOKerror)
+ return NULL;
+
+ Expression *e = exp;
+ if (exp->type->isString())
+ {
+ e = e->ctfeInterpret();
+ if (e->op == TOKerror)
+ return NULL;
+ }
+
+ StringExp *se = e->toStringExp();
+ if (!se)
+ {
+ exp->error("string expected for %s, not (%s) of type %s",
+ s, exp->toChars(), exp->type->toChars());
+ return NULL;
+ }
+ return se;
+}
+
+/****************************************************************/
+
+static Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
+{
+ Expression *e0;
+ Expression *e1 = Expression::extractLast(ue->e1, &e0);
+ // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
+
+ if (!isTrivialExp(e1))
+ {
+ /* Even if opDollar is needed, 'e1' should be evaluate only once. So
+ * Rewrite:
+ * e1.opIndex( ... use of $ ... )
+ * e1.opSlice( ... use of $ ... )
+ * as:
+ * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
+ * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
+ */
+ e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
+ assert(e1->op == TOKvar);
+ VarExp *ve = (VarExp *)e1;
+ ve->var->storage_class |= STCexptemp; // lifetime limited to expression
+ }
+ ue->e1 = e1;
+ return e0;
+}
+
+/**************************************
+ * Runs semantic on ae->arguments. Declares temporary variables
+ * if '$' was used.
+ */
+Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
+{
+ assert(!ae->lengthVar);
+
+ *pe0 = NULL;
+
+ AggregateDeclaration *ad = isAggregate(ae->e1->type);
+ Dsymbol *slice = search_function(ad, Id::slice);
+ //printf("slice = %s %s\n", slice->kind(), slice->toChars());
+
+ for (size_t i = 0; i < ae->arguments->length; i++)
+ {
+ if (i == 0)
+ *pe0 = extractOpDollarSideEffect(sc, ae);
+
+ Expression *e = (*ae->arguments)[i];
+ if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
+ {
+ Lfallback:
+ if (ae->arguments->length == 1)
+ return NULL;
+ ae->error("multi-dimensional slicing requires template opSlice");
+ return new ErrorExp();
+ }
+ //printf("[%d] e = %s\n", i, e->toChars());
+
+ // Create scope for '$' variable for this dimension
+ ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
+ sym->loc = ae->loc;
+ sym->parent = sc->scopesym;
+ sc = sc->push(sym);
+ ae->lengthVar = NULL; // Create it only if required
+ ae->currentDimension = i; // Dimension for $, if required
+
+ e = expressionSemantic(e, sc);
+ e = resolveProperties(sc, e);
+
+ if (ae->lengthVar && sc->func)
+ {
+ // If $ was used, declare it now
+ Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
+ de = expressionSemantic(de, sc);
+ *pe0 = Expression::combine(*pe0, de);
+ }
+ sc = sc->pop();
+
+ if (e->op == TOKinterval)
+ {
+ IntervalExp *ie = (IntervalExp *)e;
+
+ Objects *tiargs = new Objects();
+ Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
+ edim = expressionSemantic(edim, sc);
+ tiargs->push(edim);
+
+ Expressions *fargs = new Expressions();
+ fargs->push(ie->lwr);
+ fargs->push(ie->upr);
+
+ unsigned xerrors = global.startGagging();
+ sc = sc->push();
+ FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
+ sc = sc->pop();
+ global.endGagging(xerrors);
+ if (!fslice)
+ goto Lfallback;
+
+ e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
+ e = new CallExp(ae->loc, e, fargs);
+ e = expressionSemantic(e, sc);
+ }
+
+ if (!e->type)
+ {
+ ae->error("%s has no value", e->toChars());
+ e = new ErrorExp();
+ }
+ if (e->op == TOKerror)
+ return e;
+
+ (*ae->arguments)[i] = e;
+ }
+
+ return ae;
+}
+
+/**************************************
+ * Runs semantic on se->lwr and se->upr. Declares a temporary variable
+ * if '$' was used.
+ */
+Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
+{
+ //assert(!ae->lengthVar);
+ if (!ie)
+ return ae;
+
+ VarDeclaration *lengthVar = ae->lengthVar;
+
+ // create scope for '$'
+ ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
+ sym->loc = ae->loc;
+ sym->parent = sc->scopesym;
+ sc = sc->push(sym);
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ Expression *e = i == 0 ? ie->lwr : ie->upr;
+ e = expressionSemantic(e, sc);
+ e = resolveProperties(sc, e);
+ if (!e->type)
+ {
+ ae->error("%s has no value", e->toChars());
+ return new ErrorExp();
+ }
+ (i == 0 ? ie->lwr : ie->upr) = e;
+ }
+
+ if (lengthVar != ae->lengthVar && sc->func)
+ {
+ // If $ was used, declare it now
+ Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
+ de = expressionSemantic(de, sc);
+ *pe0 = Expression::combine(*pe0, de);
+ }
+ sc = sc->pop();
+
+ return ae;
+}
+
+/******************************
+ * Perform semantic() on an array of Expressions.
+ */
+
+bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
+{
+ bool err = false;
+ if (exps)
+ {
+ for (size_t i = 0; i < exps->length; i++)
+ {
+ Expression *e = (*exps)[i];
+ if (e)
+ {
+ e = expressionSemantic(e, sc);
+ if (e->op == TOKerror)
+ err = true;
+ if (preserveErrors || e->op != TOKerror)
+ (*exps)[i] = e;
+ }
+ }
+ }
+ return err;
+}
+
+/******************************
+ * Check the tail CallExp is really property function call.
+ */
+static bool checkPropertyCall(Expression *e)
+{
+ while (e->op == TOKcomma)
+ e = ((CommaExp *)e)->e2;
+
+ if (e->op == TOKcall)
+ {
+ CallExp *ce = (CallExp *)e;
+ TypeFunction *tf;
+ if (ce->f)
+ {
+ tf = (TypeFunction *)ce->f->type;
+ /* If a forward reference to ce->f, try to resolve it
+ */
+ if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
+ {
+ dsymbolSemantic(ce->f, NULL);
+ tf = (TypeFunction *)ce->f->type;
+ }
+ }
+ else if (ce->e1->type->ty == Tfunction)
+ tf = (TypeFunction *)ce->e1->type;
+ else if (ce->e1->type->ty == Tdelegate)
+ tf = (TypeFunction *)ce->e1->type->nextOf();
+ else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction)
+ tf = (TypeFunction *)ce->e1->type->nextOf();
+ else
+ assert(0);
+ }
+ return false;
+}
+
+// TODO: merge with Scope::search::searchScopes()
+static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
+{
+ Dsymbol *s = NULL;
+ for (Scope *scx = sc; scx; scx = scx->enclosing)
+ {
+ if (!scx->scopesym)
+ continue;
+ if (scx->scopesym->isModule())
+ flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
+ s = scx->scopesym->search(loc, ident, flags);
+ if (s)
+ {
+ // overload set contains only module scope symbols.
+ if (s->isOverloadSet())
+ break;
+ // selective/renamed imports also be picked up
+ if (AliasDeclaration *ad = s->isAliasDeclaration())
+ {
+ if (ad->_import)
+ break;
+ }
+ // See only module scope symbols for UFCS target.
+ Dsymbol *p = s->toParent2();
+ if (p && p->isModule())
+ break;
+ }
+ s = NULL;
+
+ // Stop when we hit a module, but keep going if that is not just under the global scope
+ if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing))
+ break;
+ }
+ return s;
+}
+
+/******************************
+ * Find symbol in accordance with the UFCS name look up rule
+ */
+
+static Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
+{
+ //printf("searchUFCS(ident = %s)\n", ident->toChars());
+ Loc loc = ue->loc;
+ int flags = 0;
+ Dsymbol *s = NULL;
+
+ if (sc->flags & SCOPEignoresymbolvisibility)
+ flags |= IgnoreSymbolVisibility;
+
+ // First look in local scopes
+ s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
+ if (!s)
+ {
+ // Second look in imported modules
+ s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
+ }
+
+ if (!s)
+ return ue->e1->type->Type::getProperty(loc, ident, 0);
+
+ FuncDeclaration *f = s->isFuncDeclaration();
+ if (f)
+ {
+ TemplateDeclaration *td = getFuncTemplateDecl(f);
+ if (td)
+ {
+ if (td->overroot)
+ td = td->overroot;
+ s = td;
+ }
+ }
+
+ if (ue->op == TOKdotti)
+ {
+ DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue;
+ TemplateInstance *ti = new TemplateInstance(loc, s->ident);
+ ti->tiargs = dti->ti->tiargs; // for better diagnostic message
+ if (!ti->updateTempDecl(sc, s))
+ return new ErrorExp();
+ return new ScopeExp(loc, ti);
+ }
+ else
+ {
+ //printf("-searchUFCS() %s\n", s->toChars());
+ return new DsymbolExp(loc, s);
+ }
+}
+
+/******************************
+ * Pull out callable entity with UFCS.
+ */
+
+static Expression *resolveUFCS(Scope *sc, CallExp *ce)
+{
+ Loc loc = ce->loc;
+ Expression *eleft;
+ Expression *e;
+
+ if (ce->e1->op == TOKdotid)
+ {
+ DotIdExp *die = (DotIdExp *)ce->e1;
+ Identifier *ident = die->ident;
+
+ Expression *ex = semanticX(die, sc);
+ if (ex != die)
+ {
+ ce->e1 = ex;
+ return NULL;
+ }
+ eleft = die->e1;
+
+ Type *t = eleft->type->toBasetype();
+ if (t->ty == Tarray || t->ty == Tsarray ||
+ t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid))
+ {
+ /* Built-in types and arrays have no callable properties, so do shortcut.
+ * It is necessary in: e.init()
+ */
+ }
+ else if (t->ty == Taarray)
+ {
+ if (ident == Id::remove)
+ {
+ /* Transform:
+ * aa.remove(arg) into delete aa[arg]
+ */
+ if (!ce->arguments || ce->arguments->length != 1)
+ {
+ ce->error("expected key as argument to aa.remove()");
+ return new ErrorExp();
+ }
+ if (!eleft->type->isMutable())
+ {
+ ce->error("cannot remove key from %s associative array %s",
+ MODtoChars(t->mod), eleft->toChars());
+ return new ErrorExp();
+ }
+ Expression *key = (*ce->arguments)[0];
+ key = expressionSemantic(key, sc);
+ key = resolveProperties(sc, key);
+
+ TypeAArray *taa = (TypeAArray *)t;
+ key = key->implicitCastTo(sc, taa->index);
+
+ if (key->checkValue())
+ return new ErrorExp();
+
+ semanticTypeInfo(sc, taa->index);
+
+ return new RemoveExp(loc, eleft, key);
+ }
+ }
+ else
+ {
+ if (Expression *ey = semanticY(die, sc, 1))
+ {
+ if (ey->op == TOKerror)
+ return ey;
+ ce->e1 = ey;
+ if (isDotOpDispatch(ey))
+ {
+ unsigned errors = global.startGagging();
+ e = expressionSemantic(ce->syntaxCopy(), sc);
+ if (!global.endGagging(errors))
+ return e;
+ /* fall down to UFCS */
+ }
+ else
+ return NULL;
+ }
+ }
+ e = searchUFCS(sc, die, ident);
+ }
+ else if (ce->e1->op == TOKdotti)
+ {
+ DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
+ if (Expression *ey = semanticY(dti, sc, 1))
+ {
+ ce->e1 = ey;
+ return NULL;
+ }
+ eleft = dti->e1;
+ e = searchUFCS(sc, dti, dti->ti->name);
+ }
+ else
+ return NULL;
+
+ // Rewrite
+ ce->e1 = e;
+ if (!ce->arguments)
+ ce->arguments = new Expressions();
+ ce->arguments->shift(eleft);
+
+ return NULL;
+}
+
+/******************************
+ * Pull out property with UFCS.
+ */
+
+static Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
+{
+ Loc loc = e1->loc;
+ Expression *eleft;
+ Expression *e;
+
+ if (e1->op == TOKdotid)
+ {
+ DotIdExp *die = (DotIdExp *)e1;
+ eleft = die->e1;
+ e = searchUFCS(sc, die, die->ident);
+ }
+ else if (e1->op == TOKdotti)
+ {
+ DotTemplateInstanceExp *dti;
+ dti = (DotTemplateInstanceExp *)e1;
+ eleft = dti->e1;
+ e = searchUFCS(sc, dti, dti->ti->name);
+ }
+ else
+ return NULL;
+
+ if (e == NULL)
+ return NULL;
+
+ // Rewrite
+ if (e2)
+ {
+ // run semantic without gagging
+ e2 = expressionSemantic(e2, sc);
+
+ /* f(e1) = e2
+ */
+ Expression *ex = e->copy();
+ Expressions *a1 = new Expressions();
+ a1->setDim(1);
+ (*a1)[0] = eleft;
+ ex = new CallExp(loc, ex, a1);
+ ex = trySemantic(ex, sc);
+
+ /* f(e1, e2)
+ */
+ Expressions *a2 = new Expressions();
+ a2->setDim(2);
+ (*a2)[0] = eleft;
+ (*a2)[1] = e2;
+ e = new CallExp(loc, e, a2);
+ if (ex)
+ { // if fallback setter exists, gag errors
+ e = trySemantic(e, sc);
+ if (!e)
+ { checkPropertyCall(ex);
+ ex = new AssignExp(loc, ex, e2);
+ return expressionSemantic(ex, sc);
+ }
+ }
+ else
+ { // strict setter prints errors if fails
+ e = expressionSemantic(e, sc);
+ }
+ checkPropertyCall(e);
+ return e;
+ }
+ else
+ {
+ /* f(e1)
+ */
+ Expressions *arguments = new Expressions();
+ arguments->setDim(1);
+ (*arguments)[0] = eleft;
+ e = new CallExp(loc, e, arguments);
+ e = expressionSemantic(e, sc);
+ checkPropertyCall(e);
+ return expressionSemantic(e, sc);
+ }
+}
+
+/******************************
+ * If e1 is a property function (template), resolve it.
+ */
+
+Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
+{
+ //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
+ OverloadSet *os;
+ FuncDeclaration *fd;
+ TemplateDeclaration *td;
+
+ if (e1->op == TOKdot)
+ {
+ DotExp *de = (DotExp *)e1;
+ if (de->e2->op == TOKoverloadset)
+ {
+ os = ((OverExp *)de->e2)->vars;
+ goto Los;
+ }
+ }
+ else if (e1->op == TOKoverloadset)
+ {
+ os = ((OverExp *)e1)->vars;
+ Los:
+ assert(os);
+ for (size_t i = 0; i < os->a.length; i++)
+ {
+ Dsymbol *s = os->a[i];
+ fd = s->isFuncDeclaration();
+ td = s->isTemplateDeclaration();
+ if (fd)
+ {
+ if (((TypeFunction *)fd->type)->isproperty)
+ return resolveProperties(sc, e1);
+ }
+ else if (td && td->onemember &&
+ (fd = td->onemember->isFuncDeclaration()) != NULL)
+ {
+ if (((TypeFunction *)fd->type)->isproperty ||
+ (fd->storage_class2 & STCproperty) ||
+ (td->_scope->stc & STCproperty))
+ {
+ return resolveProperties(sc, e1);
+ }
+ }
+ }
+ }
+ else if (e1->op == TOKdotti)
+ {
+ DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
+ if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
+ goto Ltd;
+ }
+ else if (e1->op == TOKdottd)
+ {
+ td = ((DotTemplateExp *)e1)->td;
+ goto Ltd;
+ }
+ else if (e1->op == TOKscope)
+ {
+ Dsymbol *s = ((ScopeExp *)e1)->sds;
+ TemplateInstance *ti = s->isTemplateInstance();
+ if (ti && !ti->semanticRun && ti->tempdecl)
+ {
+ if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
+ goto Ltd;
+ }
+ }
+ else if (e1->op == TOKtemplate)
+ {
+ td = ((TemplateExp *)e1)->td;
+ Ltd:
+ assert(td);
+ if (td->onemember &&
+ (fd = td->onemember->isFuncDeclaration()) != NULL)
+ {
+ if (((TypeFunction *)fd->type)->isproperty ||
+ (fd->storage_class2 & STCproperty) ||
+ (td->_scope->stc & STCproperty))
+ {
+ return resolveProperties(sc, e1);
+ }
+ }
+ }
+ else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
+ {
+ DotVarExp *dve = (DotVarExp *)e1;
+ fd = dve->var->isFuncDeclaration();
+ goto Lfd;
+ }
+ else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
+ (sc->intypeof || !((VarExp *)e1)->var->needThis()))
+ {
+ fd = ((VarExp *)e1)->var->isFuncDeclaration();
+ Lfd:
+ assert(fd);
+ if (((TypeFunction *)fd->type)->isproperty)
+ return resolveProperties(sc, e1);
+ }
+ return e1;
+}
+
+/*************************************************************
+ * Given var, we need to get the
+ * right 'this' pointer if var is in an outer class, but our
+ * existing 'this' pointer is in an inner class.
+ * Input:
+ * e1 existing 'this'
+ * ad struct or class we need the correct 'this' for
+ * var the specific member of ad we're accessing
+ */
+
+static Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
+ Expression *e1, Declaration *var, int flag = 0)
+{
+ //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
+ L1:
+ Type *t = e1->type->toBasetype();
+ //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
+
+ /* If e1 is not the 'this' pointer for ad
+ */
+ if (ad &&
+ !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
+ ((TypeStruct *)t->nextOf())->sym == ad)
+ &&
+ !(t->ty == Tstruct &&
+ ((TypeStruct *)t)->sym == ad)
+ )
+ {
+ ClassDeclaration *cd = ad->isClassDeclaration();
+ ClassDeclaration *tcd = t->isClassHandle();
+
+ /* e1 is the right this if ad is a base class of e1
+ */
+ if (!cd || !tcd ||
+ !(tcd == cd || cd->isBaseOf(tcd, NULL))
+ )
+ {
+ /* Only classes can be inner classes with an 'outer'
+ * member pointing to the enclosing class instance
+ */
+ if (tcd && tcd->isNested())
+ {
+ /* e1 is the 'this' pointer for an inner class: tcd.
+ * Rewrite it as the 'this' pointer for the outer class.
+ */
+
+ e1 = new DotVarExp(loc, e1, tcd->vthis);
+ e1->type = tcd->vthis->type;
+ e1->type = e1->type->addMod(t->mod);
+ // Do not call checkNestedRef()
+ //e1 = expressionSemantic(e1, sc);
+
+ // Skip up over nested functions, and get the enclosing
+ // class type.
+ int n = 0;
+ Dsymbol *s;
+ for (s = tcd->toParent();
+ s && s->isFuncDeclaration();
+ s = s->toParent())
+ {
+ FuncDeclaration *f = s->isFuncDeclaration();
+ if (f->vthis)
+ {
+ //printf("rewriting e1 to %s's this\n", f->toChars());
+ n++;
+ e1 = new VarExp(loc, f->vthis);
+ }
+ else
+ {
+ e1->error("need `this` of type %s to access member %s"
+ " from static function %s",
+ ad->toChars(), var->toChars(), f->toChars());
+ e1 = new ErrorExp();
+ return e1;
+ }
+ }
+ if (s && s->isClassDeclaration())
+ {
+ e1->type = s->isClassDeclaration()->type;
+ e1->type = e1->type->addMod(t->mod);
+ if (n > 1)
+ e1 = expressionSemantic(e1, sc);
+ }
+ else
+ e1 = expressionSemantic(e1, sc);
+ goto L1;
+ }
+
+ /* Can't find a path from e1 to ad
+ */
+ if (flag)
+ return NULL;
+ e1->error("this for %s needs to be type %s not type %s",
+ var->toChars(), ad->toChars(), t->toChars());
+ return new ErrorExp();
+ }
+ }
+ return e1;
+}
+
+/***************************************
+ * Pull out any properties.
+ */
+
+static Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
+{
+ //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
+ Loc loc = e1->loc;
+
+ OverloadSet *os;
+ Dsymbol *s;
+ Objects *tiargs;
+ Type *tthis;
+ if (e1->op == TOKdot)
+ {
+ DotExp *de = (DotExp *)e1;
+ if (de->e2->op == TOKoverloadset)
+ {
+ tiargs = NULL;
+ tthis = de->e1->type;
+ os = ((OverExp *)de->e2)->vars;
+ goto Los;
+ }
+ }
+ else if (e1->op == TOKoverloadset)
+ {
+ tiargs = NULL;
+ tthis = NULL;
+ os = ((OverExp *)e1)->vars;
+ Los:
+ assert(os);
+ FuncDeclaration *fd = NULL;
+ if (e2)
+ {
+ e2 = expressionSemantic(e2, sc);
+ if (e2->op == TOKerror)
+ return new ErrorExp();
+ e2 = resolveProperties(sc, e2);
+
+ Expressions a;
+ a.push(e2);
+
+ for (size_t i = 0; i < os->a.length; i++)
+ {
+ FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
+ if (f)
+ {
+ if (f->errors)
+ return new ErrorExp();
+ fd = f;
+ assert(fd->type->ty == Tfunction);
+ }
+ }
+ if (fd)
+ {
+ Expression *e = new CallExp(loc, e1, e2);
+ return expressionSemantic(e, sc);
+ }
+ }
+ {
+ for (size_t i = 0; i < os->a.length; i++)
+ {
+ FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
+ if (f)
+ {
+ if (f->errors)
+ return new ErrorExp();
+ fd = f;
+ assert(fd->type->ty == Tfunction);
+ TypeFunction *tf = (TypeFunction *)fd->type;
+ if (!tf->isref && e2)
+ goto Leproplvalue;
+ }
+ }
+ if (fd)
+ {
+ Expression *e = new CallExp(loc, e1);
+ if (e2)
+ e = new AssignExp(loc, e, e2);
+ return expressionSemantic(e, sc);
+ }
+ }
+ if (e2)
+ goto Leprop;
+ }
+ else if (e1->op == TOKdotti)
+ {
+ DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
+ if (!dti->findTempDecl(sc))
+ goto Leprop;
+ if (!dti->ti->semanticTiargs(sc))
+ goto Leprop;
+ tiargs = dti->ti->tiargs;
+ tthis = dti->e1->type;
+ if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL)
+ goto Los;
+ if ((s = dti->ti->tempdecl) != NULL)
+ goto Lfd;
+ }
+ else if (e1->op == TOKdottd)
+ {
+ DotTemplateExp *dte = (DotTemplateExp *)e1;
+ s = dte->td;
+ tiargs = NULL;
+ tthis = dte->e1->type;
+ goto Lfd;
+ }
+ else if (e1->op == TOKscope)
+ {
+ s = ((ScopeExp *)e1)->sds;
+ TemplateInstance *ti = s->isTemplateInstance();
+ if (ti && !ti->semanticRun && ti->tempdecl)
+ {
+ //assert(ti->needsTypeInference(sc));
+ if (!ti->semanticTiargs(sc))
+ goto Leprop;
+ tiargs = ti->tiargs;
+ tthis = NULL;
+ if ((os = ti->tempdecl->isOverloadSet()) != NULL)
+ goto Los;
+ if ((s = ti->tempdecl) != NULL)
+ goto Lfd;
+ }
+ }
+ else if (e1->op == TOKtemplate)
+ {
+ s = ((TemplateExp *)e1)->td;
+ tiargs = NULL;
+ tthis = NULL;
+ goto Lfd;
+ }
+ else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
+ {
+ DotVarExp *dve = (DotVarExp *)e1;
+ s = dve->var->isFuncDeclaration();
+ tiargs = NULL;
+ tthis = dve->e1->type;
+ goto Lfd;
+ }
+ else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
+ {
+ s = ((VarExp *)e1)->var->isFuncDeclaration();
+ tiargs = NULL;
+ tthis = NULL;
+ Lfd:
+ assert(s);
+ if (e2)
+ {
+ e2 = expressionSemantic(e2, sc);
+ if (e2->op == TOKerror)
+ return new ErrorExp();
+ e2 = resolveProperties(sc, e2);
+
+ Expressions a;
+ a.push(e2);
+
+ FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
+ if (fd && fd->type)
+ {
+ if (fd->errors)
+ return new ErrorExp();
+ assert(fd->type->ty == Tfunction);
+ Expression *e = new CallExp(loc, e1, e2);
+ return expressionSemantic(e, sc);
+ }
+ }
+ {
+ FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
+ if (fd && fd->type)
+ {
+ if (fd->errors)
+ return new ErrorExp();
+ assert(fd->type->ty == Tfunction);
+ TypeFunction *tf = (TypeFunction *)fd->type;
+ if (!e2 || tf->isref)
+ {
+ Expression *e = new CallExp(loc, e1);
+ if (e2)
+ e = new AssignExp(loc, e, e2);
+ return expressionSemantic(e, sc);
+ }
+ }
+ }
+ if (FuncDeclaration *fd = s->isFuncDeclaration())
+ {
+ // Keep better diagnostic message for invalid property usage of functions
+ assert(fd->type->ty == Tfunction);
+ Expression *e = new CallExp(loc, e1, e2);
+ return expressionSemantic(e, sc);
+ }
+ if (e2)
+ goto Leprop;
+ }
+ if (e1->op == TOKvar)
+ {
+ VarExp *ve = (VarExp *)e1;
+ VarDeclaration *v = ve->var->isVarDeclaration();
+ if (v && ve->checkPurity(sc, v))
+ return new ErrorExp();
+ }
+ if (e2)
+ return NULL;
+
+ if (e1->type &&
+ e1->op != TOKtype) // function type is not a property
+ {
+ /* Look for e1 being a lazy parameter; rewrite as delegate call
+ */
+ if (e1->op == TOKvar)
+ {
+ VarExp *ve = (VarExp *)e1;
+
+ if (ve->var->storage_class & STClazy)
+ {
+ Expression *e = new CallExp(loc, e1);
+ return expressionSemantic(e, sc);
+ }
+ }
+ else if (e1->op == TOKdotvar)
+ {
+ // Check for reading overlapped pointer field in @safe code.
+ if (checkUnsafeAccess(sc, e1, true, true))
+ return new ErrorExp();
+ }
+ else if (e1->op == TOKdot)
+ {
+ e1->error("expression has no value");
+ return new ErrorExp();
+ }
+ else if (e1->op == TOKcall)
+ {
+ CallExp *ce = (CallExp *)e1;
+ // Check for reading overlapped pointer field in @safe code.
+ if (checkUnsafeAccess(sc, ce->e1, true, true))
+ return new ErrorExp();
+ }
+ }
+
+ if (!e1->type)
+ {
+ error(loc, "cannot resolve type for %s", e1->toChars());
+ e1 = new ErrorExp();
+ }
+ return e1;
+
+Leprop:
+ error(loc, "not a property %s", e1->toChars());
+ return new ErrorExp();
+
+Leproplvalue:
+ error(loc, "%s is not an lvalue", e1->toChars());
+ return new ErrorExp();
+}
+
+Expression *resolveProperties(Scope *sc, Expression *e)
+{
+ //printf("resolveProperties(%s)\n", e->toChars());
+
+ e = resolvePropertiesX(sc, e);
+ if (e->checkRightThis(sc))
+ return new ErrorExp();
+ return e;
+}
+
+/****************************************
+ * The common type is determined by applying ?: to each pair.
+ * Output:
+ * exps[] properties resolved, implicitly cast to common type, rewritten in place
+ * *pt if pt is not NULL, set to the common type
+ * Returns:
+ * true a semantic error was detected
+ */
+
+static bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
+{
+ /* Still have a problem with:
+ * ubyte[][] = [ cast(ubyte[])"hello", [1]];
+ * which works if the array literal is initialized top down with the ubyte[][]
+ * type, but fails with this function doing bottom up typing.
+ */
+ //printf("arrayExpressionToCommonType()\n");
+ IntegerExp integerexp(0);
+ CondExp condexp(Loc(), &integerexp, NULL, NULL);
+
+ Type *t0 = NULL;
+ Expression *e0 = NULL; // dead-store to prevent spurious warning
+ size_t j0 = ~0; // dead-store to prevent spurious warning
+ bool foundType = false;
+
+ for (size_t i = 0; i < exps->length; i++)
+ {
+ Expression *e = (*exps)[i];
+ if (!e)
+ continue;
+
+ e = resolveProperties(sc, e);
+ if (!e->type)
+ {
+ e->error("%s has no value", e->toChars());
+ t0 = Type::terror;
+ continue;
+ }
+ if (e->op == TOKtype)
+ {
+ foundType = true; // do not break immediately, there might be more errors
+ e->checkValue(); // report an error "type T has no value"
+ t0 = Type::terror;
+ continue;
+ }
+ if (e->type->ty == Tvoid)
+ {
+ // void expressions do not concur to the determination of the common
+ // type.
+ continue;
+ }
+ if (checkNonAssignmentArrayOp(e))
+ {
+ t0 = Type::terror;
+ continue;
+ }
+
+ e = doCopyOrMove(sc, e);
+
+ if (!foundType && t0 && !t0->equals(e->type))
+ {
+ /* This applies ?: to merge the types. It's backwards;
+ * ?: should call this function to merge types.
+ */
+ condexp.type = NULL;
+ condexp.e1 = e0;
+ condexp.e2 = e;
+ condexp.loc = e->loc;
+ Expression *ex = expressionSemantic(&condexp, sc);
+ if (ex->op == TOKerror)
+ e = ex;
+ else
+ {
+ (*exps)[j0] = condexp.e1;
+ e = condexp.e2;
+ }
+ }
+ j0 = i;
+ e0 = e;
+ t0 = e->type;
+ if (e->op != TOKerror)
+ (*exps)[i] = e;
+ }
+
+ if (!t0)
+ t0 = Type::tvoid; // [] is typed as void[]
+ else if (t0->ty != Terror)
+ {
+ for (size_t i = 0; i < exps->length; i++)
+ {
+ Expression *e = (*exps)[i];
+ if (!e)
+ continue;
+
+ e = e->implicitCastTo(sc, t0);
+ //assert(e->op != TOKerror);
+ if (e->op == TOKerror)
+ {
+ /* Bugzilla 13024: a workaround for the bug in typeMerge -
+ * it should paint e1 and e2 by deduced common type,
+ * but doesn't in this particular case.
+ */
+ t0 = Type::terror;
+ break;
+ }
+ (*exps)[i] = e;
+ }
+ }
+ if (pt)
+ *pt = t0;
+
+ return (t0 == Type::terror);
+}
+
+static Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
+{ Expression *e;
+
+ switch (op)
+ {
+ case TOKaddass: e = new AddExp(loc, e1, e2); break;
+ case TOKminass: e = new MinExp(loc, e1, e2); break;
+ case TOKmulass: e = new MulExp(loc, e1, e2); break;
+ case TOKdivass: e = new DivExp(loc, e1, e2); break;
+ case TOKmodass: e = new ModExp(loc, e1, e2); break;
+ case TOKandass: e = new AndExp(loc, e1, e2); break;
+ case TOKorass: e = new OrExp (loc, e1, e2); break;
+ case TOKxorass: e = new XorExp(loc, e1, e2); break;
+ case TOKshlass: e = new ShlExp(loc, e1, e2); break;
+ case TOKshrass: e = new ShrExp(loc, e1, e2); break;
+ case TOKushrass: e = new UshrExp(loc, e1, e2); break;
+ default: assert(0);
+ }
+ return e;
+}
+
+/*********************
+ * Rewrite:
+ * array.length op= e2
+ * as:
+ * array.length = array.length op e2
+ * or:
+ * auto tmp = &array;
+ * (*tmp).length = (*tmp).length op e2
+ */
+
+static Expression *rewriteOpAssign(BinExp *exp)
+{
+ Expression *e;
+
+ assert(exp->e1->op == TOKarraylength);
+ ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
+ if (ale->e1->op == TOKvar)
+ {
+ e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
+ e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
+ }
+ else
+ {
+ /* auto tmp = &array;
+ * (*tmp).length = (*tmp).length op e2
+ */
+ VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
+
+ Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
+ Expression *elvalue = e1->syntaxCopy();
+ e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
+ e = new AssignExp(exp->loc, elvalue, e);
+ e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
+ }
+ return e;
+}
/****************************************
* Preprocess arguments to function.
@@ -111,6 +1337,695 @@ static bool preFunctionParameters(Scope *sc, Expressions *exps)
return err;
}
+/********************************************
+ * Issue an error if default construction is disabled for type t.
+ * Default construction is required for arrays and 'out' parameters.
+ * Returns:
+ * true an error was issued
+ */
+static bool checkDefCtor(Loc loc, Type *t)
+{
+ t = t->baseElemOf();
+ if (t->ty == Tstruct)
+ {
+ StructDeclaration *sd = ((TypeStruct *)t)->sym;
+ if (sd->noDefaultCtor)
+ {
+ sd->error(loc, "default construction is disabled");
+ return true;
+ }
+ }
+ return false;
+}
+
+/****************************************
+ * Now that we know the exact type of the function we're calling,
+ * the arguments[] need to be adjusted:
+ * 1. implicitly convert argument to the corresponding parameter type
+ * 2. add default arguments for any missing arguments
+ * 3. do default promotions on arguments corresponding to ...
+ * 4. add hidden _arguments[] argument
+ * 5. call copy constructor for struct value arguments
+ * Input:
+ * tf type of the function
+ * fd the function being called, NULL if called indirectly
+ * Output:
+ * *prettype return type of function
+ * *peprefix expression to execute before arguments[] are evaluated, NULL if none
+ * Returns:
+ * true errors happened
+ */
+
+static bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
+ Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
+{
+ //printf("functionParameters()\n");
+ assert(arguments);
+ assert(fd || tf->next);
+ size_t nargs = arguments ? arguments->length : 0;
+ size_t nparams = tf->parameterList.length();
+ unsigned olderrors = global.errors;
+ bool err = false;
+ *prettype = Type::terror;
+ Expression *eprefix = NULL;
+ *peprefix = NULL;
+
+ if (nargs > nparams && tf->parameterList.varargs == VARARGnone)
+ {
+ error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
+ return true;
+ }
+
+ // If inferring return type, and semantic3() needs to be run if not already run
+ if (!tf->next && fd->inferRetType)
+ {
+ fd->functionSemantic();
+ }
+ else if (fd && fd->parent)
+ {
+ TemplateInstance *ti = fd->parent->isTemplateInstance();
+ if (ti && ti->tempdecl)
+ {
+ fd->functionSemantic3();
+ }
+ }
+ bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
+
+ size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
+
+ /* If the function return type has wildcards in it, we'll need to figure out the actual type
+ * based on the actual argument types.
+ */
+ MOD wildmatch = 0;
+ if (tthis && tf->isWild() && !isCtorCall)
+ {
+ Type *t = tthis;
+ if (t->isImmutable())
+ wildmatch = MODimmutable;
+ else if (t->isWildConst())
+ wildmatch = MODwildconst;
+ else if (t->isWild())
+ wildmatch = MODwild;
+ else if (t->isConst())
+ wildmatch = MODconst;
+ else
+ wildmatch = MODmutable;
+ }
+
+ int done = 0;
+ for (size_t i = 0; i < n; i++)
+ {
+ Expression *arg;
+
+ if (i < nargs)
+ arg = (*arguments)[i];
+ else
+ arg = NULL;
+
+ if (i < nparams)
+ {
+ Parameter *p = tf->parameterList[i];
+
+ if (!arg)
+ {
+ if (!p->defaultArg)
+ {
+ if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
+ goto L2;
+ error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
+ return true;
+ }
+ arg = p->defaultArg;
+ arg = inlineCopy(arg, sc);
+ // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
+ arg = arg->resolveLoc(loc, sc);
+ arguments->push(arg);
+ nargs++;
+ }
+
+ if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
+ {
+ //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
+ {
+ MATCH m;
+ if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
+ {
+ if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
+ goto L2;
+ else if (nargs != nparams)
+ { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
+ return true;
+ }
+ goto L1;
+ }
+ }
+ L2:
+ Type *tb = p->type->toBasetype();
+ Type *tret = p->isLazyArray();
+ switch (tb->ty)
+ {
+ case Tsarray:
+ case Tarray:
+ {
+ /* Create a static array variable v of type arg->type:
+ * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
+ *
+ * The array literal in the initializer of the hidden variable
+ * is now optimized. See Bugzilla 2356.
+ */
+ Type *tbn = ((TypeArray *)tb)->next;
+
+ Expressions *elements = new Expressions();
+ elements->setDim(nargs - i);
+ for (size_t u = 0; u < elements->length; u++)
+ {
+ Expression *a = (*arguments)[i + u];
+ if (tret && a->implicitConvTo(tret))
+ {
+ a = a->implicitCastTo(sc, tret);
+ a = a->optimize(WANTvalue);
+ a = toDelegate(a, a->type, sc);
+ }
+ else
+ a = a->implicitCastTo(sc, tbn);
+ (*elements)[u] = a;
+ }
+ // Bugzilla 14395: Convert to a static array literal, or its slice.
+ arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
+ if (tb->ty == Tarray)
+ {
+ arg = new SliceExp(loc, arg, NULL, NULL);
+ arg->type = p->type;
+ }
+ break;
+ }
+ case Tclass:
+ {
+ /* Set arg to be:
+ * new Tclass(arg0, arg1, ..., argn)
+ */
+ Expressions *args = new Expressions();
+ args->setDim(nargs - i);
+ for (size_t u = i; u < nargs; u++)
+ (*args)[u - i] = (*arguments)[u];
+ arg = new NewExp(loc, NULL, NULL, p->type, args);
+ break;
+ }
+ default:
+ if (!arg)
+ {
+ error(loc, "not enough arguments");
+ return true;
+ }
+ break;
+ }
+ arg = expressionSemantic(arg, sc);
+ //printf("\targ = '%s'\n", arg->toChars());
+ arguments->setDim(i + 1);
+ (*arguments)[i] = arg;
+ nargs = i + 1;
+ done = 1;
+ }
+
+ L1:
+ if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
+ {
+ bool isRef = (p->storageClass & (STCref | STCout)) != 0;
+ if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
+ {
+ if (wildmatch)
+ wildmatch = MODmerge(wildmatch, wm);
+ else
+ wildmatch = wm;
+ //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
+ }
+ }
+ }
+ if (done)
+ break;
+ }
+ if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
+ tf->next->hasWild() &&
+ (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
+ {
+ if (fd)
+ {
+ /* If the called function may return the reference to
+ * outer inout data, it should be rejected.
+ *
+ * void foo(ref inout(int) x) {
+ * ref inout(int) bar(inout(int)) { return x; }
+ * struct S { ref inout(int) bar() inout { return x; } }
+ * bar(int.init) = 1; // bad!
+ * S().bar() = 1; // bad!
+ * }
+ */
+ Dsymbol *s = NULL;
+ if (fd->isThis() || fd->isNested())
+ s = fd->toParent2();
+ for (; s; s = s->toParent2())
+ {
+ if (AggregateDeclaration *ad = s->isAggregateDeclaration())
+ {
+ if (ad->isNested())
+ continue;
+ break;
+ }
+ if (FuncDeclaration *ff = s->isFuncDeclaration())
+ {
+ if (((TypeFunction *)ff->type)->iswild)
+ goto Linouterr;
+
+ if (ff->isNested() || ff->isThis())
+ continue;
+ }
+ break;
+ }
+ }
+ else if (tf->isWild())
+ {
+ Linouterr:
+ const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
+ error(loc, "modify inout to %s is not allowed inside inout function", s);
+ return true;
+ }
+ }
+
+ assert(nargs >= nparams);
+ for (size_t i = 0; i < nargs; i++)
+ {
+ Expression *arg = (*arguments)[i];
+ assert(arg);
+ if (i < nparams)
+ {
+ Parameter *p = tf->parameterList[i];
+
+ if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
+ {
+ Type *tprm = p->type;
+ if (p->type->hasWild())
+ tprm = p->type->substWildTo(wildmatch);
+ if (!tprm->equals(arg->type))
+ {
+ //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
+ arg = arg->implicitCastTo(sc, tprm);
+ arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
+ }
+ }
+ if (p->storageClass & STCref)
+ {
+ arg = arg->toLvalue(sc, arg);
+
+ // Look for mutable misaligned pointer, etc., in @safe mode
+ err |= checkUnsafeAccess(sc, arg, false, true);
+ }
+ else if (p->storageClass & STCout)
+ {
+ Type *t = arg->type;
+ if (!t->isMutable() || !t->isAssignable()) // check blit assignable
+ {
+ arg->error("cannot modify struct %s with immutable members", arg->toChars());
+ err = true;
+ }
+ else
+ {
+ // Look for misaligned pointer, etc., in @safe mode
+ err |= checkUnsafeAccess(sc, arg, false, true);
+ err |= checkDefCtor(arg->loc, t); // t must be default constructible
+ }
+ arg = arg->toLvalue(sc, arg);
+ }
+ else if (p->storageClass & STClazy)
+ {
+ // Convert lazy argument to a delegate
+ if (p->type->ty == Tvoid)
+ arg = toDelegate(arg, p->type, sc);
+ else
+ arg = toDelegate(arg, arg->type, sc);
+ }
+
+ //printf("arg: %s\n", arg->toChars());
+ //printf("type: %s\n", arg->type->toChars());
+ if (tf->parameterEscapes(p))
+ {
+ /* Argument value can escape from the called function.
+ * Check arg to see if it matters.
+ */
+ if (global.params.vsafe)
+ err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
+ }
+ else
+ {
+ /* Argument value cannot escape from the called function.
+ */
+ Expression *a = arg;
+ if (a->op == TOKcast)
+ a = ((CastExp *)a)->e1;
+
+ if (a->op == TOKfunction)
+ {
+ /* Function literals can only appear once, so if this
+ * appearance was scoped, there cannot be any others.
+ */
+ FuncExp *fe = (FuncExp *)a;
+ fe->fd->tookAddressOf = 0;
+ }
+ else if (a->op == TOKdelegate)
+ {
+ /* For passing a delegate to a scoped parameter,
+ * this doesn't count as taking the address of it.
+ * We only worry about 'escaping' references to the function.
+ */
+ DelegateExp *de = (DelegateExp *)a;
+ if (de->e1->op == TOKvar)
+ { VarExp *ve = (VarExp *)de->e1;
+ FuncDeclaration *f = ve->var->isFuncDeclaration();
+ if (f)
+ { f->tookAddressOf--;
+ //printf("tookAddressOf = %d\n", f->tookAddressOf);
+ }
+ }
+ }
+ }
+ arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
+ }
+ else
+ {
+ // These will be the trailing ... arguments
+
+ // If not D linkage, do promotions
+ if (tf->linkage != LINKd)
+ {
+ // Promote bytes, words, etc., to ints
+ arg = integralPromotions(arg, sc);
+
+ // Promote floats to doubles
+ switch (arg->type->ty)
+ {
+ case Tfloat32:
+ arg = arg->castTo(sc, Type::tfloat64);
+ break;
+
+ case Timaginary32:
+ arg = arg->castTo(sc, Type::timaginary64);
+ break;
+ }
+
+ if (tf->parameterList.varargs == VARARGvariadic)
+ {
+ const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
+ if (arg->type->ty == Tarray)
+ {
+ arg->error("cannot pass dynamic arrays to %s vararg functions", p);
+ err = true;
+ }
+ if (arg->type->ty == Tsarray)
+ {
+ arg->error("cannot pass static arrays to %s vararg functions", p);
+ err = true;
+ }
+ }
+ }
+
+ // Do not allow types that need destructors
+ if (arg->type->needsDestruction())
+ {
+ arg->error("cannot pass types that need destruction as variadic arguments");
+ err = true;
+ }
+
+ // Convert static arrays to dynamic arrays
+ // BUG: I don't think this is right for D2
+ Type *tb = arg->type->toBasetype();
+ if (tb->ty == Tsarray)
+ {
+ TypeSArray *ts = (TypeSArray *)tb;
+ Type *ta = ts->next->arrayOf();
+ if (ts->size(arg->loc) == 0)
+ arg = new NullExp(arg->loc, ta);
+ else
+ arg = arg->castTo(sc, ta);
+ }
+ if (tb->ty == Tstruct)
+ {
+ //arg = callCpCtor(sc, arg);
+ }
+
+ // Give error for overloaded function addresses
+ if (arg->op == TOKsymoff)
+ { SymOffExp *se = (SymOffExp *)arg;
+ if (se->hasOverloads &&
+ !se->var->isFuncDeclaration()->isUnique())
+ { arg->error("function %s is overloaded", arg->toChars());
+ err = true;
+ }
+ }
+ if (arg->checkValue())
+ err = true;
+ arg = arg->optimize(WANTvalue);
+ }
+ (*arguments)[i] = arg;
+ }
+
+ /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
+ */
+ const bool isVa_list = tf->parameterList.varargs == VARARGnone;
+ if (fd && (fd->flags & FUNCFLAGprintf))
+ {
+ if (StringExp *se = (*arguments)[nparams - 1 - isVa_list]->isStringExp())
+ {
+ Expressions argslice;
+ argslice.reserve(nargs - nparams);
+ for (size_t i = nparams; i < nargs; i++)
+ argslice.push((*arguments)[i]);
+ checkPrintfFormat(se->loc, se->toPtr(), argslice, isVa_list);
+ }
+ }
+ else if (fd && (fd->flags & FUNCFLAGscanf))
+ {
+ if (StringExp *se = (*arguments)[nparams - 1 - isVa_list]->isStringExp())
+ {
+ Expressions argslice;
+ argslice.reserve(nargs - nparams);
+ for (size_t i = nparams; i < nargs; i++)
+ argslice.push((*arguments)[i]);
+ checkPrintfFormat(se->loc, se->toPtr(), argslice, isVa_list);
+ }
+ }
+
+ /* Remaining problems:
+ * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
+ * implemented by calling a function) we'll defer this for now.
+ * 2. value structs (or static arrays of them) that need to be copy constructed
+ * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
+ * function gets called (functions normally destroy their parameters)
+ * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
+ * up properly. Pushing arguments on the stack then cannot fail.
+ */
+ if (1)
+ {
+ /* TODO: tackle problem 1)
+ */
+ const bool leftToRight = true; // TODO: something like !fd.isArrayOp
+ if (!leftToRight)
+ assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
+
+ const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
+ const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
+ const ptrdiff_t step = (leftToRight ? 1 : -1);
+
+ /* Compute indices of last throwing argument and first arg needing destruction.
+ * Used to not set up destructors unless an arg needs destruction on a throw
+ * in a later argument.
+ */
+ ptrdiff_t lastthrow = -1;
+ ptrdiff_t firstdtor = -1;
+ for (ptrdiff_t i = start; i != end; i += step)
+ {
+ Expression *arg = (*arguments)[i];
+ if (canThrow(arg, sc->func, false))
+ lastthrow = i;
+ if (firstdtor == -1 && arg->type->needsDestruction())
+ {
+ Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
+ if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
+ firstdtor = i;
+ }
+ }
+
+ /* Does problem 3) apply to this call?
+ */
+ const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
+ && (lastthrow - firstdtor) * step > 0);
+
+ /* If so, initialize 'eprefix' by declaring the gate
+ */
+ VarDeclaration *gate = NULL;
+ if (needsPrefix)
+ {
+ // eprefix => bool __gate [= false]
+ Identifier *idtmp = Identifier::generateId("__gate");
+ gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
+ gate->storage_class |= STCtemp | STCctfe | STCvolatile;
+ dsymbolSemantic(gate, sc);
+
+ Expression *ae = new DeclarationExp(loc, gate);
+ eprefix = expressionSemantic(ae, sc);
+ }
+
+ for (ptrdiff_t i = start; i != end; i += step)
+ {
+ Expression *arg = (*arguments)[i];
+
+ Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
+ const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
+ const bool isLazy = (parameter && (parameter->storageClass & STClazy));
+
+ /* Skip lazy parameters
+ */
+ if (isLazy)
+ continue;
+
+ /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
+ * Declare a temporary variable for this arg and append that declaration to 'eprefix',
+ * which will implicitly take care of potential problem 2) for this arg.
+ * 'eprefix' will therefore finally contain all args up to and including the last
+ * potentially throwing arg, excluding all lazy parameters.
+ */
+ if (gate)
+ {
+ const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
+
+ /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
+ */
+ VarDeclaration *tmp = copyToTemp(0,
+ needsDtor ? "__pfx" : "__pfy",
+ !isRef ? arg : arg->addressOf());
+ dsymbolSemantic(tmp, sc);
+
+ /* Modify the destructor so it only runs if gate==false, i.e.,
+ * only if there was a throw while constructing the args
+ */
+ if (!needsDtor)
+ {
+ if (tmp->edtor)
+ {
+ assert(i == lastthrow);
+ tmp->edtor = NULL;
+ }
+ }
+ else
+ {
+ // edtor => (__gate || edtor)
+ assert(tmp->edtor);
+ Expression *e = tmp->edtor;
+ e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
+ tmp->edtor = expressionSemantic(e, sc);
+ //printf("edtor: %s\n", tmp->edtor->toChars());
+ }
+
+ // eprefix => (eprefix, auto __pfx/y = arg)
+ DeclarationExp *ae = new DeclarationExp(loc, tmp);
+ eprefix = Expression::combine(eprefix, expressionSemantic(ae, sc));
+
+ // arg => __pfx/y
+ arg = new VarExp(loc, tmp);
+ arg = expressionSemantic(arg, sc);
+ if (isRef)
+ {
+ arg = new PtrExp(loc, arg);
+ arg = expressionSemantic(arg, sc);
+ }
+
+ /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
+ * i.e., disable the dtors right after constructing the last throwing arg.
+ * From now on, the callee will take care of destructing the args because
+ * the args are implicitly moved into function parameters.
+ *
+ * Set gate to null to let the next iterations know they don't need to
+ * append to eprefix anymore.
+ */
+ if (i == lastthrow)
+ {
+ Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
+ eprefix = Expression::combine(eprefix, expressionSemantic(e, sc));
+ gate = NULL;
+ }
+ }
+ else
+ {
+ /* No gate, no prefix to append to.
+ * Handle problem 2) by calling the copy constructor for value structs
+ * (or static arrays of them) if appropriate.
+ */
+ Type *tv = arg->type->baseElemOf();
+ if (!isRef && tv->ty == Tstruct)
+ arg = doCopyOrMove(sc, arg);
+ }
+
+ (*arguments)[i] = arg;
+ }
+ }
+ //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
+
+ // If D linkage and variadic, add _arguments[] as first argument
+ if (tf->isDstyleVariadic())
+ {
+ assert(arguments->length >= nparams);
+
+ Parameters *args = new Parameters;
+ args->setDim(arguments->length - nparams);
+ for (size_t i = 0; i < arguments->length - nparams; i++)
+ {
+ Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL, NULL);
+ (*args)[i] = arg;
+ }
+
+ TypeTuple *tup = new TypeTuple(args);
+ Expression *e = new TypeidExp(loc, tup);
+ e = expressionSemantic(e, sc);
+ arguments->insert(0, e);
+ }
+
+ Type *tret = tf->next;
+ if (isCtorCall)
+ {
+ //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
+ // wildmatch, tf->isWild(), fd->isolateReturn());
+ if (!tthis)
+ {
+ assert(sc->intypeof || global.errors);
+ tthis = fd->isThis()->type->addMod(fd->type->mod);
+ }
+ if (tf->isWild() && !fd->isolateReturn())
+ {
+ if (wildmatch)
+ tret = tret->substWildTo(wildmatch);
+ int offset;
+ if (!tret->implicitConvTo(tthis) &&
+ !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
+ {
+ const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
+ const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
+ ::error(loc, "inout constructor %s creates%s object, not%s",
+ fd->toPrettyChars(), s1, s2);
+ err = true;
+ }
+ }
+ tret = tthis;
+ }
+ else if (wildmatch && tret)
+ {
+ /* Adjust function return type based on wildmatch
+ */
+ //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
+ tret = tret->substWildTo(wildmatch);
+ }
+ *prettype = tret;
+ *peprefix = eprefix;
+ return (err || olderrors != global.errors);
+}
+
/**
* Determines whether a symbol represents a module or package
* (Used as a helper for is(type == module) and is(type == package))
@@ -134,6 +2049,8 @@ Package *resolveIsPackage(Dsymbol *sym)
}
pkg = imp->pkg;
}
+ else if (Module *mod = sym->isModule())
+ pkg = mod->isPackageFile ? mod->pkg : sym->isPackage();
else
pkg = sym->isPackage();
if (pkg)
@@ -141,6 +2058,25 @@ Package *resolveIsPackage(Dsymbol *sym)
return pkg;
}
+static Module *loadStdMath()
+{
+ static Import *impStdMath = NULL;
+ if (!impStdMath)
+ {
+ Identifiers *a = new Identifiers();
+ a->push(Id::std);
+ Import *s = new Import(Loc(), a, Id::math, NULL, false);
+ s->load(NULL);
+ if (s->mod)
+ {
+ s->mod->importAll(NULL);
+ dsymbolSemantic(s->mod, NULL);
+ }
+ impStdMath = s;
+ }
+ return impStdMath->mod;
+}
+
class ExpressionSemanticVisitor : public Visitor
{
public:
@@ -1938,7 +3874,7 @@ public:
void visit(HaltExp *e)
{
- e->type = Type::tvoid;
+ e->type = Type::tnoreturn;
result = e;
}
@@ -1959,7 +3895,9 @@ public:
Type *tded = NULL;
if (e->tok2 == TOKpackage || e->tok2 == TOKmodule) // These is() expressions are special because they can work on modules, not just types.
{
+ const unsigned oldErrors = global.startGagging();
Dsymbol *sym = e->targ->toDsymbol(sc);
+ global.endGagging(oldErrors);
if (sym == NULL)
goto Lno;
Package *p = resolveIsPackage(sym);
@@ -2292,7 +4230,7 @@ public:
if (exp->e1->op == TOKarraylength)
{
// arr.length op= e2;
- e = ArrayLengthExp::rewriteOpAssign(exp);
+ e = rewriteOpAssign(exp);
e = expressionSemantic(e, sc);
result = e;
return;
@@ -2382,27 +4320,39 @@ public:
result = ((BinExp *)e)->reorderSettingAAElem(sc);
}
- void visit(CompileExp *exp)
+private:
+ Expression *compileIt(CompileExp *exp)
{
- StringExp *se = semanticString(sc, exp->e1, "argument to mixin");
- if (!se)
- return setError();
- se = se->toUTF8(sc);
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, exp->exps))
+ return NULL;
+
unsigned errors = global.errors;
- Parser p(exp->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+ const size_t len = buf.length();
+ const char *str = buf.extractChars();
+ Parser p(exp->loc, sc->_module, (const utf8_t *)str, len, false);
p.nextToken();
//printf("p.loc.linnum = %d\n", p.loc.linnum);
+
Expression *e = p.parseExpression();
- if (p.errors)
- {
- assert(global.errors != errors); // should have caught all these cases
- return setError();
- }
+ if (global.errors != errors)
+ return NULL;
+
if (p.token.value != TOKeof)
{
- exp->error("incomplete mixin expression (%s)", se->toChars());
- return setError();
+ exp->error("incomplete mixin expression (%s)", str);
+ return NULL;
}
+ return e;
+ }
+
+public:
+ void visit(CompileExp *exp)
+ {
+ //printf("CompileExp::semantic('%s')\n", exp->toChars());
+ Expression *e = compileIt(exp);
+ if (!e)
+ return setError();
result = expressionSemantic(e, sc);
}
@@ -2508,6 +4458,8 @@ public:
if (exp->e1->isBool(false))
{
+ /* This is an `assert(0)` which means halt program execution
+ */
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
if (fd)
fd->hasReturnExp |= 4;
@@ -2525,8 +4477,10 @@ public:
result = e;
return;
}
+ exp->type = Type::tnoreturn;
}
- exp->type = Type::tvoid;
+ else
+ exp->type = Type::tvoid;
result = exp;
}
@@ -3484,7 +5438,8 @@ public:
return setError();
}
- if (!tf->callMatch(NULL, exp->arguments))
+ const char *failMessage = NULL;
+ if (!tf->callMatch(NULL, exp->arguments, 0, &failMessage))
{
OutBuffer buf;
@@ -3495,10 +5450,11 @@ public:
tthis->modToBuffer(&buf);
//printf("tf = %s, args = %s\n", tf->deco, (*exp->arguments)[0]->type->deco);
- ::error(exp->loc, "%s %s %s is not callable using argument types %s",
+ ::error(exp->loc, "%s `%s%s` is not callable using argument types `%s`",
p, exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
buf.peekChars());
-
+ if (failMessage)
+ errorSupplemental(exp->loc, failMessage);
return setError();
}
@@ -3553,13 +5509,14 @@ public:
assert(exp->f);
tiargs = NULL;
- if (ve->hasOverloads)
+ if (exp->f->overnext)
exp->f = resolveFuncCall(exp->loc, sc, exp->f, tiargs, NULL, exp->arguments, 2);
else
{
exp->f = exp->f->toAliasFunc();
TypeFunction *tf = (TypeFunction *)exp->f->type;
- if (!tf->callMatch(NULL, exp->arguments))
+ const char *failMessage = NULL;
+ if (!tf->callMatch(NULL, exp->arguments, 0, &failMessage))
{
OutBuffer buf;
@@ -3568,10 +5525,11 @@ public:
buf.writeByte(')');
//printf("tf = %s, args = %s\n", tf->deco, (*exp->arguments)[0]->type->deco);
- ::error(exp->loc, "%s %s is not callable using argument types %s",
- exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
+ ::error(exp->loc, "%s `%s%s` is not callable using argument types `%s`",
+ exp->f->kind(), exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
buf.peekChars());
-
+ if (failMessage)
+ errorSupplemental(exp->loc, failMessage);
exp->f = NULL;
}
}
@@ -3954,6 +5912,10 @@ public:
exp->e1 = exp->e1->castTo(sc, exp->type->pointerTo());
break;
+ case Tnull:
+ exp->type = Type::tnoreturn; // typeof(*null) is bottom type
+ break;
+
default:
exp->error("can only * a pointer, not a `%s`", exp->e1->type->toChars());
/* fall through */
@@ -7109,25 +9071,6 @@ public:
result = exp;
}
- Module *loadStdMath()
- {
- static Import *impStdMath = NULL;
- if (!impStdMath)
- {
- Identifiers *a = new Identifiers();
- a->push(Id::std);
- Import *s = new Import(Loc(), a, Id::math, NULL, false);
- s->load(NULL);
- if (s->mod)
- {
- s->mod->importAll(NULL);
- dsymbolSemantic(s->mod, NULL);
- }
- impStdMath = s;
- }
- return impStdMath->mod;
- }
-
void visit(PowExp *exp)
{
if (exp->type)
@@ -7579,7 +9522,7 @@ public:
exp->error("%s is not an expression", exp->e2->toChars());
return setError();
}
- if (e1x->op == TOKerror)
+ if (e1x->op == TOKerror || e1x->type->ty == Tnoreturn)
{
result = e1x;
return;
@@ -8032,10 +9975,18 @@ public:
Type *t1 = exp->e1->type;
Type *t2 = exp->e2->type;
+ if (t1->ty == Tnoreturn)
+ {
+ exp->type = t2;
+ }
+ else if (t2->ty == Tnoreturn)
+ {
+ exp->type = t1;
+ }
// If either operand is void the result is void, we have to cast both
// the expression to void so that we explicitly discard the expression
// value if any (bugzilla 16598)
- if (t1->ty == Tvoid || t2->ty == Tvoid)
+ else if (t1->ty == Tvoid || t2->ty == Tvoid)
{
exp->type = Type::tvoid;
exp->e1 = exp->e1->castTo(sc, exp->type);
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index 7a216a9..b8e1e31 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -1473,7 +1473,8 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
memset(&m, 0, sizeof(m));
m.last = MATCHnomatch;
- functionResolve(&m, s, loc, sc, tiargs, tthis, fargs);
+ const char *failMessage = NULL;
+ functionResolve(&m, s, loc, sc, tiargs, tthis, fargs, &failMessage);
if (m.last > MATCHnomatch && m.lastf)
{
@@ -1555,20 +1556,23 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
::error(loc, "none of the overloads of `%s` are callable using a %sobject, candidates are:",
fd->ident->toChars(), thisBuf.peekChars());
else
- ::error(loc, "%smethod %s is not callable using a %sobject",
+ ::error(loc, "%smethod `%s` is not callable using a %sobject",
funcBuf.peekChars(), fd->toPrettyChars(), thisBuf.peekChars());
}
else
{
//printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
if (hasOverloads)
- ::error(loc, "none of the overloads of `%s` are callable using argument types %s, candidates are:",
+ ::error(loc, "none of the overloads of `%s` are callable using argument types `%s`, candidates are:",
fd->ident->toChars(), fargsBuf.peekChars());
else
- fd->error(loc, "%s%s is not callable using argument types %s",
- parametersTypeToChars(tf->parameterList),
- tf->modToChars(),
- fargsBuf.peekChars());
+ {
+ fd->error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
+ fd->kind(), fd->toPrettyChars(), parametersTypeToChars(tf->parameterList),
+ tf->modToChars(), fargsBuf.peekChars());
+ if (failMessage)
+ errorSupplemental(loc, failMessage);
+ }
}
// Display candidate functions
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index a11c9c3..9eba88f 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -122,7 +122,7 @@ public:
void visit(CompileStatement *s)
{
buf->writestring("mixin(");
- s->exp->accept(this);
+ argsToBuffer(s->exps);
buf->writestring(");");
if (!hgs->forStmtInit)
buf->writenl();
@@ -1104,6 +1104,18 @@ public:
buf->writestring("typeof(null)");
}
+ void visit(TypeMixin *t)
+ {
+ buf->writestring("mixin(");
+ argsToBuffer(t->exps);
+ buf->writeByte(')');
+ }
+
+ void visit(TypeNoreturn *)
+ {
+ buf->writestring("noreturn");
+ }
+
////////////////////////////////////////////////////////////////////////////
void visit(Dsymbol *s)
@@ -1418,7 +1430,7 @@ public:
void visit(CompileDeclaration *d)
{
buf->writestring("mixin(");
- d->exp->accept(this);
+ argsToBuffer(d->exps);
buf->writestring(");");
buf->writenl();
}
@@ -2408,8 +2420,15 @@ public:
buf->writeByte(')');
if (target.ptrsize == 8)
goto L4;
- else
+ else if (target.ptrsize == 4 ||
+ target.ptrsize == 2)
goto L3;
+ else
+ assert(0);
+
+ case Tvoid:
+ buf->writestring("cast(void)0");
+ break;
default:
/* This can happen if errors, such as
@@ -2822,7 +2841,7 @@ public:
void visit(CompileExp *e)
{
buf->writestring("mixin(");
- expToBuffer(e->e1, PREC_assign);
+ argsToBuffer(e->exps);
buf->writeByte(')');
}
@@ -3528,6 +3547,13 @@ void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
}
}
+/*************************************************************
+ * Pretty print function parameters.
+ * Params:
+ * parameters = parameters to print, such as TypeFunction.parameters.
+ * varargs = kind of varargs, see TypeFunction.varargs.
+ * Returns: Null-terminated string representing parameters.
+ */
const char *parametersTypeToChars(ParameterList pl)
{
OutBuffer buf;
@@ -3536,3 +3562,26 @@ const char *parametersTypeToChars(ParameterList pl)
v.parametersToBuffer(pl.parameters, pl.varargs);
return buf.extractChars();
}
+
+/*************************************************************
+ * Pretty print function parameter.
+ * Params:
+ * parameter = parameter to print.
+ * tf = TypeFunction which holds parameter.
+ * fullQual = whether to fully qualify types.
+ * Returns: Null-terminated string representing parameters.
+ */
+const char *parameterToChars(Parameter *parameter, TypeFunction *tf, bool fullQual)
+{
+ OutBuffer buf;
+ HdrGenState hgs;
+ hgs.fullQual = fullQual;
+ PrettyPrintVisitor v(&buf, &hgs);
+
+ parameter->accept(&v);
+ if (tf->parameterList.varargs == 2 && parameter == tf->parameterList[tf->parameterList.parameters->length - 1])
+ {
+ buf.writestring("...");
+ }
+ return buf.extractChars();
+}
diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h
index d464d4a..6822aaf4 100644
--- a/gcc/d/dmd/hdrgen.h
+++ b/gcc/d/dmd/hdrgen.h
@@ -47,6 +47,7 @@ void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects);
void moduleToBuffer(OutBuffer *buf, Module *m);
const char *parametersTypeToChars(ParameterList pl);
+const char *parameterToChars(Parameter *parameter, TypeFunction *tf, bool fullQual);
bool stcToBuffer(OutBuffer *buf, StorageClass stc);
const char *stcToChars(StorageClass& stc);
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index 59faa99..0740653 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -86,10 +86,16 @@ Msgtable msgtable[] =
{ "__c_longlong", NULL },
{ "__c_ulonglong", NULL },
{ "__c_long_double", NULL },
+ { "__c_wchar_t", NULL },
+ { "__c_complex_float", NULL },
+ { "__c_complex_double", NULL },
+ { "__c_complex_real", NULL },
{ "cpp_type_info_ptr", "__cpp_type_info_ptr" },
{ "_assert", "assert" },
{ "_unittest", "unittest" },
{ "_body", "body" },
+ { "printf", NULL },
+ { "scanf", NULL },
{ "TypeInfo", NULL },
{ "TypeInfo_Class", NULL },
@@ -395,7 +401,6 @@ Msgtable msgtable[] =
{ "derivedMembers", NULL },
{ "isSame", NULL },
{ "compiles", NULL },
- { "parameters", NULL },
{ "getAliasThis", NULL },
{ "getAttributes", NULL },
{ "getFunctionAttributes", NULL },
@@ -411,6 +416,7 @@ Msgtable msgtable[] =
{ "getLocation", NULL },
{ "hasPostblit", NULL },
{ "isCopyable", NULL },
+ { "toType", NULL },
// For C++ mangling
{ "allocator", NULL },
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index e49ad15..07fb32a 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -47,6 +47,7 @@ public:
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void importAll(Scope *sc);
+ void addPackageAccess(ScopeDsymbol *scopesym);
Dsymbol *toAlias();
void addMember(Scope *sc, ScopeDsymbol *sds);
void setScope(Scope* sc);
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 03078b5e..1664492 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -75,6 +75,7 @@ public:
unsigned numlines; // number of lines in source file
int isDocFile; // if it is a documentation input file, not D source
bool isPackageFile; // if it is a package.d
+ Package *pkg; // if isPackageFile is true, the Package that contains this package.d
Strings contentImportedFiles; // array of files whose content was imported
int needmoduleinfo;
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index c1071b2..6b01999 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -39,6 +39,7 @@ Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expr
Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
Expression *typeToExpression(Type *t);
Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
+RootObject *compileTypeMixin(TypeMixin *tm, Loc loc, Scope *sc);
/***************************** Type *****************************/
@@ -93,6 +94,7 @@ Type *Type::tdchar;
Type *Type::tshiftcnt;
Type *Type::terror;
Type *Type::tnull;
+Type *Type::tnoreturn;
Type *Type::tsize_t;
Type *Type::tptrdiff_t;
@@ -195,6 +197,8 @@ void Type::_init()
sizeTy[Tnull] = sizeof(TypeNull);
sizeTy[Tvector] = sizeof(TypeVector);
sizeTy[Ttraits] = sizeof(TypeTraits);
+ sizeTy[Tmixin] = sizeof(TypeMixin);
+ sizeTy[Tnoreturn] = sizeof(TypeNoreturn);
initTypeMangle();
@@ -216,6 +220,10 @@ void Type::_init()
}
basic[Terror] = new TypeError();
+ tnoreturn = new TypeNoreturn();
+ tnoreturn->deco = tnoreturn->merge()->deco;
+ basic[Tnoreturn] = tnoreturn;
+
tvoid = basic[Tvoid];
tint8 = basic[Tint8];
tuns8 = basic[Tuns8];
@@ -246,7 +254,7 @@ void Type::_init()
tshiftcnt = tint32;
terror = basic[Terror];
- tnull = basic[Tnull];
+ tnoreturn = basic[Tnoreturn];
tnull = new TypeNull();
tnull->deco = tnull->merge()->deco;
@@ -2079,7 +2087,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
if (this != Type::terror)
{
if (s)
- error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident->toChars(), toChars(), s->toChars());
+ error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident->toChars(), toChars(), s->toPrettyChars());
else
error(loc, "no property `%s` for type `%s`", ident->toChars(), toChars());
}
@@ -2413,6 +2421,16 @@ TypeTraits *Type::isTypeTraits()
return ty == Ttraits ? (TypeTraits *)this : NULL;
}
+TypeMixin *Type::isTypeMixin()
+{
+ return ty == Tmixin ? (TypeMixin *)this : NULL;
+}
+
+TypeNoreturn *Type::isTypeNoreturn()
+{
+ return ty == Tnoreturn ? (TypeNoreturn *)this : NULL;
+}
+
TypeFunction *Type::toTypeFunction()
{
if (ty != Tfunction)
@@ -5175,16 +5193,47 @@ void TypeFunction::purityLevel()
tf->purity = purity;
}
+// arguments get specially formatted
+static const char *getParamError(TypeFunction *tf, Expression *arg, Parameter *par)
+{
+ if (global.gag && !global.params.showGaggedErrors)
+ return NULL;
+ // show qualification when toChars() is the same but types are different
+ const char *at = arg->type->toChars();
+ bool qual = !arg->type->equals(par->type) && strcmp(at, par->type->toChars()) == 0;
+ if (qual)
+ at = arg->type->toPrettyChars(true);
+ OutBuffer buf;
+ // only mention rvalue if it's relevant
+ const bool rv = !arg->isLvalue() && (par->storageClass & (STCref | STCout)) != 0;
+ buf.printf("cannot pass %sargument `%s` of type `%s` to parameter `%s`",
+ rv ? "rvalue " : "", arg->toChars(), at,
+ parameterToChars(par, tf, qual));
+ return buf.extractChars();
+}
+
+static const char *getMatchError(const char *format, ...)
+{
+ if (global.gag && !global.params.showGaggedErrors)
+ return NULL;
+ OutBuffer buf;
+ va_list ap;
+ va_start(ap, format);
+ buf.vprintf(format, ap);
+ return buf.extractChars();
+}
+
/********************************
* 'args' are being matched to function 'this'
* Determine match level.
* Input:
* flag 1 performing a partial ordering match
+ * pMessage address to store error message, or null
* Returns:
* MATCHxxxx
*/
-MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
+MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag, const char **pMessage)
{
//printf("TypeFunction::callMatch() %s\n", toChars());
MATCH match = MATCHexact; // assume exact match
@@ -5221,12 +5270,15 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
size_t nparams = parameterList.length();
size_t nargs = args ? args->length : 0;
- if (nparams == nargs)
- ;
- else if (nargs > nparams)
+ if (nargs > nparams)
{
if (parameterList.varargs == VARARGnone)
- goto Nomatch; // too many args; no match
+ {
+ // suppress early exit if an error message is wanted,
+ // so we can check any matching args are valid
+ if (!pMessage)
+ goto Nomatch; // too many args; no match
+ }
match = MATCHconvert; // match ... with a "conversion" match level
}
@@ -5309,7 +5361,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
if (m && !arg->isLvalue())
{
if (p->storageClass & STCout)
+ {
+ if (pMessage) *pMessage = getParamError(this, arg, p);
goto Nomatch;
+ }
if (arg->op == TOKstring && tp->ty == Tsarray)
{
@@ -5331,7 +5386,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
}
}
else
+ {
+ if (pMessage) *pMessage = getParamError(this, arg, p);
goto Nomatch;
+ }
}
/* Find most derived alias this type being matched.
@@ -5351,7 +5409,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
* ref T[dim] <- an lvalue of const(T[dim]) argument
*/
if (!ta->constConv(tp))
+ {
+ if (pMessage) *pMessage = getParamError(this, arg, p);
goto Nomatch;
+ }
}
}
@@ -5377,7 +5438,11 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
tsa = (TypeSArray *)tb;
sz = tsa->dim->toInteger();
if (sz != nargs - u)
+ {
+ if (pMessage)
+ *pMessage = getMatchError("expected %llu variadic argument(s), not %zu", sz, nargs - u);
goto Nomatch;
+ }
/* fall through */
case Tarray:
{
@@ -5408,7 +5473,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
m = arg->implicitConvTo(ta->next);
if (m == MATCHnomatch)
+ {
+ if (pMessage) *pMessage = getParamError(this, arg, p);
goto Nomatch;
+ }
if (m < match)
match = m;
}
@@ -5420,9 +5488,14 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
goto Ldone;
default:
- goto Nomatch;
+ break;
}
}
+ if (pMessage && u < nargs)
+ *pMessage = getParamError(this, (*args)[u], p);
+ else if (pMessage)
+ *pMessage = getMatchError("missing argument for parameter #%d: `%s`",
+ u + 1, parameterToChars(p, this, false));
goto Nomatch;
}
if (m < match)
@@ -5430,6 +5503,12 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
}
Ldone:
+ if (pMessage && !parameterList.varargs && nargs > nparams)
+ {
+ // all parameters had a match, but there are surplus args
+ *pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs);
+ goto Nomatch;
+ }
//printf("match = %d\n", match);
return match;
@@ -5797,6 +5876,20 @@ Type *TypeTraits::syntaxCopy()
return tt;
}
+Dsymbol *TypeTraits::toDsymbol(Scope *sc)
+{
+ Type *t = NULL;
+ Expression *e = NULL;
+ Dsymbol *s = NULL;
+ resolve(loc, sc, &e, &t, &s);
+ if (t && t->ty != Terror)
+ s = t->toDsymbol(sc);
+ else if (e)
+ s = getDsymbol(e);
+
+ return s;
+}
+
void TypeTraits::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool)
{
*pt = NULL;
@@ -5816,6 +5909,90 @@ d_uns64 TypeTraits::size(Loc)
return SIZE_INVALID;
}
+/***************************** TypeMixin *****************************/
+
+/******
+ * Implements mixin types.
+ *
+ * Semantic analysis will convert it to a real type.
+ */
+TypeMixin::TypeMixin(const Loc &loc, Expressions *exps)
+ : Type(Tmixin)
+{
+ this->loc = loc;
+ this->exps = exps;
+ this->obj = NULL; // cached result of semantic analysis.
+}
+
+const char *TypeMixin::kind()
+{
+ return "mixin";
+}
+
+Type *TypeMixin::syntaxCopy()
+{
+ return new TypeMixin(loc, Expression::arraySyntaxCopy(exps));
+}
+
+Dsymbol *TypeMixin::toDsymbol(Scope *sc)
+{
+ Type *t = NULL;
+ Expression *e = NULL;
+ Dsymbol *s = NULL;
+ resolve(loc, sc, &e, &t, &s);
+ if (t)
+ s = t->toDsymbol(sc);
+ else if (e)
+ s = getDsymbol(e);
+
+ return s;
+}
+
+void TypeMixin::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
+{
+ // if already resolved just set pe/pt/ps and return.
+ if (obj)
+ {
+ *pe = isExpression(obj);
+ *pt = isType(obj);
+ *ps = isDsymbol(obj);
+ return;
+ }
+
+ RootObject *o = compileTypeMixin(this, loc, sc);
+ if (Type *t = isType(o))
+ {
+ t->resolve(loc, sc, pe, pt, ps, intypeid);
+ if (*pt)
+ (*pt) = (*pt)->addMod(mod);
+ }
+ else if (Expression *e = isExpression(o))
+ {
+ e = expressionSemantic(e, sc);
+ if (TypeExp *et = e->isTypeExp())
+ {
+ *pe = NULL;
+ *pt = et->type->addMod(mod);
+ *ps = NULL;
+ }
+ else
+ {
+ *pe = e;
+ *pt = NULL;
+ *ps = NULL;
+ }
+ }
+ else
+ {
+ *pe = NULL;
+ *pt = Type::terror;
+ *ps = NULL;
+ }
+
+ // save the result
+ obj = *pe ? (RootObject *)*pe : (*pt ? (RootObject *)*pt : (RootObject *)*ps);
+}
+
/***************************** TypeQualified *****************************/
TypeQualified::TypeQualified(TY ty, Loc loc)
@@ -6003,11 +6180,25 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
Type *t = s->getType(); // type symbol, type alias, or type tuple?
unsigned errorsave = global.errors;
- Dsymbol *sm = s->searchX(loc, sc, id);
- if (sm && !(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, sm))
+ int flags = t == NULL ? SearchLocalsOnly : IgnorePrivateImports;
+ Dsymbol *sm = s->searchX(loc, sc, id, flags);
+ if (sm)
{
- ::error(loc, "`%s` is not visible from module `%s`", sm->toPrettyChars(), sc->_module->toChars());
- sm = NULL;
+ if (!(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, sm))
+ {
+ ::error(loc, "`%s` is not visible from module `%s`", sm->toPrettyChars(), sc->_module->toChars());
+ sm = NULL;
+ }
+ // Same check as in Expression::semanticY(DotIdExp)
+ else if (sm->isPackage() && checkAccess(sc, (Package *)sm))
+ {
+ // @@@DEPRECATED_2.096@@@
+ // Should be an error in 2.106. Just remove the deprecation call
+ // and uncomment the null assignment
+ ::deprecation(loc, "%s %s is not accessible here, perhaps add 'static import %s;'",
+ sm->kind(), sm->toPrettyChars(), sm->toPrettyChars());
+ //sm = null;
+ }
}
if (global.errors != errorsave)
{
@@ -6052,7 +6243,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
sm = t->toDsymbol(sc);
if (sm && id->dyncast() == DYNCAST_IDENTIFIER)
{
- sm = sm->search(loc, (Identifier *)id);
+ sm = sm->search(loc, (Identifier *)id, IgnorePrivateImports);
if (sm)
goto L2;
}
@@ -8177,6 +8368,49 @@ Expression *TypeNull::defaultInit(Loc)
return new NullExp(Loc(), Type::tnull);
}
+/***************************** TypeNoreturn *****************************/
+
+TypeNoreturn::TypeNoreturn()
+ : Type(Tnoreturn)
+{
+ //printf("TypeNoreturn %p\n", this);
+}
+
+const char *TypeNoreturn::kind()
+{
+ return "noreturn";
+}
+
+Type *TypeNoreturn::syntaxCopy()
+{
+ // No semantic analysis done, no need to copy
+ return this;
+}
+
+MATCH TypeNoreturn::implicitConvTo(Type *to)
+{
+ //printf("TypeNoreturn::implicitConvTo(this=%p, to=%p)\n", this, to);
+ //printf("from: %s\n", toChars());
+ //printf("to : %s\n", to.toChars());
+ MATCH m = Type::implicitConvTo(to);
+ return (m == MATCHexact) ? MATCHexact : MATCHconvert;
+}
+
+bool TypeNoreturn::isBoolean()
+{
+ return true; // bottom type can be implicitly converted to any other type
+}
+
+d_uns64 TypeNoreturn::size(Loc)
+{
+ return 0;
+}
+
+unsigned TypeNoreturn::alignsize()
+{
+ return 0;
+}
+
/***********************************************************
* Encapsulate Parameters* so .length and [i] can be used on it.
* https://dlang.org/spec/function.html#ParameterList
@@ -8472,3 +8706,25 @@ bool Parameter::isCovariantScope(bool returnByRef, StorageClass from, StorageCla
return covariant[SR::buildSR(returnByRef, from)][SR::buildSR(returnByRef, to)];
}
+
+/**
+ * For printing two types with qualification when necessary.
+ * Params:
+ * t1 = The first type to receive the type name for
+ * t2 = The second type to receive the type name for
+ * Returns:
+ * The fully-qualified names of both types if the two type names are not the same,
+ * or the unqualified names of both types if the two type names are the same.
+ */
+void toAutoQualChars(const char **result, Type *t1, Type *t2)
+{
+ const char *s1 = t1->toChars();
+ const char *s2 = t2->toChars();
+ if (strcmp(s1, s2) == 0)
+ {
+ s1 = t1->toPrettyChars(true);
+ s2 = t2->toPrettyChars(true);
+ }
+ result[0] = s1;
+ result[1] = s2;
+}
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 083d707..3687053 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -96,6 +96,8 @@ enum ENUMTY
Tint128,
Tuns128,
Ttraits,
+ Tmixin,
+ Tnoreturn,
TMAX
};
typedef unsigned char TY; // ENUMTY
@@ -201,6 +203,7 @@ public:
static Type *tdstring; // immutable(dchar)[]
static Type *terror; // for error recovery
static Type *tnull; // for null type
+ static Type *tnoreturn; // for bottom type typeof(*null)
static Type *tsize_t; // matches size_t alias
static Type *tptrdiff_t; // matches ptrdiff_t alias
@@ -367,7 +370,9 @@ public:
TypeTuple *isTypeTuple();
TypeSlice *isTypeSlice();
TypeNull *isTypeNull();
+ TypeMixin *isTypeMixin();
TypeTraits *isTypeTraits();
+ TypeNoreturn *isTypeNoreturn();
void accept(Visitor *v) { v->visit(this); }
};
@@ -686,7 +691,7 @@ public:
int attributesApply(void *param, int (*fp)(void *, const char *), TRUSTformat trustFormat = TRUSTformatDefault);
Type *substWildTo(unsigned mod);
- MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0);
+ MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0, const char **pMessage = NULL);
bool checkRetType(Loc loc);
Expression *defaultInit(Loc loc) /*const*/;
@@ -726,11 +731,27 @@ public:
TypeTraits(const Loc &loc, TraitsExp *exp);
Type *syntaxCopy();
+ Dsymbol *toDsymbol(Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
d_uns64 size(Loc loc);
void accept(Visitor *v) { v->visit(this); }
};
+class TypeMixin : public Type
+{
+public:
+ Loc loc;
+ Expressions *exps;
+ RootObject *obj;
+
+ TypeMixin(const Loc &loc, Expressions *exps);
+ const char *kind();
+ Type *syntaxCopy();
+ Dsymbol *toDsymbol(Scope *sc);
+ void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
+ void accept(Visitor *v) { v->visit(this); }
+};
+
class TypeQualified : public Type
{
public:
@@ -966,6 +987,21 @@ public:
void accept(Visitor *v) { v->visit(this); }
};
+class TypeNoreturn : public Type
+{
+public:
+ TypeNoreturn();
+ const char *kind();
+
+ Type *syntaxCopy();
+ MATCH implicitConvTo(Type *to);
+ bool isBoolean() /*const*/;
+
+ d_uns64 size(Loc loc) /*const*/;
+ unsigned alignsize();
+ void accept(Visitor *v) { v->visit(this); }
+};
+
/**************************************************************/
bool arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index c050b05..e1f1321 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -328,11 +328,9 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
{
// mixin(string)
nextToken();
- check(TOKlparen, "mixin");
- Expression *e = parseAssignExp();
- check(TOKrparen);
+ Expressions *exps = parseArguments();
check(TOKsemicolon);
- s = new CompileDeclaration(loc, e);
+ s = new CompileDeclaration(loc, exps);
break;
}
case TOKtemplate:
@@ -1336,7 +1334,7 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pc
}
else if (!Identifier::isValidIdentifier(name))
{
- error("expected valid identifer for C++ namespace but got `%s`", name);
+ error("expected valid identifier for C++ namespace but got `%s`", name);
idents = NULL;
break;
}
@@ -2922,6 +2920,18 @@ Objects *Parser::parseTemplateArguments()
return tiargs;
}
+/***************************************
+ * Parse a Type or an Expression
+ * Returns:
+ * RootObject representing the AST
+ */
+RootObject *Parser::parseTypeOrAssignExp(TOK endtoken)
+{
+ return isDeclaration(&token, 0, endtoken, NULL)
+ ? (RootObject *)parseType() // argument is a type
+ : (RootObject *)parseAssignExp(); // argument is an expression
+}
+
/******************************************
* Parse template argument list.
* Input:
@@ -2942,20 +2952,10 @@ Objects *Parser::parseTemplateArgumentList()
// Get TemplateArgumentList
while (token.value != endtok)
{
- // See if it is an Expression or a Type
- if (isDeclaration(&token, 0, TOKreserved, NULL))
- { // Template argument is a type
- Type *ta = parseType();
- tiargs->push(ta);
- }
- else
- { // Template argument is an expression
- Expression *ea = parseAssignExp();
- tiargs->push(ea);
- }
- if (token.value != TOKcomma)
- break;
- nextToken();
+ tiargs->push(parseTypeOrAssignExp());
+ if (token.value != TOKcomma)
+ break;
+ nextToken();
}
check(endtok, "template argument list");
return tiargs;
@@ -3288,6 +3288,15 @@ Type *Parser::parseBasicType(bool dontLookDotIdents)
}
break;
+ case TOKmixin:
+ // https://dlang.org/spec/expression.html#mixin_types
+ loc = token.loc;
+ nextToken();
+ if (token.value != TOKlparen)
+ error("found `%s` when expecting `%s` following %s", token.toChars(), Token::toChars(TOKlparen), "`mixin`");
+ t = new TypeMixin(loc, parseArguments());
+ break;
+
case TOKdot:
// Leading . as in .foo
t = parseBasicTypeStartingAt(new TypeIdentifier(token.loc, Id::empty), dontLookDotIdents);
@@ -3602,7 +3611,7 @@ Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident,
if (pident)
*pident = token.ident;
else
- error("unexpected identifer `%s` in declarator", token.ident->toChars());
+ error("unexpected identifier `%s` in declarator", token.ident->toChars());
ts = t;
nextToken();
break;
@@ -3863,6 +3872,21 @@ void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link,
}
}
+static void parseAttributes(Parser *p, bool &hasParsedAttributes,
+ StorageClass &storage_class, LINK &link, bool &setAlignment,
+ Expression *&ealign, Expressions *&udas)
+{
+ if (hasParsedAttributes) // only parse once
+ return;
+ hasParsedAttributes = true;
+ udas = NULL;
+ storage_class = STCundefined;
+ link = p->linkage;
+ setAlignment = false;
+ ealign = NULL;
+ p->parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
+}
+
/**********************************
* Parse Declarations.
* These can be:
@@ -3936,26 +3960,48 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
bool hasParsedAttributes = false;
if (token.value == TOKat)
{
- if (!hasParsedAttributes)
- {
- hasParsedAttributes = true;
- storage_class = STCundefined;
- link = linkage;
- setAlignment = false;
- ealign = NULL;
- udas = NULL;
- parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
- }
+ parseAttributes(this, hasParsedAttributes,
+ storage_class, link, setAlignment, ealign, udas);
}
Declaration *v;
- if (token.value == TOKfunction ||
+ Dsymbol *s;
+
+ // try to parse function type:
+ // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
+ bool attributesAppended = false;
+ const StorageClass funcStc = parseTypeCtor();
+ Token *tlu = &token;
+ if (token.value != TOKfunction &&
+ token.value != TOKdelegate &&
+ isBasicType(&tlu) && tlu &&
+ tlu->value == TOKlparen)
+ {
+ VarArg vargs;
+ Type *tret = parseBasicType();
+ Parameters *prms = parseParameters(&vargs);
+ ParameterList pl = ParameterList(prms, vargs);
+
+ parseAttributes(this, hasParsedAttributes,
+ storage_class, link, setAlignment, ealign, udas);
+ if (udas)
+ error("user-defined attributes not allowed for `alias` declarations");
+
+ attributesAppended = true;
+ storage_class = appendStorageClass(storage_class, funcStc);
+ Type *tf = new TypeFunction(pl, tret, link, storage_class);
+ v = new AliasDeclaration(loc, ident, tf);
+ }
+ else if (token.value == TOKfunction ||
token.value == TOKdelegate ||
(token.value == TOKlparen &&
skipAttributes(peekPastParen(&token), &tk) &&
(tk->value == TOKgoesto || tk->value == TOKlcurly)) ||
token.value == TOKlcurly ||
- (token.value == TOKidentifier && peekNext() == TOKgoesto))
+ (token.value == TOKidentifier && peekNext() == TOKgoesto) ||
+ (token.value == TOKref && peekNext() == TOKlparen &&
+ skipAttributes(peekPastParen(peek(&token)), &tk) &&
+ (tk->value == TOKgoesto || tk->value == TOKlcurly)))
{
// function (parameters) { statements... }
// delegate (parameters) { statements... }
@@ -3963,8 +4009,10 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
// (parameters) => expression
// { statements... }
// identifier => expression
+ // ref (parameters) { statements... }
+ // ref (parameters) => expression
- Dsymbol *s = parseFunctionLiteral();
+ s = parseFunctionLiteral();
if (udas != NULL)
{
@@ -3985,26 +4033,19 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
else
{
// StorageClasses type
- if (!hasParsedAttributes)
- {
- hasParsedAttributes = true;
- storage_class = STCundefined;
- link = linkage;
- setAlignment = false;
- ealign = NULL;
- udas = NULL;
- parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
- }
-
+ parseAttributes(this, hasParsedAttributes,
+ storage_class, link, setAlignment, ealign, udas);
if (udas)
error("user-defined attributes not allowed for %s declarations", Token::toChars(tok));
t = parseType();
v = new AliasDeclaration(loc, ident, t);
}
+ if (!attributesAppended)
+ storage_class = appendStorageClass(storage_class, funcStc);
v->storage_class = storage_class;
- Dsymbol *s = v;
+ s = v;
if (tpl)
{
Dsymbols *a2 = new Dsymbols();
@@ -4358,6 +4399,13 @@ Dsymbol *Parser::parseFunctionLiteral()
case TOKdelegate:
save = token.value;
nextToken();
+ if (token.value == TOKref)
+ {
+ // function ref (parameters) { statements... }
+ // delegate ref (parameters) { statements... }
+ stc = STCref;
+ nextToken();
+ }
if (token.value != TOKlparen && token.value != TOKlcurly)
{
// function type (parameters) { statements... }
@@ -4377,14 +4425,22 @@ Dsymbol *Parser::parseFunctionLiteral()
// delegate { statements... }
break;
}
- /* fall through */
+ goto LTOKlparen;
+
+ case TOKref:
+ // ref (parameters) => expression
+ // ref (parameters) { statements... }
+ stc = STCref;
+ nextToken();
+ goto LTOKlparen;
case TOKlparen:
+ LTOKlparen:
{
// (parameters) => expression
// (parameters) { statements... }
parameters = parseParameters(&varargs, &tpl);
- stc = parsePostfix(STCundefined, NULL);
+ stc = parsePostfix(stc, NULL);
if (StorageClass modStc = stc & STC_TYPECTOR)
{
if (save == TOKfunction)
@@ -5093,7 +5149,7 @@ Statement *Parser::parseForeach(Loc loc, bool *isRange, bool isDecl)
check(TOKrparen);
Loc endloc;
Statement *body = (!isDecl) ? parseStatement(0, NULL, &endloc) : NULL;
- if (isRange)
+ if (isRange)
*isRange = false;
return new ForeachStatement(loc, op, parameters, aggr, body, endloc);
}
@@ -5378,15 +5434,19 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
}
case TOKmixin:
- { Token *t = peek(&token);
+ {
+ if (isDeclaration(&token, 3, TOKreserved, NULL))
+ goto Ldeclaration;
+ Token *t = peek(&token);
if (t->value == TOKlparen)
- { // mixin(string)
+ {
+ // mixin(string)
Expression *e = parseAssignExp();
check(TOKsemicolon);
if (e->op == TOKmixin)
{
CompileExp *cpe = (CompileExp *)e;
- s = new CompileStatement(loc, cpe->e1);
+ s = new CompileStatement(loc, cpe->exps);
}
else
{
@@ -6332,6 +6392,7 @@ bool Parser::isBasicType(Token **pt)
case TOKtypeof:
case TOKvector:
+ case TOKmixin:
/* typeof(exp).identifier...
*/
t = peek(t);
@@ -6592,9 +6653,11 @@ bool Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, boo
case TOKin:
case TOKout:
case TOKdo:
+ LTOKdo:
// The !parens is to disallow unnecessary parentheses
if (!parens && (endtok == TOKreserved || endtok == t->value))
- { *pt = t;
+ {
+ *pt = t;
return true;
}
return false;
@@ -6602,6 +6665,12 @@ bool Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, boo
case TOKif:
return haveTpl ? true : false;
+ // Used for mixin type parsing
+ case TOKeof:
+ if (endtok == TOKeof)
+ goto LTOKdo;
+ return false;
+
default:
Ldefault:
return false;
@@ -7229,15 +7298,7 @@ Expression *Parser::parsePrimaryExp()
{
nextToken();
check(TOKlparen, "typeid");
- RootObject *o;
- if (isDeclaration(&token, 0, TOKreserved, NULL))
- { // argument is a type
- o = parseType();
- }
- else
- { // argument is an expression
- o = parseAssignExp();
- }
+ RootObject *o = parseTypeOrAssignExp();
check(TOKrparen);
e = new TypeidExp(loc, o);
break;
@@ -7279,6 +7340,14 @@ Expression *Parser::parsePrimaryExp()
if (token.value == TOKlparen)
{
nextToken();
+ if (token.value == TOKidentifier && peekNext() == TOKlparen)
+ {
+ error(loc, "unexpected `(` after `%s`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression", token.toChars());
+ nextToken();
+ Token *tempTok = peekPastParen(&token);
+ memcpy(&token, tempTok, sizeof(Token));
+ goto Lerr;
+ }
targ = parseType(&ident);
if (token.value == TOKcolon || token.value == TOKequal)
{
@@ -7357,11 +7426,11 @@ Expression *Parser::parsePrimaryExp()
case TOKmixin:
{
+ // https://dlang.org/spec/expression.html#mixin_expressions
nextToken();
- check(TOKlparen, "mixin");
- e = parseAssignExp();
- check(TOKrparen);
- e = new CompileExp(loc, e);
+ if (token.value != TOKlparen)
+ error("found `%s` when expecting `%s` following %s", token.toChars(), Token::toChars(TOKlparen), "`mixin`");
+ e = new CompileExp(loc, parseArguments());
break;
}
@@ -7379,6 +7448,24 @@ Expression *Parser::parsePrimaryExp()
e = parseNewExp(NULL);
break;
+ case TOKref:
+ {
+ if (peekNext() == TOKlparen)
+ {
+ Token *tk = peekPastParen(peek(&token));
+ if (skipAttributes(tk, &tk) &&
+ (tk->value == TOKgoesto || tk->value == TOKlcurly))
+ {
+ // ref (arguments) => expression
+ // ref (arguments) { statements... }
+ goto case_delegate;
+ }
+ }
+ nextToken();
+ error("found `%s` when expecting function literal following `ref`", token.toChars());
+ goto Lerr;
+ }
+
case TOKlparen:
{
Token *tk = peekPastParen(&token);
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
index 82ce325..a2ad478 100644
--- a/gcc/d/dmd/parse.h
+++ b/gcc/d/dmd/parse.h
@@ -83,6 +83,7 @@ public:
TemplateParameters *parseTemplateParameterList(int flag = 0);
Dsymbol *parseMixin();
Objects *parseTemplateArguments();
+ RootObject *parseTypeOrAssignExp(TOK endtoken = TOKreserved);
Objects *parseTemplateArgumentList();
Objects *parseTemplateSingleArgument();
StaticAssert *parseStaticAssert();
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index ea3bf38..ea3061b 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -66,6 +66,10 @@ enum PINLINE;
#define SCOPEfullinst 0x10000 // fully instantiate templates
#define SCOPEalias 0x20000 // inside alias declaration
+// The following are mutually exclusive
+#define SCOPEprintf 0x40000 // printf-style function
+#define SCOPEscanf 0x80000 // scanf-style function
+
struct Scope
{
Scope *enclosing; // enclosing Scope
diff --git a/gcc/d/dmd/semantic2.c b/gcc/d/dmd/semantic2.c
index 7bcf6ce..194a3fb 100644
--- a/gcc/d/dmd/semantic2.c
+++ b/gcc/d/dmd/semantic2.c
@@ -163,6 +163,15 @@ public:
if (vd->_init && !vd->toParent()->isFuncDeclaration())
{
vd->inuse++;
+
+ /* https://issues.dlang.org/show_bug.cgi?id=20280
+ *
+ * Template instances may import modules that have not
+ * finished semantic1.
+ */
+ if (!vd->type)
+ dsymbolSemantic(vd, sc);
+
// Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
vd->_init = initializerSemantic(vd->_init, sc, vd->type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
vd->inuse--;
@@ -265,6 +274,17 @@ public:
{
if (fd->semanticRun >= PASSsemantic2done)
return;
+
+ if (fd->semanticRun < PASSsemanticdone && !fd->errors)
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=21614
+ *
+ * Template instances may import modules that have not
+ * finished semantic1.
+ */
+ dsymbolSemantic(fd, sc);
+ }
+
assert(fd->semanticRun <= PASSsemantic2);
fd->semanticRun = PASSsemantic2;
diff --git a/gcc/d/dmd/semantic3.c b/gcc/d/dmd/semantic3.c
index 304eaee..6bd9a6d 100644
--- a/gcc/d/dmd/semantic3.c
+++ b/gcc/d/dmd/semantic3.c
@@ -850,32 +850,18 @@ public:
}
assert(!funcdecl->returnLabel);
}
+ else if (f->next->ty == Tnoreturn)
+ {
+ }
else
{
const bool inlineAsm = (funcdecl->hasReturnExp & 8) != 0;
if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
{
- Expression *e;
if (!funcdecl->hasReturnExp)
- funcdecl->error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
- else
- funcdecl->error("no return exp; or assert(0); at end of function");
- if (global.params.useAssert == CHECKENABLEon &&
- !global.params.useInline)
- {
- /* Add an assert(0, msg); where the missing return
- * should be.
- */
- e = new AssertExp(funcdecl->endloc,
- new IntegerExp(0),
- new StringExp(funcdecl->loc, const_cast<char *>("missing return expression")));
- }
+ funcdecl->error("has no `return` statement, but is expected to return a value of type `%s`", f->next->toChars());
else
- e = new HaltExp(funcdecl->endloc);
- e = new CommaExp(Loc(), e, f->next->defaultInit());
- e = expressionSemantic(e, sc2);
- Statement *s = new ExpStatement(Loc(), e);
- funcdecl->fbody = new CompoundStatement(Loc(), funcdecl->fbody, s);
+ funcdecl->error("no `return exp;` or `assert(0);` at end of function");
}
}
@@ -1162,15 +1148,7 @@ public:
if (cd)
{
- if (!global.params.is64bit &&
- global.params.isWindows &&
- !funcdecl->isStatic() && !sbody->usesEH() && !global.params.trace)
- {
- /* The back end uses the "jmonitor" hack for syncing;
- * no need to do the sync at this level.
- */
- }
- else
+ if (target.libraryObjectMonitors(funcdecl, sbody))
{
Expression *vsync;
if (funcdecl->isStatic())
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c
index 2f7b7e1..1f8e512 100644
--- a/gcc/d/dmd/statement.c
+++ b/gcc/d/dmd/statement.c
@@ -31,6 +31,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
Identifier *fixupLabelName(Scope *sc, Identifier *ident)
{
@@ -504,12 +505,19 @@ Statement *DtorExpStatement::syntaxCopy()
CompileStatement::CompileStatement(Loc loc, Expression *exp)
: Statement(loc)
{
- this->exp = exp;
+ this->exps = new Expressions();
+ this->exps->push(exp);
+}
+
+CompileStatement::CompileStatement(Loc loc, Expressions *exps)
+ : Statement(loc)
+{
+ this->exps = exps;
}
Statement *CompileStatement::syntaxCopy()
{
- return new CompileStatement(loc, exp->syntaxCopy());
+ return new CompileStatement(loc, Expression::arraySyntaxCopy(exps));
}
static Statements *errorStatements()
@@ -519,32 +527,36 @@ static Statements *errorStatements()
return a;
}
-Statements *CompileStatement::flatten(Scope *sc)
+static Statements *compileIt(CompileStatement *cs, Scope *sc)
{
- //printf("CompileStatement::flatten() %s\n", exp->toChars());
- StringExp *se = semanticString(sc, exp, "argument to mixin");
- if (!se)
+ //printf("CompileStatement::compileIt() %s\n", exp->toChars());
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, cs->exps))
return errorStatements();
- se = se->toUTF8(sc);
unsigned errors = global.errors;
- Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+ const size_t len = buf.length();
+ const char *str = buf.extractChars();
+ Parser p(cs->loc, sc->_module, (const utf8_t *)str, len, false);
p.nextToken();
Statements *a = new Statements();
while (p.token.value != TOKeof)
{
Statement *s = p.parseStatement(PSsemi | PScurlyscope);
- if (!s || p.errors)
- {
- assert(!p.errors || global.errors != errors); // make sure we caught all the cases
+ if (!s || global.errors != errors)
return errorStatements();
- }
a->push(s);
}
return a;
}
+Statements *CompileStatement::flatten(Scope *sc)
+{
+ //printf("CompileStatement::flatten() %s\n", exp->toChars());
+ return compileIt(this, sc);
+}
+
/******************************** CompoundStatement ***************************/
CompoundStatement::CompoundStatement(Loc loc, Statements *s)
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index 2d8b46c..c64e51a 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -173,9 +173,10 @@ public:
class CompileStatement : public Statement
{
public:
- Expression *exp;
+ Expressions *exps;
CompileStatement(Loc loc, Expression *exp);
+ CompileStatement(Loc loc, Expressions *exps);
Statement *syntaxCopy();
Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 5579c1c..491d9c9 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -581,7 +581,7 @@ public:
{
fs->error("constant value %s cannot be ref", ie->toChars());
}
- else
+ else
{
fs->error("constant value %s cannot be ref", ident->toChars());
}
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index a91880f..f8f977c 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -21,6 +21,7 @@ class Dsymbol;
class Expression;
class FuncDeclaration;
class Parameter;
+class Statement;
class Type;
class TypeFunction;
class TypeTuple;
@@ -30,6 +31,7 @@ struct TargetC
{
unsigned longsize; // size of a C 'long' or 'unsigned long' type
unsigned long_doublesize; // size of a C 'long double'
+ Type *twchar_t; // C 'wchar_t' type
};
struct TargetCPP
@@ -44,6 +46,7 @@ struct TargetCPP
const char *typeMangle(Type *t);
Type *parameterType(Parameter *p);
bool fundamentalType(const Type *t, bool& isFundamental);
+ unsigned derivedClassOffset(ClassDeclaration *baseClass);
};
struct TargetObjC
@@ -108,6 +111,7 @@ public:
TypeTuple *toArgTypes(Type *t);
bool isReturnOnStack(TypeFunction *tf, bool needsThis);
Expression *getTargetInfo(const char* name, const Loc& loc);
+ bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody);
};
extern Target target;
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index dac1e85..fb842ac 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -78,6 +78,7 @@ public:
bool ismixin; // template declaration is only to be used as a mixin
bool isstatic; // this is static template declaration
Prot protection;
+ int inuse; // for recursive expansion detection
TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack
diff --git a/gcc/d/dmd/templateparamsem.c b/gcc/d/dmd/templateparamsem.c
index 11cd52e..d3e9b23 100644
--- a/gcc/d/dmd/templateparamsem.c
+++ b/gcc/d/dmd/templateparamsem.c
@@ -25,7 +25,7 @@ public:
{
this->sc = sc;
this->parameters = parameters;
- this->result = false;
+ this->result = false;
}
void visit(TemplateTypeParameter *ttp)
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index b7c612c..99b5457 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -40,6 +40,8 @@ void freeFieldinit(Scope *sc);
Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
Package *resolveIsPackage(Dsymbol *sym);
Expression *typeToExpression(Type *t);
+Type *decoToType(const char *deco);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
/************************************************
@@ -442,7 +444,6 @@ TraitsInitializer::TraitsInitializer()
"derivedMembers",
"isSame",
"compiles",
- "parameters",
"getAliasThis",
"getAttributes",
"getFunctionAttributes",
@@ -1032,6 +1033,34 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
ex = expressionSemantic(ex, sc);
return ex;
}
+ else if (e->ident == Id::toType)
+ {
+ if (dim != 1)
+ return dimError(e, 1, dim);
+
+ Expression *ex = isExpression((*e->args)[0]);
+ if (!ex)
+ {
+ e->error("expression expected as second argument of __traits `%s`", e->ident->toChars());
+ return new ErrorExp();
+ }
+ ex = ex->ctfeInterpret();
+
+ StringExp *se = semanticString(sc, ex, "__traits(toType, string)");
+ if (!se)
+ {
+ return new ErrorExp();
+ }
+ Type *t = decoToType(se->toUTF8(sc)->toPtr());
+ if (!t)
+ {
+ e->error("cannot determine `%s`", e->toChars());
+ return new ErrorExp();
+ }
+ ex = new TypeExp(e->loc, t);
+ ex = expressionSemantic(ex, sc);
+ return ex;
+ }
else if (e->ident == Id::hasMember ||
e->ident == Id::getMember ||
e->ident == Id::getOverloads ||
@@ -1674,33 +1703,67 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
RootObject *o = (*e->args)[i];
Type *t = isType(o);
- Expression *ex = t ? typeToExpression(t) : isExpression(o);
- if (!ex && t)
+ while (t)
{
- Dsymbol *s;
- t->resolve(e->loc, sc2, &ex, &t, &s);
- if (t)
+ if (TypeMixin *tm = t->isTypeMixin())
{
- typeSemantic(t, e->loc, sc2);
- if (t->ty == Terror)
+ /* The mixin string could be a type or an expression.
+ * Have to try compiling it to see.
+ */
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, tm->exps))
+ {
+ err = true;
+ break;
+ }
+ const size_t len = buf.length();
+ const char *str = buf.extractChars();
+ Parser p(e->loc, sc->_module, (const utf8_t *)str, len, false);
+ p.nextToken();
+ //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
+ o = p.parseTypeOrAssignExp(TOKeof);
+ if (p.errors || p.token.value != TOKeof)
+ {
err = true;
+ break;
+ }
+ t = isType(o);
}
- else if (s && s->errors)
- err = true;
+ else
+ break;
}
- if (ex)
+
+ if (!err)
{
- ex = expressionSemantic(ex, sc2);
- ex = resolvePropertiesOnly(sc2, ex);
- ex = ex->optimize(WANTvalue);
- if (sc2->func && sc2->func->type->ty == Tfunction)
+ Expression *ex = t ? typeToExpression(t) : isExpression(o);
+ if (!ex && t)
{
- TypeFunction *tf = (TypeFunction *)sc2->func->type;
- canThrow(ex, sc2->func, tf->isnothrow);
+ Dsymbol *s;
+ t->resolve(e->loc, sc2, &ex, &t, &s);
+ if (t)
+ {
+ typeSemantic(t, e->loc, sc2);
+ if (t->ty == Terror)
+ err = true;
+ }
+ else if (s && s->errors)
+ err = true;
+ }
+ if (ex)
+ {
+ ex = expressionSemantic(ex, sc2);
+ ex = resolvePropertiesOnly(sc2, ex);
+ ex = ex->optimize(WANTvalue);
+ if (sc2->func && sc2->func->type->ty == Tfunction)
+ {
+ TypeFunction *tf = (TypeFunction *)sc2->func->type;
+ canThrow(ex, sc2->func, tf->isnothrow);
+ }
+ ex = checkGC(sc2, ex);
+ if (ex->op == TOKerror)
+ err = true;
}
- ex = checkGC(sc2, ex);
- if (ex->op == TOKerror)
- err = true;
}
// Carefully detach the scope from the parent and throw it away as
diff --git a/gcc/d/dmd/typesem.c b/gcc/d/dmd/typesem.c
index 496cfe3..670144d 100644
--- a/gcc/d/dmd/typesem.c
+++ b/gcc/d/dmd/typesem.c
@@ -18,6 +18,7 @@
#include "hdrgen.h"
#include "id.h"
#include "init.h"
+#include "parse.h"
#include "scope.h"
#include "target.h"
#include "template.h"
@@ -25,6 +26,7 @@
Expression *typeToExpression(Type *t);
Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
char *MODtoChars(MOD mod);
class TypeToExpressionVisitor : public Visitor
@@ -76,6 +78,11 @@ public:
{
result = typeToExpressionHelper(t, new ScopeExp(t->loc, t->tempinst));
}
+
+ void visit(TypeMixin *t)
+ {
+ result = new TypeExp(t->loc, t);
+ }
};
/* We've mistakenly parsed this as a type.
@@ -84,6 +91,8 @@ public:
*/
Expression *typeToExpression(Type *t)
{
+ if (t->mod)
+ return NULL;
TypeToExpressionVisitor v = TypeToExpressionVisitor(t);
t->accept(&v);
return v.result;
@@ -178,6 +187,48 @@ static Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *ex
}
/******************************************
+ * Compile the MixinType, returning the type or expression AST.
+ *
+ * Doesn't run semantic() on the returned object.
+ * Params:
+ * tm = mixin to compile as a type or expression
+ * loc = location for error messages
+ * sc = context
+ * Return:
+ * null if error, else RootObject AST as parsed
+ */
+RootObject *compileTypeMixin(TypeMixin *tm, Loc loc, Scope *sc)
+{
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, tm->exps))
+ return NULL;
+
+ const unsigned errors = global.errors;
+ const size_t len = buf.length();
+ const char *str = buf.extractChars();
+ Parser p(loc, sc->_module, (const utf8_t *)str, len, false);
+ p.nextToken();
+ //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
+ RootObject *o = p.parseTypeOrAssignExp(TOKeof);
+ if (errors != global.errors)
+ {
+ assert(global.errors != errors); // should have caught all these cases
+ return NULL;
+ }
+ if (p.token.value != TOKeof)
+ {
+ ::error(loc, "incomplete mixin type `%s`", str);
+ return NULL;
+ }
+
+ Type *t = isType(o);
+ Expression *e = t ? typeToExpression(t) : isExpression(o);
+
+ return (!e && t) ? (RootObject *)t : (RootObject *)e;
+}
+
+/******************************************
* Perform semantic analysis on a type.
* Params:
* type = Type AST node
@@ -440,7 +491,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
// Deal with the case where we thought the index was a type, but
// in reality it was an expression.
if (mtype->index->ty == Tident || mtype->index->ty == Tinstance || mtype->index->ty == Tsarray ||
- mtype->index->ty == Ttypeof || mtype->index->ty == Treturn)
+ mtype->index->ty == Ttypeof || mtype->index->ty == Treturn || mtype->index->ty == Tmixin)
{
Expression *e;
Type *t;
@@ -1072,6 +1123,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
mtype->exp->ident != Id::getMember &&
mtype->exp->ident != Id::parent &&
mtype->exp->ident != Id::child &&
+ mtype->exp->ident != Id::toType &&
mtype->exp->ident != Id::getOverloads &&
mtype->exp->ident != Id::getVirtualFunctions &&
mtype->exp->ident != Id::getVirtualMethods &&
@@ -1275,7 +1327,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
void visit(TypeStruct *mtype)
{
- //printf("TypeStruct::semantic('%s')\n", mtype->sym->toChars());
+ //printf("TypeStruct::semantic('%s')\n", mtype->toChars());
if (mtype->deco)
{
if (sc && sc->cppmangle != CPPMANGLEdefault)
@@ -1304,7 +1356,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
void visit(TypeClass *mtype)
{
- //printf("TypeClass::semantic(%s)\n", mtype->sym->toChars());
+ //printf("TypeClass::semantic(%s)\n", mtype->toChars());
if (mtype->deco)
{
if (sc && sc->cppmangle != CPPMANGLEdefault)
@@ -1386,6 +1438,25 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
Type *t = new TypeTuple(args);
result = typeSemantic(t, loc, sc);
}
+
+ void visit(TypeMixin *mtype)
+ {
+ //printf("TypeMixin::semantic() %s\n", mtype->toChars());
+
+ Expression *e = NULL;
+ Type *t = NULL;
+ Dsymbol *s = NULL;
+ mtype->resolve(loc, sc, &e, &t, &s);
+
+ if (t && t->ty != Terror)
+ {
+ result = t;
+ return;
+ }
+
+ ::error(mtype->loc, "`mixin(%s)` does not give a valid type", mtype->obj->toChars());
+ return error();
+ }
};
TypeSemanticVisitor v(loc, sc);
type->accept(&v);
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index a274e6f..09ba202 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -81,7 +81,9 @@ class TypeClass;
class TypeTuple;
class TypeSlice;
class TypeNull;
+class TypeNoreturn;
class TypeTraits;
+class TypeMixin;
class Dsymbol;
@@ -374,7 +376,9 @@ public:
virtual void visit(TypeTuple *t) { visit((Type *)t); }
virtual void visit(TypeSlice *t) { visit((TypeNext *)t); }
virtual void visit(TypeNull *t) { visit((Type *)t); }
+ virtual void visit(TypeNoreturn *t) { visit((Type *)t); }
virtual void visit(TypeTraits *t) { visit((Type *)t); }
+ virtual void visit(TypeMixin *t) { visit((Type *)t); }
virtual void visit(Dsymbol *) { assert(0); }
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index ee3e3d5..41d07a7 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -1068,6 +1068,13 @@ public:
add_stmt (return_expr (decl));
}
+ else if (tf->next->ty == Tnoreturn)
+ {
+ /* Returning an expression that has no value, but has a side effect
+ that should never return. */
+ add_stmt (build_expr_dtor (s->exp));
+ add_stmt (return_expr (NULL_TREE));
+ }
else
{
/* Convert for initializing the DECL_RESULT. */
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 3cddfc5..924d829 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -603,6 +603,12 @@ public:
t->ctype = ptr_type_node;
}
+ /* Bottom type used for functions that never return. */
+
+ void visit (TypeNoreturn *t)
+ {
+ t->ctype = void_type_node;
+ }
/* Basic Data Types. */
@@ -852,7 +858,46 @@ public:
tree basetype = (t->sym->memtype)
? build_ctype (t->sym->memtype) : void_type_node;
- if (!INTEGRAL_TYPE_P (basetype) || TREE_CODE (basetype) == BOOLEAN_TYPE)
+ if (t->sym->isSpecial ())
+ {
+ /* Special enums are opaque types that bind to C types. */
+ const char *ident = t->toChars ();
+ Type *underlying = NULL;
+
+ /* Skip over the prefixing `__c_'. */
+ gcc_assert (strncmp (ident, "__c_", strlen ("__c_")) == 0);
+ ident = ident + strlen ("__c_");
+
+ /* To keep things compatible within the code generation we stick to
+ mapping to equivalent D types. However it should be OK to use the
+ GCC provided C types here as the front-end enforces that everything
+ must be explicitly cast from a D type to any of the opaque types. */
+ if (strcmp (ident, "long") == 0)
+ underlying = build_frontend_type (long_integer_type_node);
+ else if (strcmp (ident, "ulong") == 0)
+ underlying = build_frontend_type (long_unsigned_type_node);
+ else if (strcmp (ident, "wchar_t") == 0)
+ underlying = target.c.twchar_t;
+ else if (strcmp (ident, "longlong") == 0)
+ underlying = build_frontend_type (long_long_integer_type_node);
+ else if (strcmp (ident, "ulonglong") == 0)
+ underlying = build_frontend_type (long_long_unsigned_type_node);
+ else if (strcmp (ident, "long_double") == 0)
+ underlying = build_frontend_type (long_double_type_node);
+ else if (strcmp (ident, "complex_real") == 0)
+ underlying = build_frontend_type (complex_long_double_type_node);
+ else if (strcmp (ident, "complex_float") == 0)
+ underlying = build_frontend_type (complex_float_type_node);
+ else if (strcmp (ident, "complex_double") == 0)
+ underlying = build_frontend_type (complex_double_type_node);
+
+ /* Conversion failed or there's an unhandled special type. */
+ gcc_assert (underlying != NULL);
+
+ t->ctype = build_variant_type_copy (build_ctype (underlying));
+ build_type_decl (t->ctype, t->sym);
+ }
+ else if (!INTEGRAL_TYPE_P (basetype) || TREE_CODE (basetype) == BOOLEAN_TYPE)
{
/* Enums in D2 can have a base type that is not necessarily integral.
For these, we simplify this a little by using the base type directly
diff --git a/gcc/testsuite/gdc.test/compilable/bug20796.d b/gcc/testsuite/gdc.test/compilable/bug20796.d
new file mode 100644
index 0000000..00d00c8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/bug20796.d
@@ -0,0 +1,2 @@
+// EXTRA_SOURCES: protection/issue20796/package.d
+// https://issues.dlang.org/show_bug.cgi?id=20796
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle.d b/gcc/testsuite/gdc.test/compilable/cppmangle.d
index 7fcd41ab..954a9be 100644
--- a/gcc/testsuite/gdc.test/compilable/cppmangle.d
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle.d
@@ -372,3 +372,21 @@ version (Posix)
static assert(T.boo.mangleof == "_ZN1T3booE");
}
+/*****************************************/
+
+alias noreturn = typeof(*null);
+
+extern (C++)
+{
+ alias fpcpp = noreturn function();
+ int funccpp(fpcpp);
+
+ version (Posix)
+ static assert(funccpp.mangleof == "_Z7funccppPFvvE");
+
+ version (Win32)
+ static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
+
+ version (Win64)
+ static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/ddocunittest.d b/gcc/testsuite/gdc.test/compilable/ddocunittest.d
index 940ef1c..8c691b6 100644
--- a/gcc/testsuite/gdc.test/compilable/ddocunittest.d
+++ b/gcc/testsuite/gdc.test/compilable/ddocunittest.d
@@ -357,6 +357,7 @@ auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
}
/// ditto
auto redBlackTree(alias less, E)(E[] elems...)
+if (__traits(compiles, (E a, E b) => mixin(less)))
{
return 3;
}
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d b/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
index 9ade317..62de518 100644
--- a/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
+++ b/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
@@ -3,6 +3,12 @@ class Controller {
enum _s_pkg = __traits(parent, __traits(parent, __traits(parent, T))).stringof["package ".length .. $];
enum _s_model = T.stringof[0 .. $-`Controller`.length] ~ `Model`;
+
+ import serenity7190.core.Model;
+ // expands to "import example7190.models.HomeModel;"
+ mixin(q{import } ~ _s_pkg ~ q{.models.} ~ _s_model ~ q{;});
+
+ // "enum _ = is(example7190.models.HomeModel.HomeModel : serenity7190.core.Model.Model);"
mixin(q{enum _ = is(} ~ _s_pkg ~ q{.models.} ~ _s_model ~ q{.} ~ _s_model ~ q{ : serenity7190.core.Model.Model);});
}
-} \ No newline at end of file
+}
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d b/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d
new file mode 100644
index 0000000..edb40954
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d
@@ -0,0 +1,12 @@
+module test20280a;
+
+struct Alpha(uint _)
+{
+ import test20280a;
+}
+
+struct Foxtrot(uint _)
+{
+ alias Attributes = Alpha!10;
+ enum A = 10;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/fix21585.d b/gcc/testsuite/gdc.test/compilable/fix21585.d
new file mode 100644
index 0000000..a83fb89
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix21585.d
@@ -0,0 +1,24 @@
+/* TEST_OUTPUT:
+---
+i int
+d double
+Pi int*
+---
+*/
+
+pragma(msg, 1.mangleof, " ", __traits(toType, 1.mangleof));
+pragma(msg, (1.0).mangleof, " ", __traits(toType, (1.0).mangleof));
+pragma(msg, (int*).mangleof, " ", __traits(toType, (int*).mangleof));
+
+template Type(T) { alias Type = T; }
+
+Type!(__traits(toType, 1.mangleof)) j = 3;
+
+alias T = Type!(__traits(toType, 1.mangleof));
+static assert(is(T == int));
+
+__traits(toType, "i") x = 7;
+
+static assert(is(Type!(__traits(toType, 1.mangleof)) == int));
+static assert(is(Type!(__traits(toType, (1.0).mangleof)) == double));
+static assert(is(Type!(__traits(toType, (int*).mangleof)) == int*));
diff --git a/gcc/testsuite/gdc.test/compilable/fix21647.d b/gcc/testsuite/gdc.test/compilable/fix21647.d
new file mode 100644
index 0000000..c129fa0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix21647.d
@@ -0,0 +1,30 @@
+/*
+REQUIRED_ARGS:
+TEST_OUTPUT:
+---
+cast(void)0
+cast(void)0
+void
+cast(void)0
+cast(void)0
+cast(void)0
+void
+---
+*/
+
+
+// https://issues.dlang.org/show_bug.cgi?id=21647
+
+void foo() { return cast(void)1; }
+
+void main(){}
+
+alias V = void;
+
+void test1() { pragma(msg, foo()); }
+void test2() { pragma(msg, main()); }
+void test3() { pragma(msg, V); }
+
+pragma(msg, foo());
+pragma(msg, main());
+pragma(msg, V);
diff --git a/gcc/testsuite/gdc.test/compilable/ice10598.d b/gcc/testsuite/gdc.test/compilable/ice10598.d
deleted file mode 100644
index 58a7c3b..0000000
--- a/gcc/testsuite/gdc.test/compilable/ice10598.d
+++ /dev/null
@@ -1,3 +0,0 @@
-// EXTRA_SOURCES: imports/ice10598a.d imports/ice10598b.d
-
-void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d b/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d
new file mode 100644
index 0000000..ee3c9eb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d
@@ -0,0 +1,22 @@
+module imports.issue21614a;
+
+struct FormatSpec(Char)
+{
+ import imports.issue21614a;
+}
+
+template Tuple(Specs...)
+{
+ struct Tuple
+ {
+ alias spec = FormatSpec!char();
+ this(Specs)
+ {
+ }
+ }
+}
+
+auto findRoot(T)(T)
+{
+ return Tuple!(T)();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d b/gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d b/gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d b/gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test20530a.d b/gcc/testsuite/gdc.test/compilable/imports/test20530a.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test20530a.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21501b.d b/gcc/testsuite/gdc.test/compilable/imports/test21501b.d
new file mode 100644
index 0000000..c1f8fab
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21501b.d
@@ -0,0 +1,7 @@
+module imports.test21501b;
+import test21501a;
+
+struct B
+{
+ A data;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21501c.d b/gcc/testsuite/gdc.test/compilable/imports/test21501c.d
new file mode 100644
index 0000000..cc1f95f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21501c.d
@@ -0,0 +1,4 @@
+module imports.test21501c;
+
+alias C = int;
+const D = 1;
diff --git a/gcc/testsuite/gdc.test/compilable/issue16020.d b/gcc/testsuite/gdc.test/compilable/issue16020.d
new file mode 100644
index 0000000..cfd078c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue16020.d
@@ -0,0 +1,39 @@
+module issue16020;
+
+alias F1 = const(int)(); const(int) f1(){return 42;}
+static assert (is(F1 == typeof(f1)));
+
+alias F2 = float(float); float f2(float p){return p;}
+static assert (is(F2 == typeof(f2)));
+
+alias F3 = void(); void f3(){}
+static assert (is(F3 == typeof(f3)));
+
+alias void F41() @safe;
+alias F42 = void() @safe;
+alias F43 = @safe void();
+static assert (is(F41 == F42));
+static assert (is(F43 == F42));
+
+alias void F51() @system;
+alias F52 = void() @safe;
+static assert (!is(F51 == F52));
+
+alias F61 = int() const shared;
+alias int F62() const shared ;
+alias F63 = const shared int();
+static assert (is(F61 == F62));
+static assert (is(F63 == F62));
+
+alias F71 = int() immutable inout;
+alias int F72() immutable inout;
+alias F73 = immutable inout int();
+static assert (is(F71 == F72));
+static assert (is(F73 == F72));
+
+alias FunTemplate(T) = void(T t);
+alias Specialized = FunTemplate!int;
+alias Compared = void(int);
+static assert(is(Specialized == Compared));
+
+void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21614.d b/gcc/testsuite/gdc.test/compilable/issue21614.d
new file mode 100644
index 0000000..1843fe6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue21614.d
@@ -0,0 +1,10 @@
+// EXTRA_FILES: imports/issue21614a.d
+// REQUIRED_ARGS: -i
+
+// https://issues.dlang.org/show_bug.cgi?id=21614
+
+void logmdigammaInverse(real y)
+{
+ import imports.issue21614a;
+ findRoot(y);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21726.d b/gcc/testsuite/gdc.test/compilable/issue21726.d
new file mode 100644
index 0000000..c8a8675
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue21726.d
@@ -0,0 +1,2 @@
+// EXTRA_SOURCES: protection/issue21726/typecons.d
+// https://issues.dlang.org/show_bug.cgi?id=21726
diff --git a/gcc/testsuite/gdc.test/compilable/mixintype.d b/gcc/testsuite/gdc.test/compilable/mixintype.d
new file mode 100644
index 0000000..abbf85a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/mixintype.d
@@ -0,0 +1,55 @@
+
+alias Int = mixin("int");
+alias Lint = mixin("Int");
+
+int test1(mixin("int")* p)
+{
+ mixin("int")[] a;
+ mixin("int[]") b;
+ mixin("int[] c;");
+ mixin("*p = c[0];");
+ *p = mixin("c[0]");
+ return *p + a[0] + b[0] + c[0];
+}
+
+/******************************************/
+
+void test2()
+{
+ auto a = __traits(allMembers, mixin(__MODULE__));
+}
+
+/*****************************************/
+
+void test3()
+{
+ char val;
+ int mod;
+ enum b = __traits(compiles, mixin("*cast(int*)&val + mod"));
+ static assert(b == true);
+}
+
+/********************************************/
+
+
+struct S
+{
+ int fielda;
+ int fieldb;
+}
+
+template Foo4(alias T)
+{
+ enum Foo4 = true;
+}
+
+void test4()
+{
+ S sa;
+ auto a = Foo4!( __traits(getMember,sa,"fielda") );
+
+ S sb;
+ enum getStuff = q{ __traits(getMember,sb,"fieldb") };
+ auto b = Foo4!(mixin(getStuff));
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/mixintype2.d b/gcc/testsuite/gdc.test/compilable/mixintype2.d
new file mode 100644
index 0000000..43803df
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/mixintype2.d
@@ -0,0 +1,68 @@
+
+alias fun = mixin("(){}");
+
+void test1()
+{
+ int x = 1;
+ static immutable c = 2;
+
+ fun();
+ foo!(mixin("int"))();
+ foo!(mixin("long*"))();
+ foo!(mixin("ST!(int, S.T)"))();
+ foo!(mixin(ST!(int, S.T)))();
+
+ int[mixin("string")] a1;
+ int[mixin("5")] a2;
+ int[mixin("c")] a3;
+ int[] v1 = new int[mixin("3")];
+ auto v2 = new int[mixin("x")];
+
+ mixin(q{__traits(getMember, S, "T")}) ftv;
+
+ alias T = int*;
+ static assert(__traits(compiles, mixin("int")));
+ static assert(__traits(compiles, mixin(q{int[mixin("string")]})));
+ static assert(__traits(compiles, mixin(q{int[mixin("2")]})));
+ static assert(__traits(compiles, mixin(T)));
+ static assert(__traits(compiles, mixin("int*")));
+ static assert(__traits(compiles, mixin(typeof(0))));
+}
+
+struct S { alias T = float*; }
+
+struct ST(X,Y) {}
+
+void foo(alias t)() {}
+
+/**************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=21074
+
+alias Byte = ubyte;
+alias Byte2(A) = ubyte;
+alias T0 = mixin(q{const(Byte)})*;
+alias T1 = mixin(q{const(Byte[1])})*;
+alias T2 = mixin(q{const(Byte2!int)})*;
+alias T3 = mixin(q{const(mixin(Byte2!int))})*;
+alias T4 = mixin(q{const(mixin("__traits(getMember, S, \"T\")"))})*;
+alias T5 = const(mixin(q{Byte}))*;
+alias T6 = const(mixin(q{immutable(Byte)}))*;
+alias T7 = const(mixin(q{shared(Byte)}))*;
+alias T8 = const(mixin(q{Byte*}));
+
+// the following tests now work
+static assert(is(T0 == const(ubyte)*));
+static assert(is(T1 == const(ubyte[1])*));
+static assert(is(T2 == const(ubyte)*));
+static assert(is(T3 == const(ubyte)*));
+static assert(is(T4 == const(float*)*));
+static assert(is(T5 == const(ubyte)*));
+static assert(is(T6 == immutable(ubyte)*));
+static assert(is(T7 == const(shared(ubyte))*));
+static assert(is(T8 == const(ubyte*)));
+
+// this doesn't work but I'll file a new issue
+/*
+alias T8 = mixin(q{immutable(__traits(getMember, S, "T"))})*;
+static assert(is(T8 == immutable(float*)*));
+*/
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
new file mode 100644
index 0000000..e21adc4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -0,0 +1,21 @@
+/*
+TEST_OUTPUT:
+---
+noreturn
+---
+*/
+
+alias noreturn = typeof(*null);
+pragma(msg, noreturn);
+
+noreturn exits(int* p) { *p = 3; }
+
+noreturn exit();
+
+int test1(int i)
+{
+ if (exit())
+ return i + 1;
+ return i - 1;
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d
new file mode 100644
index 0000000..d0b5f5a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d
@@ -0,0 +1,5 @@
+module issue20796;
+
+package(issue20796) void foo()
+{
+}
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d
new file mode 100644
index 0000000..e0f6ba7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d
@@ -0,0 +1,7 @@
+module protection.issue21726.format;
+
+package(protection.issue21726.format):
+
+package(protection.issue21726) int issuePkgSym;
+package(protection) int protectionPkgSym();
+int formatPkgSym;
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d
new file mode 100644
index 0000000..f8986c9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d
@@ -0,0 +1 @@
+module protection.issue21726;
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d
new file mode 100644
index 0000000..faed95e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d
@@ -0,0 +1,6 @@
+module protection.issue21726.typecons;
+
+import protection.issue21726.format : issuePkgSym;
+import protection.issue21726.format : protectionPkgSym;
+static assert(!__traits(compiles,
+ { import protection.issue21726.format : formatPkgSym; }));
diff --git a/gcc/testsuite/gdc.test/compilable/test16002.d b/gcc/testsuite/gdc.test/compilable/test16002.d
index f3303c0..f7b4c2e 100644
--- a/gcc/testsuite/gdc.test/compilable/test16002.d
+++ b/gcc/testsuite/gdc.test/compilable/test16002.d
@@ -22,3 +22,6 @@ static assert(is(b == module));
// This is supposed to work even though we haven't directly imported imports.pkgmodule.
static assert(is(imports.pkgmodule == module));
static assert(!is(MyStruct == module));
+
+static assert(!is(imports.nonexistent == package));
+static assert(!is(imports.nonexistent == module));
diff --git a/gcc/testsuite/gdc.test/compilable/test17991.d b/gcc/testsuite/gdc.test/compilable/test17991.d
new file mode 100644
index 0000000..8bc9fa9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test17991.d
@@ -0,0 +1,3 @@
+// https://issues.dlang.org/show_bug.cgi?id=17991
+// EXTRA_FILES: imports/test17991a/package.d imports/test17991a/a.d
+import imports.test17991a, imports.test17991a.a;
diff --git a/gcc/testsuite/gdc.test/compilable/test19292.d b/gcc/testsuite/gdc.test/compilable/test19292.d
new file mode 100644
index 0000000..8122851
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19292.d
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=19292
+
+mixin("enum a = ", 87, ";");
+static assert(a == 87);
+
+int test()
+{
+ mixin("enum x = ", 7, ";");
+ return mixin("1", x, 2U);
+}
+
+void testit()
+{
+ static assert(test() == 172);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test20151a.d b/gcc/testsuite/gdc.test/compilable/test20151a.d
new file mode 100644
index 0000000..d9ae28f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20151a.d
@@ -0,0 +1,3 @@
+// EXTRA_FILES: imports/test20151a/b/c/c.d
+module imports.test20151a;
+import imports.test20151a.b.c.c;
diff --git a/gcc/testsuite/gdc.test/compilable/test20280.d b/gcc/testsuite/gdc.test/compilable/test20280.d
new file mode 100644
index 0000000..76a1082
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20280.d
@@ -0,0 +1,8 @@
+// PERMUTE_ARGS:
+// REQUIRED_ARGS: -Icompilable/extra-files
+// EXTRA_FILES: extra-files/test20280a.d
+module test20280;
+
+import test20280a;
+
+alias Charlie = Foxtrot!(0);
diff --git a/gcc/testsuite/gdc.test/compilable/test20530.d b/gcc/testsuite/gdc.test/compilable/test20530.d
new file mode 100644
index 0000000..be80dbb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20530.d
@@ -0,0 +1,46 @@
+// EXTRA_FILES: imports/test20530a.d imports/plainpackage/plainmodule.d imports/pkgmodule/package.d imports/pkgmodule/plainmodule.d
+module mod;
+static assert(is(mod == module));
+static assert(is(mixin("mod") == module));
+static assert(!is(mod == package));
+static assert(!is(mixin("mod") == package));
+
+import imports.test20530a;
+static assert(is(imports == package));
+static assert(is(mixin("imports") == package));
+static assert(!is(imports == module));
+static assert(!is(mixin("imports") == module));
+
+import imports.plainpackage.plainmodule;
+import imports.pkgmodule.plainmodule;
+
+struct MyStruct;
+
+alias a = mixin("imports.plainpackage");
+alias b = mixin("imports.pkgmodule.plainmodule");
+
+static assert(is(mixin("imports.plainpackage") == package));
+static assert(is(mixin("a") == package));
+static assert(!is(mixin("imports.plainpackage.plainmodule") == package));
+static assert(!is(mixin("b") == package));
+static assert(is(mixin("imports.pkgmodule") == package));
+mixin("static assert(is(imports.pkgmodule == package));");
+
+static assert(!is(mixin("MyStruct") == package));
+
+static assert(!is(mixin("imports.plainpackage") == module));
+static assert(!is(mixin("a") == module));
+static assert(is(mixin("imports.plainpackage.plainmodule") == module));
+static assert(is(mixin("b") == module));
+static assert(is(mixin("imports.pkgmodule") == module));
+mixin("static assert(is(imports.pkgmodule == module));");
+
+static assert(!is(mixin("MyStruct") == module));
+
+static assert(!is(mixin("imports.nonexistent") == package));
+static assert(!is(mixin("imports.nonexistent") == module));
+
+// this won't work due to mixin argument .stringof expansion,
+// it will expand to mixin(package imports.pkgmodule). Issue 20519.
+//static assert(is(mixin(imports.pkgmodule) == package));
+//static assert(is(mixin(imports.pkgmodule) == module));
diff --git a/gcc/testsuite/gdc.test/compilable/test20537.d b/gcc/testsuite/gdc.test/compilable/test20537.d
new file mode 100644
index 0000000..f2d05d2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20537.d
@@ -0,0 +1,10 @@
+// REQUIRED_ARGS: -Icompilable/imports
+// EXTRA_FILES: imports/pkg20537/package.d
+import pkg20537;
+
+static assert(is(pkg20537 == module));
+static assert(__traits(isModule, pkg20537));
+static assert(is(mixin("pkg20537") == module));
+static assert(is(pkg20537 == package));
+static assert(__traits(isPackage, pkg20537));
+static assert(is(mixin("pkg20537") == package));
diff --git a/gcc/testsuite/gdc.test/compilable/test20692.d b/gcc/testsuite/gdc.test/compilable/test20692.d
new file mode 100644
index 0000000..2d67211
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20692.d
@@ -0,0 +1,18 @@
+// https://issues.dlang.org/show_bug.cgi?id=20692
+
+struct S() {
+ void fun() {
+ gun("");
+ }
+ void gun(T)(T) {
+ alias buggy = bug;
+ }
+}
+
+alias X = S!();
+
+void main() {
+ X().gun(0);
+}
+
+alias bug = __traits(getMember, X, "fun");
diff --git a/gcc/testsuite/gdc.test/compilable/test21501a.d b/gcc/testsuite/gdc.test/compilable/test21501a.d
new file mode 100644
index 0000000..096fd51
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21501a.d
@@ -0,0 +1,19 @@
+// EXTRA_SOURCES: imports/test21501b.d imports/test21501c.d
+// https://issues.dlang.org/show_bug.cgi?id=21501
+
+module test21501a;
+import imports.test21501b;
+import imports.test21501c;
+
+alias Identity(alias T) = T;
+
+struct A
+{
+ alias a = imports.test21501c.C;
+ const int b = imports.test21501c.D; // fixed
+ alias c = Identity!(mixin(q{imports.test21501c.C})); // fixed
+ const int d = Identity!(mixin(q{imports.test21501c.D})); // fixed
+
+ static assert(is(a == c) && is(a == int));
+ static assert(b == d && b == 1);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test9029.d b/gcc/testsuite/gdc.test/compilable/test9029.d
new file mode 100644
index 0000000..bbbd98a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test9029.d
@@ -0,0 +1,39 @@
+// https://issues.dlang.org/show_bug.cgi?id=9029
+enum NameOf(alias S) = S.stringof;
+
+static assert(NameOf!int == "int");
+
+enum BothMatch(alias S) = "alias";
+enum BothMatch(T) = "type";
+
+void foo9029() { }
+
+struct Struct { }
+
+static assert(BothMatch!int == "type");
+static assert(BothMatch!(void function()) == "type");
+static assert(BothMatch!BothMatch == "alias");
+static assert(BothMatch!Struct == "type");
+static assert(BothMatch!foo9029 == "alias");
+static assert(BothMatch!5 == "alias");
+
+// https://issues.dlang.org/show_bug.cgi?id=19884
+mixin template genCtEvaluate()
+{
+ void evaluate(alias op)() { }
+}
+struct S
+{
+ mixin genCtEvaluate!() mixinEval;
+ alias evaluate = mixinEval.evaluate;
+ void evaluate() { }
+}
+alias List(Ops...) = Ops;
+void main()
+{
+ S g;
+ foreach (op; List!(0))
+ {
+ g.evaluate!op();
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug15613.d b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
new file mode 100644
index 0000000..e8072fd
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
@@ -0,0 +1,18 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug15613.d(16): Error: function `bug15613.f(int...)` is not callable using argument types `(typeof(null))`
+fail_compilation/bug15613.d(16): cannot pass argument `null` of type `typeof(null)` to parameter `int...`
+fail_compilation/bug15613.d(17): Error: function `bug15613.g(Object, ...)` is not callable using argument types `(int)`
+fail_compilation/bug15613.d(17): cannot pass argument `8` of type `int` to parameter `Object`
+---
+*/
+
+void f(int...);
+void g(Object, ...);
+
+void main()
+{
+ f(null);
+ g(8);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
new file mode 100644
index 0000000..fdfbf73
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
@@ -0,0 +1,18 @@
+void f(int x, Object y);
+
+void g()
+{
+ Object o;
+ f(o, o, 404);
+ f(5, 6, 404);
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug16165.d(6): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(Object, Object, int)`
+fail_compilation/bug16165.d(6): cannot pass argument `o` of type `object.Object` to parameter `int x`
+fail_compilation/bug16165.d(7): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(int, int, int)`
+fail_compilation/bug16165.d(7): cannot pass argument `6` of type `int` to parameter `Object y`
+---
+ */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
new file mode 100644
index 0000000..852eaae
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
@@ -0,0 +1,100 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(20): Error: cannot implicitly convert expression `F()` of type `bug9631.T1!().F` to `bug9631.T2!().F`
+---
+*/
+
+template T1()
+{
+ struct F { }
+}
+
+template T2()
+{
+ struct F { }
+}
+
+void main()
+{
+ T2!().F x = T1!().F();
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(41): Error: incompatible types for ((x) == (y)): 'bug9631.S' and 'bug9631.tem!
+).S'
+---
+*/
+
+struct S { char c; }
+
+template tem()
+{
+ struct S { int i; }
+}
+
+void equal()
+{
+ S x;
+ auto y = tem!().S();
+ bool b = x == y;
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(79): Error: function `bug9631.arg.f(int i, S s)` is not callable using argumen
+ types `(int, S)`
+fail_compilation/bug9631.d(79): cannot pass argument `y` of type `bug9631.tem!().S` to parameter `
+ug9631.S s`
+fail_compilation/bug9631.d(80): Error: function literal `__lambda2(S s)` is not callable using argument t
+pes `(S)`
+fail_compilation/bug9631.d(80): cannot pass argument `x` of type `bug9631.S` to parameter `bug9631
+tem!().S s`
+fail_compilation/bug9631.d(86): Error: constructor `bug9631.arg.A.this(S _param_0)` is not callable using
+argument types `(S)`
+fail_compilation/bug9631.d(86): cannot pass argument `S(0)` of type `bug9631.tem!().S` to paramete
+ `bug9631.S _param_0`
+---
+*/
+void arg()
+{
+ S x;
+ tem!().S y;
+
+ void f(int i, S s);
+ f(4, y);
+ (tem!().S s){}(x);
+
+ struct A
+ {
+ this(S){}
+ }
+ A(tem!().S());
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(106): Error: function `bug9631.targ.ft!().ft(S _param_0)` is not callable using argument types `(S)`
+fail_compilation/bug9631.d(106): cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S _param_0`
+fail_compilation/bug9631.d(107): Error: template `bug9631.targ.ft` cannot deduce function from argument types `!()(S)`, candidates are:
+fail_compilation/bug9631.d(105): `bug9631.targ.ft()(tem!().S)`
+fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` cannot deduce function from argument types `!()(S, int)`, candidates are:
+fail_compilation/bug9631.d(108): `bug9631.targ.ft2(T)(S, T)`
+---
+*/
+void targ()
+{
+ S x;
+ tem!().S y;
+
+ void ft()(tem!().S){}
+ ft!()(x);
+ ft(x);
+ void ft2(T)(S, T){}
+ ft2(y, 1);
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
new file mode 100644
index 0000000..7451b3f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
@@ -0,0 +1,139 @@
+/*
+REQUIRED_ARGS: -de
+TEST_OUTPUT:
+---
+fail_compilation/chkformat.d(101): Deprecation: width argument `0L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(101): Deprecation: precision argument `1L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(101): Deprecation: argument `2L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(104): Deprecation: argument `4` for format specification `"%lld"` must be `long`, not `int`
+fail_compilation/chkformat.d(105): Deprecation: argument `5` for format specification `"%jd"` must be `core.stdc.stdint.intmax_t`, not `int`
+fail_compilation/chkformat.d(106): Deprecation: argument `6.0` for format specification `"%zd"` must be `size_t`, not `double`
+fail_compilation/chkformat.d(107): Deprecation: argument `7.0` for format specification `"%td"` must be `ptrdiff_t`, not `double`
+fail_compilation/chkformat.d(108): Deprecation: argument `8.0L` for format specification `"%g"` must be `double`, not `real`
+fail_compilation/chkformat.d(109): Deprecation: argument `9.0` for format specification `"%Lg"` must be `real`, not `double`
+fail_compilation/chkformat.d(110): Deprecation: argument `10` for format specification `"%p"` must be `void*`, not `int`
+fail_compilation/chkformat.d(111): Deprecation: argument `& u` for format specification `"%n"` must be `int*`, not `uint*`
+fail_compilation/chkformat.d(113): Deprecation: argument `& u` for format specification `"%lln"` must be `long*`, not `int*`
+fail_compilation/chkformat.d(114): Deprecation: argument `& u` for format specification `"%hn"` must be `short*`, not `int*`
+fail_compilation/chkformat.d(115): Deprecation: argument `& u` for format specification `"%hhn"` must be `byte*`, not `int*`
+fail_compilation/chkformat.d(116): Deprecation: argument `16L` for format specification `"%c"` must be `char`, not `long`
+fail_compilation/chkformat.d(117): Deprecation: argument `17L` for format specification `"%c"` must be `char`, not `long`
+fail_compilation/chkformat.d(118): Deprecation: argument `& u` for format specification `"%s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(119): Deprecation: argument `& u` for format specification `"%ls"` must be `wchar_t*`, not `int*`
+fail_compilation/chkformat.d(201): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(202): Deprecation: more format specifiers than 1 arguments
+fail_compilation/chkformat.d(203): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(204): Deprecation: argument `0L` for format specification `"%3u"` must be `uint*`, not `long`
+fail_compilation/chkformat.d(205): Deprecation: argument `u` for format specification `"%200u"` must be `uint*`, not `uint`
+fail_compilation/chkformat.d(206): Deprecation: argument `3.0` for format specification `"%hhd"` must be `byte*`, not `double`
+fail_compilation/chkformat.d(207): Deprecation: argument `4` for format specification `"%hd"` must be `short*`, not `int`
+fail_compilation/chkformat.d(209): Deprecation: argument `4` for format specification `"%lld"` must be `long*`, not `int`
+fail_compilation/chkformat.d(210): Deprecation: argument `5` for format specification `"%jd"` must be `core.stdc.stdint.intmax_t*`, not `int`
+fail_compilation/chkformat.d(211): Deprecation: argument `6.0` for format specification `"%zd"` must be `size_t*`, not `double`
+fail_compilation/chkformat.d(212): Deprecation: argument `7.0` for format specification `"%td"` must be `ptrdiff_t*`, not `double`
+fail_compilation/chkformat.d(213): Deprecation: format specifier `"%Ld"` is invalid
+fail_compilation/chkformat.d(214): Deprecation: argument `0` for format specification `"%u"` must be `uint*`, not `int`
+fail_compilation/chkformat.d(215): Deprecation: argument `0` for format specification `"%hhu"` must be `ubyte*`, not `int`
+fail_compilation/chkformat.d(216): Deprecation: argument `0` for format specification `"%hu"` must be `ushort*`, not `int`
+fail_compilation/chkformat.d(218): Deprecation: argument `0` for format specification `"%llu"` must be `ulong*`, not `int`
+fail_compilation/chkformat.d(219): Deprecation: argument `0` for format specification `"%ju"` must be `ulong*`, not `int`
+fail_compilation/chkformat.d(220): Deprecation: argument `0` for format specification `"%zu"` must be `size_t*`, not `int`
+fail_compilation/chkformat.d(221): Deprecation: argument `0` for format specification `"%tu"` must be `ptrdiff_t*`, not `int`
+fail_compilation/chkformat.d(222): Deprecation: argument `8.0L` for format specification `"%g"` must be `float*`, not `real`
+fail_compilation/chkformat.d(223): Deprecation: argument `8.0L` for format specification `"%lg"` must be `double*`, not `real`
+fail_compilation/chkformat.d(224): Deprecation: argument `9.0` for format specification `"%Lg"` must be `real*`, not `double`
+fail_compilation/chkformat.d(225): Deprecation: argument `& u` for format specification `"%s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(226): Deprecation: argument `& u` for format specification `"%ls"` must be `wchar_t*`, not `int*`
+fail_compilation/chkformat.d(227): Deprecation: argument `v` for format specification `"%p"` must be `void**`, not `void*`
+fail_compilation/chkformat.d(228): Deprecation: argument `& u` for format specification `"%n"` must be `int*`, not `ushort*`
+fail_compilation/chkformat.d(229): Deprecation: argument `& u` for format specification `"%hhn"` must be `byte*`, not `int*`
+fail_compilation/chkformat.d(230): Deprecation: format specifier `"%[n"` is invalid
+fail_compilation/chkformat.d(231): Deprecation: format specifier `"%]"` is invalid
+fail_compilation/chkformat.d(232): Deprecation: argument `& u` for format specification `"%90s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(233): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(234): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+---
+*/
+
+
+import core.stdc.stdio;
+
+#line 100
+
+void test1() { printf("%*.*d\n", 0L, 1L, 2L); }
+//void test2() { }
+//void test3() { printf("%ld\n", 3.0); }
+void test4() { printf("%lld\n", 4); }
+void test5() { printf("%jd\n", 5); }
+void test6() { printf("%zd\n", 6.0); }
+void test7() { printf("%td\n", 7.0); }
+void test8() { printf("%g\n", 8.0L); }
+void test9() { printf("%Lg\n", 9.0); }
+void test10() { printf("%p\n", 10); }
+void test11() { uint u; printf("%n\n", &u); }
+//void test12() { ushort u; printf("%ln\n", &u); }
+void test13() { int u; printf("%lln\n", &u); }
+void test14() { int u; printf("%hn\n", &u); }
+void test15() { int u; printf("%hhn\n", &u); }
+void test16() { printf("%c\n", 16L); }
+void test17() { printf("%c\n", 17L); }
+void test18() { int u; printf("%s\n", &u); }
+void test19() { int u; printf("%ls\n", &u); }
+//void test20() { int u; char[] s; sprintf(&s[0], "%d\n", &u); }
+//void test21() { int u; fprintf(null, "%d\n", &u); }
+
+#line 200
+
+void test31() { scanf("%d\n", 0L); }
+void test32() { int i; scanf("%d %d\n", &i); }
+void test33() { scanf("%d%*c\n", 0L); }
+void test34() { scanf("%3u\n", 0L); }
+void test35() { uint u; scanf("%200u%*s\n", u); }
+void test36() { scanf("%hhd\n", 3.0); }
+void test37() { scanf("%hd\n", 4); }
+//void test38() { scanf("%ld\n", 3.0); }
+void test39() { scanf("%lld\n", 4); }
+void test40() { scanf("%jd\n", 5); }
+void test41() { scanf("%zd\n", 6.0); }
+void test42() { scanf("%td\n", 7.0); }
+void test43() { scanf("%Ld\n", 0); }
+void test44() { scanf("%u\n", 0); }
+void test45() { scanf("%hhu\n", 0); }
+void test46() { scanf("%hu\n", 0); }
+//void test47() { scanf("%lu\n", 0); }
+void test48() { scanf("%llu\n", 0); }
+void test49() { scanf("%ju\n", 0); }
+void test50() { scanf("%zu\n", 0); }
+void test51() { scanf("%tu\n", 0); }
+void test52() { scanf("%g\n", 8.0L); }
+void test53() { scanf("%lg\n", 8.0L); }
+void test54() { scanf("%Lg\n", 9.0); }
+void test55() { int u; scanf("%s\n", &u); }
+void test56() { int u; scanf("%ls\n", &u); }
+void test57() { void* v; scanf("%p\n", v); }
+void test58() { ushort u; scanf("%n\n", &u); }
+void test59() { int u; scanf("%hhn\n", &u); }
+void test60() { int u; scanf("%[n", &u); }
+void test61() { int u; scanf("%]\n", &u); }
+void test62() { int u; scanf("%90s\n", &u); }
+void test63() { sscanf("1234", "%d\n", 0L); }
+void test64() { fscanf(null, "%d\n", 0L); }
+
+/* TEST_OUTPUT:
+---
+fail_compilation/chkformat.d(301): Deprecation: format specifier `"%K"` is invalid
+fail_compilation/chkformat.d(302): Deprecation: format specifier `"%Q"` is invalid
+---
+*/
+
+import core.stdc.stdarg;
+
+#line 300
+
+void test301() { va_list vargs; vprintf("%K", vargs); }
+void test302() { va_list vargs; vscanf("%Q", vargs); }
+
+// TODO - C++ 11 only:
+//void test() { vscanf(); }
+//void test() { vfscanf(); }
+//void test() { vsscanf(); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
index b8b2f03..ca9ed9a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/cppmangle.d(10): Error: invalid zero length C++ namespace
-fail_compilation/cppmangle.d(14): Error: expected valid identifer for C++ namespace but got `0num`
+fail_compilation/cppmangle.d(14): Error: expected valid identifier for C++ namespace but got `0num`
fail_compilation/cppmangle.d(18): Error: string expected following `,` for C++ namespace, not `)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
index 2280691..a5d6a14 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
@@ -14,7 +14,7 @@ fail_compilation/diag11819b.d(37): Error: unrecognized trait `AllMembers`, did y
fail_compilation/diag11819b.d(38): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
fail_compilation/diag11819b.d(39): Error: unrecognized trait `IsSame`, did you mean `isSame`?
fail_compilation/diag11819b.d(40): Error: unrecognized trait `Compiles`, did you mean `compiles`?
-fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`, did you mean `parameters`?
+fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`
fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13082.d b/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
index 13259ce..7360a3df6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
@@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag13082.d(22): Error: constructor diag13082.C.this (int a) is not callable using argument types (string)
-fail_compilation/diag13082.d(23): Error: constructor diag13082.S.this (int a) is not callable using argument types (string)
+fail_compilation/diag13082.d(24): Error: constructor `diag13082.C.this(int a)` is not callable using argument types `(string)`
+fail_compilation/diag13082.d(24): cannot pass argument `b` of type `string` to parameter `int a`
+fail_compilation/diag13082.d(25): Error: constructor `diag13082.S.this(int a)` is not callable using argument types `(string)`
+fail_compilation/diag13082.d(25): cannot pass argument `b` of type `string` to parameter `int a`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16271.d b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
new file mode 100644
index 0000000..b85dc8d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
@@ -0,0 +1,12 @@
+/*
+TEST_OUTPUT
+---
+fail_compilation/diag16271.d(10): Error: found `x` when expecting function literal following `ref`
+---
+*/
+
+void main()
+{
+ auto fun = ref x;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
index 6fc3809..3b2401a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
@@ -1,29 +1,30 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag8101.d(56): Error: function diag8101.f_0 (int) is not callable using argument types ()
-fail_compilation/diag8101.d(57): Error: none of the overloads of 'f_1' are callable using argument types (), candidates are:
-fail_compilation/diag8101.d(32): diag8101.f_1(int)
-fail_compilation/diag8101.d(33): diag8101.f_1(int, int)
-fail_compilation/diag8101.d(58): Error: none of the overloads of 'f_2' are callable using argument types (), candidates are:
-fail_compilation/diag8101.d(35): diag8101.f_2(int)
-fail_compilation/diag8101.d(36): diag8101.f_2(int, int)
-fail_compilation/diag8101.d(37): diag8101.f_2(int, int, int)
-fail_compilation/diag8101.d(38): diag8101.f_2(int, int, int, int)
-fail_compilation/diag8101.d(39): diag8101.f_2(int, int, int, int, int)
-fail_compilation/diag8101.d(58): ... (1 more, -v to show) ...
-fail_compilation/diag8101.d(60): Error: template diag8101.t_0 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(42): diag8101.t_0(T1)()
-fail_compilation/diag8101.d(61): Error: template diag8101.t_1 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(44): diag8101.t_1(T1)()
-fail_compilation/diag8101.d(45): diag8101.t_1(T1, T2)()
-fail_compilation/diag8101.d(62): Error: template diag8101.t_2 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(47): diag8101.t_2(T1)()
-fail_compilation/diag8101.d(48): diag8101.t_2(T1, T2)()
-fail_compilation/diag8101.d(49): diag8101.t_2(T1, T2, T3)()
-fail_compilation/diag8101.d(50): diag8101.t_2(T1, T2, T3, T4)()
-fail_compilation/diag8101.d(51): diag8101.t_2(T1, T2, T3, T4, T5)()
-fail_compilation/diag8101.d(62): ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(57): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
+fail_compilation/diag8101.d(57): missing argument for parameter #1: `int`
+fail_compilation/diag8101.d(58): Error: none of the overloads of `f_1` are callable using argument types `()`, candidates are:
+fail_compilation/diag8101.d(33): `diag8101.f_1(int)`
+fail_compilation/diag8101.d(34): `diag8101.f_1(int, int)`
+fail_compilation/diag8101.d(59): Error: none of the overloads of `f_2` are callable using argument types `()`, candidates are:
+fail_compilation/diag8101.d(36): `diag8101.f_2(int)`
+fail_compilation/diag8101.d(37): `diag8101.f_2(int, int)`
+fail_compilation/diag8101.d(38): `diag8101.f_2(int, int, int)`
+fail_compilation/diag8101.d(39): `diag8101.f_2(int, int, int, int)`
+fail_compilation/diag8101.d(40): `diag8101.f_2(int, int, int, int, int)`
+fail_compilation/diag8101.d(59): ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(61): Error: template `diag8101.t_0` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(43): `diag8101.t_0(T1)()`
+fail_compilation/diag8101.d(62): Error: template `diag8101.t_1` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(45): `diag8101.t_1(T1)()`
+fail_compilation/diag8101.d(46): `diag8101.t_1(T1, T2)()`
+fail_compilation/diag8101.d(63): Error: template `diag8101.t_2` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(48): `diag8101.t_2(T1)()`
+fail_compilation/diag8101.d(49): `diag8101.t_2(T1, T2)()`
+fail_compilation/diag8101.d(50): `diag8101.t_2(T1, T2, T3)()`
+fail_compilation/diag8101.d(51): `diag8101.t_2(T1, T2, T3, T4)()`
+fail_compilation/diag8101.d(52): `diag8101.t_2(T1, T2, T3, T4, T5)()`
+fail_compilation/diag8101.d(63): ... (1 more, -v to show) ...
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
index a3baa27..228ba16 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
@@ -1,14 +1,15 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag8101b.d(26): Error: none of the overloads of 'foo' are callable using argument types (double), candidates are:
-fail_compilation/diag8101b.d(17): diag8101b.S.foo(int _param_0)
-fail_compilation/diag8101b.d(18): diag8101b.S.foo(int _param_0, int _param_1)
-fail_compilation/diag8101b.d(28): Error: function diag8101b.S.bar (int _param_0) is not callable using argument types (double)
-fail_compilation/diag8101b.d(31): Error: none of the overloads of 'foo' are callable using a const object, candidates are:
-fail_compilation/diag8101b.d(17): diag8101b.S.foo(int _param_0)
-fail_compilation/diag8101b.d(18): diag8101b.S.foo(int _param_0, int _param_1)
-fail_compilation/diag8101b.d(33): Error: mutable method diag8101b.S.bar is not callable using a const object
+fail_compilation/diag8101b.d(27): Error: none of the overloads of `foo` are callable using argument types `(double)`, candidates are:
+fail_compilation/diag8101b.d(18): `diag8101b.S.foo(int _param_0)`
+fail_compilation/diag8101b.d(19): `diag8101b.S.foo(int _param_0, int _param_1)`
+fail_compilation/diag8101b.d(29): Error: function `diag8101b.S.bar(int _param_0)` is not callable using argument types `(double)`
+fail_compilation/diag8101b.d(29): cannot pass argument `1.00000` of type `double` to parameter `int _param_0`
+fail_compilation/diag8101b.d(32): Error: none of the overloads of `foo` are callable using a `const` object, candidates are:
+fail_compilation/diag8101b.d(18): `diag8101b.S.foo(int _param_0)`
+fail_compilation/diag8101b.d(19): `diag8101b.S.foo(int _param_0, int _param_1)`
+fail_compilation/diag8101b.d(34): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
index dfaf7c8..6b2577d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT
---
-fail_compilation/diag9420.d(20): Error: function diag9420.S.t3!().tx () is not callable using argument types (int)
+fail_compilation/diag9420.d(21): Error: function `diag9420.S.t3!().tx()` is not callable using argument types `(int)`
+fail_compilation/diag9420.d(21): expected 0 argument(s), not 1
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11038.d b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
new file mode 100644
index 0000000..8f39ccc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
@@ -0,0 +1,17 @@
+// https://issues.dlang.org/show_bug.cgi?id=11038
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail11038.d(16): Error: `writeln` is not defined, perhaps `import std.stdio;` is needed?
+---
+*/
+
+static
+{
+ import std.stdio;
+}
+
+void main()
+{
+ writeln("foo"); // compiles
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
index a3cfc11..ed3f226 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail11445.d(11): Error: incompatible types for ((a) + (b)): 'double[string]' and 'double[string]'
+fail_compilation/fail11445.d(11): Error: incompatible types for ((a) + (b)): both operands are of type 'double[string]'
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
new file mode 100644
index 0000000..8e5f980
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
@@ -0,0 +1,8 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail15361.d(8): Error: unexpected `(` after `errorize`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression
+---
+*/
+
+enum isErrorizable(T) = is(errorize(T.init));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15896.d b/gcc/testsuite/gdc.test/fail_compilation/fail15896.d
new file mode 100644
index 0000000..e52503d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15896.d
@@ -0,0 +1,18 @@
+// REQUIRED_ARGS: -de
+// EXTRA_FILES: imports/imp15896.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail15896.d(11): Error: module `imports.imp15896` member `thebar` is not visible from module `fail15896`
+fail_compilation/fail15896.d(11): Error: module `imports.imp15896` member `packagebar` is not visible from module `fail15896`
+---
+*/
+
+import imports.imp15896 : thebar, packagebar;
+
+int func()
+{
+ thebar +=1;
+ packagebar += 1;
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17630.d b/gcc/testsuite/gdc.test/fail_compilation/fail17630.d
new file mode 100644
index 0000000..9b6ed82
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17630.d
@@ -0,0 +1,15 @@
+// REQUIRED_ARGS: -de
+// EXTRA_FILES: imports/a17630.d
+// EXTRA_SOURCES: imports/b17630.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail17630.d(13): Error: module `a17630` import `Erase` not found, did you mean variable `b17630.Erase`?
+---
+*/
+
+void main()
+{
+ import imports.a17630 : Erase;
+ assert(Erase == 2);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
new file mode 100644
index 0000000..f3ec680
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
@@ -0,0 +1,20 @@
+// EXTRA_SOURCES: imports/b18219.d
+// EXTRA_FILES: imports/a18219.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail18219.d(16): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(17): Error: no property `Bar` for type `a18219.AST`
+fail_compilation/fail18219.d(18): Error: no property `fun` for type `AST`, did you mean `b18219.fun`?
+fail_compilation/fail18219.d(19): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+---
+*/
+import imports.a18219;
+
+void main()
+{
+ AST.Foobar t;
+ AST.Bar l;
+ AST.fun();
+ AST.Foobar.smeth();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19107.d b/gcc/testsuite/gdc.test/fail_compilation/fail19107.d
new file mode 100644
index 0000000..c748650
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19107.d
@@ -0,0 +1,21 @@
+// REQUIRED_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test19107.d(20): Error: template `test19107.all` cannot deduce function from argument types `!((c) => c)(string[])`, candidates are:
+fail_compilation/test19107.d(14): `test19107.all(alias pred, T)(T t) if (is(typeof(I!pred(t))))`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=19107
+
+import imports.test19107b;
+
+void all(alias pred, T)(T t)
+ if (is(typeof(I!pred(t))))
+{ }
+
+void main(string[] args)
+{
+ args.all!(c => c);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail263.d b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
index f7dfe21..8cf9b20 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail263.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail263.d(18): Error: function fail263.f (byte* p) is not callable using argument types (const(byte)*)
+fail_compilation/fail263.d(19): Error: function `fail263.f(byte* p)` is not callable using argument types `(const(byte)*)`
+fail_compilation/fail263.d(19): cannot pass argument `cast(const(byte)*)A` of type `const(byte)*` to parameter `byte* p`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail3.d b/gcc/testsuite/gdc.test/fail_compilation/fail3.d
index 332e561..0b7516c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail3.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail3.d(40): Error: incompatible types for ((a) + (b)): 'vec2' and 'vec2'
+fail_compilation/fail3.d(41): Error: incompatible types for ((a) + (b)): both operands are of type 'vec2'
---
*/
@@ -14,6 +14,7 @@ template vector(T)
T x, y;
}
+ // not struct member
vec2 opAdd(vec2 a, vec2 b)
{
vec2 r;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail322.d b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
index 0ffa15a..491111f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail322.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
@@ -1,13 +1,18 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail322.d(10): Error: function fail322.digestToString2 (ref char[16] digest) is not callable using argument types (string)
+fail_compilation/fail322.d(13): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(string)`
+fail_compilation/fail322.d(13): cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] digest`
+fail_compilation/fail322.d(15): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(const(char[16]))`
+fail_compilation/fail322.d(15): cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] digest`
---
*/
void main()
{
digestToString2("1234567890123456");
+ const char[16] s;
+ digestToString2(s);
}
void digestToString2(ref char[16] digest)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail332.d b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
index 03f3706..91f8046 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail332.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
@@ -1,15 +1,56 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail332.d(14): Error: function fail332.foo (int _param_0, ...) is not callable using argument types ()
+fail_compilation/fail332.d(22): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `()`
+fail_compilation/fail332.d(22): missing argument for parameter #1: `int _param_0`
+fail_compilation/fail332.d(23): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(23): cannot pass argument `null` of type `typeof(null)` to parameter `int _param_0`
+fail_compilation/fail332.d(25): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(string)`
+fail_compilation/fail332.d(25): cannot pass argument `""` of type `string` to parameter `int[] _param_0...`
+fail_compilation/fail332.d(26): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(int, typeof(null))`
+fail_compilation/fail332.d(26): cannot pass argument `null` of type `typeof(null)` to parameter `int[] _param_0...`
---
*/
import core.vararg;
void foo(int, ...) {}
+void baz(int[]...) {}
-void bar()
+void test()
{
foo();
+ foo(null);
+
+ baz("");
+ baz(3, null);
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail332.d(50): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `()`
+fail_compilation/fail332.d(50): missing argument for parameter #1: `Object`
+fail_compilation/fail332.d(51): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(int)`
+fail_compilation/fail332.d(51): cannot pass argument `4` of type `int` to parameter `Object`
+fail_compilation/fail332.d(52): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(52): expected 2 variadic argument(s), not 0
+fail_compilation/fail332.d(53): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int)`
+fail_compilation/fail332.d(53): expected 2 variadic argument(s), not 1
+fail_compilation/fail332.d(54): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, string)`
+fail_compilation/fail332.d(54): cannot pass argument `""` of type `string` to parameter `int[2]...`
+fail_compilation/fail332.d(55): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, int, int)`
+fail_compilation/fail332.d(55): expected 2 variadic argument(s), not 3
+---
+*/
+void bar(Object, int[2]...);
+
+void test2()
+{
+ bar();
+ bar(4);
+ bar(null);
+ bar(null, 2);
+ bar(null, 2, "");
+ bar(null, 2,3,4);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail347.d b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
index 03ae703..61718df 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail347.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail347.d(21): Error: undefined identifier `bbr`, did you mean variable `bar`?
-fail_compilation/fail347.d(22): Error: no property 'ofo' for type 'S', did you mean 'foo'?
+fail_compilation/fail347.d(22): Error: no property 'ofo' for type 'S', did you mean 'fail347.S.foo'?
fail_compilation/fail347.d(23): Error: undefined identifier `strlenx`, did you mean function `strlen`?
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail53.d b/gcc/testsuite/gdc.test/fail_compilation/fail53.d
index 2570dd8..556896c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail53.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail53.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail53.d(25): Error: function object.Object.opEquals (Object o) is not callable using argument types (int)
+fail_compilation/fail53.d(26): Error: function `object.Object.opEquals(Object o)` is not callable using argument types `(int)`
+fail_compilation/fail53.d(26): cannot pass argument `i` of type `int` to parameter `Object o`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail55.d b/gcc/testsuite/gdc.test/fail_compilation/fail55.d
index 57117d8..290c2b66 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail55.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail55.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail55.d(22): Error: function object.Object.opCmp (Object o) is not callable using argument types (int)
+fail_compilation/fail55.d(23): Error: function `object.Object.opCmp(Object o)` is not callable using argument types `(int)`
+fail_compilation/fail55.d(23): cannot pass argument `0` of type `int` to parameter `Object o`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail79.d b/gcc/testsuite/gdc.test/fail_compilation/fail79.d
index 46581d9..da06984e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail79.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail79.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail79.d(13): Error: incompatible types for ((& a) + (& b)): 'int*' and 'int*'
+fail_compilation/fail79.d(13): Error: incompatible types for ((& a) + (& b)): both operands are of type 'int*'
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail99.d b/gcc/testsuite/gdc.test/fail_compilation/fail99.d
index da87ed6..c147b81 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail99.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail99.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail99.d(12): Error: delegate dg (int) is not callable using argument types ()
+fail_compilation/fail99.d(13): Error: delegate `dg(int)` is not callable using argument types `()`
+fail_compilation/fail99.d(13): missing argument for parameter #1: `int`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21585.d b/gcc/testsuite/gdc.test/fail_compilation/fix21585.d
new file mode 100644
index 0000000..48c74cb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix21585.d
@@ -0,0 +1,19 @@
+/* https://issues.dlang.org/show_bug.cgi?id=21585
+TEST_OUTPUT:
+---
+fail_compilation/fix21585.d(103): Error: expected 1 arguments for `toType` but had 0
+fail_compilation/fix21585.d(104): Error: expression expected as second argument of __traits `toType`
+fail_compilation/fix21585.d(105): Error: `string` expected for __traits(toType, string), not `(1)` of type `int`
+fail_compilation/fix21585.d(106): Error: cannot determine `__traits(toType, "hello betty")`
+---
+*/
+
+#line 100
+
+template Type(T) { alias Type = T; }
+
+alias T1 = Type!(__traits(toType));
+alias T2 = Type!(__traits(toType, int));
+alias T3 = Type!(__traits(toType, 1));
+alias T4 = Type!(__traits(toType, "hello betty"));
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/format.d b/gcc/testsuite/gdc.test/fail_compilation/format.d
new file mode 100644
index 0000000..3a24227
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/format.d
@@ -0,0 +1,44 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/format.d(101): Error: function `format.printf1` `pragma(printf)` functions must be `extern(C) void printf1([parameters...], const(char)*, ...)` not `void(const(char)*, ...)`
+fail_compilation/format.d(102): Error: function `format.printf2` `pragma(printf)` functions must be `extern(C) int printf2([parameters...], const(char)*, ...)` not `extern (C) int(const(int)*, ...)`
+fail_compilation/format.d(103): Error: function `format.printf3` `pragma(printf)` functions must be `extern(C) int printf3([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(104): Error: function `format.printf4` `pragma(printf)` functions must be `extern(C) int printf4([parameters...], const(char)*, ...)` not `extern (C) int(const(char)*, int, ...)`
+---
+ */
+
+#line 100
+
+pragma(printf) void printf1(const(char)*, ...);
+pragma(printf) extern (C) int printf2(const(int )*, ...);
+pragma(printf) extern (C) int printf3(const(char)*);
+pragma(printf) extern (C) int printf4(const(char)*, int, ...);
+
+pragma(printf) extern (C) int printf5(const(char)*, ...);
+pragma(printf) extern (C) int printf6(immutable(char)*, ...);
+pragma(printf) extern (C) int printf7(char*, ...);
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/format.d(203): Error: function `format.vprintf1` `pragma(printf)` functions must be `extern(C) void vprintf1([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(204): Error: function `format.vprintf2` `pragma(printf)` functions must be `extern(C) int vprintf2([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(205): Error: function `format.vprintf3` `pragma(printf)` functions must be `extern(C) int vprintf3([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(206): Error: function `format.vprintf4` `pragma(printf)` functions must be `extern(C) int vprintf4([parameters...], const(char)*, va_list)`
+---
+ */
+
+#line 200
+
+import core.stdc.stdarg;
+
+pragma(printf) void vprintf1(const(char)*, va_list);
+pragma(printf) extern (C) int vprintf2(const(int )*, va_list);
+pragma(printf) extern (C) int vprintf3(const(char)*);
+pragma(printf) extern (C) int vprintf4(const(char)*, int, va_list);
+
+pragma(printf) extern (C) int vprintf5(const(char)*, va_list);
+pragma(printf) extern (C) int vprintf6(immutable(char)*, va_list);
+pragma(printf) extern (C) int vprintf7(char*, va_list);
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10598.d b/gcc/testsuite/gdc.test/fail_compilation/ice10598.d
new file mode 100644
index 0000000..ba6cdf7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10598.d
@@ -0,0 +1,10 @@
+// REQUIRED_ARGS: -de
+// EXTRA_SOURCES: imports/ice10598a.d imports/ice10598b.d
+/* TEST_OUTPUT:
+---
+fail_compilation/imports/ice10598a.d(5): Deprecation: module imports.ice10598b is not accessible here, perhaps add 'static import imports.ice10598b;'
+fail_compilation/imports/ice10598a.d(5): Deprecation: module imports.ice10598b is not accessible here, perhaps add 'static import imports.ice10598b;'
+---
+*/
+
+void main() {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
index 1ddad18..9eeb622 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice10922.d(9): Error: function ice10922.__lambda4 (const(uint) n) is not callable using argument types ()
+fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(const(uint) n)` is not callable using argument types `()`
+fail_compilation/ice10922.d(10): missing argument for parameter #1: `const(uint) n`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12497.d b/gcc/testsuite/gdc.test/fail_compilation/ice12497.d
deleted file mode 100644
index ab95e81..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12497.d
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/ice12497.d(15): Error: string expected for argument to mixin, not (foo()) of type void
-fail_compilation/ice12497.d(17): Error: string expected for argument to mixin, not (foo()) of type void
----
-*/
-
-void foo() {}
-
-void main()
-{
- struct S
- {
- mixin(foo()); // MixinDeclaration
- }
- mixin(foo()); // MixinStatement
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
index f57980d..2c45c8a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
@@ -1,9 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice12501.d(29): Error: function ice12501.foo (int value) is not callable using argument types (int, int)
-fail_compilation/ice12501.d(29): Error: function ice12501.foo (int value) is not callable using argument types (int, int)
-fail_compilation/ice12501.d(43): Error: template instance ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[]) error instantiating
+fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(31): expected 1 argument(s), not 2
+fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(31): expected 1 argument(s), not 2
+fail_compilation/ice12501.d(45): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
new file mode 100644
index 0000000..6d9edf0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
@@ -0,0 +1,22 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice14907.d(14): Error: struct ice14907.S(int v = S) recursive template expansion
+fail_compilation/ice14907.d(19): while looking for match for `S!()`
+fail_compilation/ice14907.d(15): Error: template ice14907.f(int v = f)() recursive template expansion
+fail_compilation/ice14907.d(20): while looking for match for `f!()`
+fail_compilation/ice14907.d(15): Error: template ice14907.f(int v = f)() recursive template expansion
+fail_compilation/ice14907.d(21): Error: template `ice14907.f` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/ice14907.d(15): `ice14907.f(int v = f)()`
+---
+*/
+
+struct S(int v = S) {}
+void f(int v = f)() {}
+
+void main()
+{
+ S!() s; // OK <- ICE
+ f!()(); // OK <- ICE
+ f(); // OK <- ICE
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
index 86e3b2a..e3b677e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
@@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice14923.d(21): Error: function ice14923.parse (C a) is not callable using argument types (A)
-fail_compilation/ice14923.d(21): instantiated from here: bar!((b) => parse(b))
+fail_compilation/ice14923.d(22): Error: function `ice14923.parse(C a)` is not callable using argument types `(A)`
+fail_compilation/ice14923.d(22): cannot pass argument `b` of type `ice14923.A` to parameter `C a`
+fail_compilation/ice14923.d(22): instantiated from here: `bar!((b) => parse(b))`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice8255.d b/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
index d98e38a..0db3abc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
@@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice8255.d(10): Error: function ice8255.F!(G).F.f (ref G _param_0) is not callable using argument types (G)
-fail_compilation/ice8255.d(10): while evaluating pragma(msg, F().f(G()))
+fail_compilation/ice8255.d(11): Error: function `ice8255.F!(G).F.f(ref G _param_0)` is not callable using argument types `(G)`
+fail_compilation/ice8255.d(11): cannot pass rvalue argument `G()` of type `G` to parameter `ref G _param_0`
+fail_compilation/ice8255.d(11): while evaluating `pragma(msg, F().f(G()))`
---
*/
struct G {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
index d6c9cda..f95cb97 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
@@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice9540.d(34): Error: function ice9540.A.test.AddFront!(this, f).AddFront.dg (int _param_0) is not callable using argument types ()
-fail_compilation/ice9540.d(25): Error: template instance ice9540.A.test.AddFront!(this, f) error instantiating
+fail_compilation/ice9540.d(35): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int _param_0)` is not callable using argument types `()`
+fail_compilation/ice9540.d(35): missing argument for parameter #1: `int _param_0`
+fail_compilation/ice9540.d(26): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d b/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d
new file mode 100644
index 0000000..c104841
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d
@@ -0,0 +1,3 @@
+module a17630;
+
+import b17630;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d b/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d
new file mode 100644
index 0000000..1a88493
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d
@@ -0,0 +1,6 @@
+module a18219;
+
+struct AST
+{
+ import b18219;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d b/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d
new file mode 100644
index 0000000..5ad5f99
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d
@@ -0,0 +1,3 @@
+module b17630;
+
+int Erase;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d b/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d
new file mode 100644
index 0000000..6008c8a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d
@@ -0,0 +1,15 @@
+module b18219;
+
+class Foobar
+{
+ int a;
+ this(int a)
+ {
+ this.a = a;
+ }
+ static int smeth()
+ {
+ return 1;
+ }
+}
+void fun() {}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/ice10598a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598a.d
index b0e9c3b..b0e9c3b 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/ice10598a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598a.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/ice10598b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598b.d
index de50787..de50787 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/ice10598b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598b.d
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d b/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d
new file mode 100644
index 0000000..d7edcc1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d
@@ -0,0 +1,4 @@
+module imports.imp15896;
+
+private int thebar=4;
+package int packagebar=3;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d
new file mode 100644
index 0000000..4c85aad
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d
@@ -0,0 +1,3 @@
+module imports.test21651b;
+
+alias T = int;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
new file mode 100644
index 0000000..75e3b9f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations
+fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration
+fail_compilation/issue16020.d(13): Error: declaration expected, not `(`
+---
+*/
+module issue16020;
+
+struct UDA{}
+alias Fun = @UDA void();
+alias FunTemplate = void(T)(T t);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d b/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d
new file mode 100644
index 0000000..b18627d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d
@@ -0,0 +1,16 @@
+
+/* TEST_OUTPUT:
+---
+fail_compilation/mixintype2.d(10): Error: alias `mixintype2.Foo.T` recursive alias declaration
+fail_compilation/mixintype2.d(16): Error: `mixin(0)` does not give a valid type
+---
+*/
+
+struct Foo {
+ alias T = mixin("T2");
+}
+alias T1 = mixin("Foo.T");
+alias T2 = mixin("T1");
+void func (T2 p) {}
+
+enum mixin(0) a = 0;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16002.d b/gcc/testsuite/gdc.test/fail_compilation/test16002.d
deleted file mode 100644
index 80ae40b..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/test16002.d
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-REQUIRED_ARGS:
-PERMUTE_ARGS:
-TEST_OUTPUT:
----
-fail_compilation/test16002.d(100): Error: undefined identifier `imports.nonexistent`
-fail_compilation/test16002.d(101): Error: undefined identifier `imports.nonexistent`
----
-*/
-
-module test.fail_compilation.test16002;
-
-#line 100
-enum A = is(imports.nonexistent == package);
-enum B = is(imports.nonexistent == module);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21651.d b/gcc/testsuite/gdc.test/fail_compilation/test21651.d
new file mode 100644
index 0000000..a4d959f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21651.d
@@ -0,0 +1,11 @@
+// REQUIRED_ARGS: -de
+// EXTRA_SOURCES: imports/test21651b.d
+/* TEST_OUTPUT:
+---
+fail_compilation/test21651.d(11): Deprecation: module imports.test21651b is not accessible here, perhaps add 'static import imports.test21651b;'
+---
+*/
+
+module imports.test21651;
+
+imports.test21651b.T a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/warn12809.d b/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
index 100f0fb..06c998d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
@@ -32,3 +32,44 @@ void test_unrachable3()
int x = 1; // unreachable
}
+
+/********************************************/
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/warn12809.d(108): Warning: statement is not reachable
+fail_compilation/warn12809.d(115): Warning: statement is not reachable
+fail_compilation/warn12809.d(122): Warning: statement is not reachable
+Error: warnings are treated as errors
+ Use -wi if you wish to treat warnings only as informational.
+---
+*/
+
+#line 100
+
+alias noreturn = typeof(*null);
+
+noreturn foo();
+
+void test1(ref int i)
+{
+ foo();
+ i = 3;
+}
+
+void test2()
+{
+ try foo();
+ finally { }
+ int x = 1;
+}
+
+void test3()
+{
+ try { }
+ finally foo();
+ int x = 1;
+}
+
+
diff --git a/gcc/testsuite/gdc.test/runnable/funclit.d b/gcc/testsuite/gdc.test/runnable/funclit.d
index d45e3e6d..c299bad 100644
--- a/gcc/testsuite/gdc.test/runnable/funclit.d
+++ b/gcc/testsuite/gdc.test/runnable/funclit.d
@@ -1242,6 +1242,66 @@ void test15794()
}
/***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=16271
+
+ref auto funa16271(alias dg, T)(ref T a)
+{
+ return dg(a);
+}
+
+ref auto func16271(alias dg)()
+{
+ return dg();
+}
+
+void assign16271(T)(ref T a, T b)
+{
+ alias fun = ref (ref a) => a;
+ fun(a) = b;
+}
+
+void test16271()
+{
+ int x;
+ (ref () => x )() = 1; assert(x == 1);
+ func16271!(ref () => x) = 2; assert(x == 2);
+ assign16271(x, 3); assert(x == 3);
+
+ alias alx = func16271!(ref () => x);
+ alx = 4; assert(x == 4);
+
+ alias alf = ref (ref a) => a;
+ auto auf = ref (ref int a) => a;
+ alf(x) = 5; assert(x == 5);
+ auf(x) = 6; assert(x == 6);
+
+ assert((funa16271!( ref (ref a) => a)(x) += 1) == 7 );
+ assert((funa16271!(function ref (ref a) => a)(x) += 1) == 8 );
+ assert((funa16271!(function ref int(ref a) => a)(x) += 1) == 9 );
+ assert((funa16271!(delegate ref (ref a) => a)(x) += 1) == 10);
+ assert((funa16271!(delegate ref int(ref a) => a)(x) += 1) == 11);
+ assert(x == 11);
+
+ alias aldc = ref () @trusted @nogc { return x; };
+ auto audc = ref () @safe nothrow { return x; };
+ alias alfuc = function ref (ref x) @trusted { return x; };
+ alias aldec = delegate ref () @trusted { return x; };
+ aldc() = 12; assert(x == 12);
+ audc() = 13; assert(x == 13);
+ alfuc(x) = 14; assert(x == 14);
+ aldec() = 15; assert(x == 15);
+
+ template T()
+ {
+ int x;
+ alias alf = ref () => x;
+ auto auf = ref () => x;
+ }
+ T!().alf() = 1; assert(T!().x == 1);
+ T!().auf() = 2; assert(T!().x == 2);
+}
+
+/***************************************************/
int main()
{
@@ -1299,6 +1359,7 @@ int main()
test13879();
test14745();
test15794();
+ test16271();
printf("Success\n");
return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/mangle.d b/gcc/testsuite/gdc.test/runnable/mangle.d
index e6d3645..9a8420a 100644
--- a/gcc/testsuite/gdc.test/runnable/mangle.d
+++ b/gcc/testsuite/gdc.test/runnable/mangle.d
@@ -599,6 +599,12 @@ void fooB(void delegate (void delegate()) scope dg)
//pragma(msg, fooB.mangleof);
static assert(typeof(fooA).mangleof != typeof(fooB).mangleof);
+/***************************************************/
+
+alias noreturn = typeof(*null);
+alias fpd = noreturn function();
+int funcd(fpd);
+static assert(funcd.mangleof == "_D6mangle5funcdFPFZNnZi");
/***************************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
new file mode 100644
index 0000000..447ea28
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -0,0 +1,74 @@
+alias noreturn = typeof(*null);
+
+extern (C) noreturn exit();
+
+/*****************************************/
+
+bool testf(int i)
+{
+ return i && assert(0);
+}
+
+bool testt(int i)
+{
+ return i || assert(0);
+}
+
+int testa(int i)
+{
+ if (i && exit())
+ return i + 1;
+ return i - 1;
+}
+
+int testb(int i)
+{
+ if (i || exit())
+ return i + 1;
+ return i - 1;
+}
+
+void test1()
+{
+ assert(testf(0) == false);
+ assert(testt(1) == true);
+
+ assert(testa(0) == -1);
+ assert(testb(3) == 4);
+}
+
+/*****************************************/
+
+noreturn exit1() { assert(0); }
+noreturn exit2() { assert(0); }
+
+
+int heli1(int i)
+{
+ return i ? exit1() : i - 1;
+}
+
+int heli2(int i)
+{
+ return i ? i - 1 : exit1();
+}
+
+noreturn heli3(int i)
+{
+ return i ? exit1() : exit2();
+}
+
+void test2()
+{
+ assert(heli1(0) == -1);
+ assert(heli2(1) == 0);
+}
+
+/*****************************************/
+
+int main()
+{
+ test1();
+ test2();
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
index b9b4832..cb576ba 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
@@ -571,18 +571,20 @@ void test13289()
assert(f13289_cpp_test());
}
+version(Posix)
+{
+ enum __c_wchar_t : dchar;
+}
+else version(Windows)
+{
+ enum __c_wchar_t : wchar;
+}
+alias wchar_t = __c_wchar_t;
extern(C++)
{
bool f13289_cpp_test();
- version(Posix)
- {
- dchar f13289_cpp_wchar_t(dchar);
- }
- else version(Windows)
- {
- wchar f13289_cpp_wchar_t(wchar);
- }
+ wchar_t f13289_cpp_wchar_t(wchar_t);
wchar f13289_d_wchar(wchar ch)
{
@@ -606,6 +608,17 @@ extern(C++)
return ch;
}
}
+ wchar_t f13289_d_wchar_t(wchar_t ch)
+ {
+ if (ch <= 'z' && ch >= 'a')
+ {
+ return cast(wchar_t)(ch - ('a' - 'A'));
+ }
+ else
+ {
+ return ch;
+ }
+ }
}
/****************************************/
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
index 587145c..823c660 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
@@ -412,8 +412,12 @@ wchar_t f13289_d_wchar(wchar_t ch);
unsigned int f13289_d_dchar(unsigned int ch);
#endif
+wchar_t f13289_d_wchar_t(wchar_t ch);
+
bool f13289_cpp_test()
{
+ if (!(f13289_d_wchar_t(L'e') == L'E')) return false;
+ if (!(f13289_d_wchar_t(L'F') == L'F')) return false;
#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun || __NetBSD__
if (!(f13289_d_wchar((unsigned short)'c') == (unsigned short)'C')) return false;
if (!(f13289_d_wchar((unsigned short)'D') == (unsigned short)'D')) return false;
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp
new file mode 100644
index 0000000..076777a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp
@@ -0,0 +1,82 @@
+#include <assert.h>
+#include <complex.h>
+
+// Use custom types for inspecting parts instead of including tgmath.h
+union cfloat_t { _Complex float z; struct { float re; float im; }; };
+union cdouble_t { _Complex double z; struct { double re; double im; }; };
+union creal_t { _Complex long double z; struct { long double re; long double im; }; };
+
+// extern(C) tests
+extern "C" _Complex float ccomplexf() { return 2.0f+I; }
+extern "C" _Complex double ccomplex() { return 2.0+I; }
+extern "C" _Complex long double ccomplexl() { return 2.0L+I; }
+extern "C" void ccomplexf2(_Complex float c) { cfloat_t z = {c}; assert(z.re == 2 && z.im == 1); }
+extern "C" void ccomplex2(_Complex double c) { cdouble_t z = {c}; assert(z.re == 2 && z.im == 1); }
+extern "C" void ccomplexl2(_Complex long double c) { creal_t z = {c}; assert(z.re == 2 && z.im == 1); }
+
+// extern(C++) tests
+_Complex float cpcomplexf() { return 2.0f+I; }
+_Complex double cpcomplex() { return 2.0+I; }
+_Complex long double cpcomplexl() { return 2.0L+I; }
+void cpcomplexf(_Complex float c) { cfloat_t z = {c}; assert(z.re == 2 && z.im == 1); }
+void cpcomplex(_Complex double c) { cdouble_t z = {c}; assert(z.re == 2 && z.im == 1); }
+void cpcomplexl(_Complex long double c) { creal_t z = {c}; assert(z.re == 2 && z.im == 1); }
+
+// Struct tests
+struct wrap_complexf { _Complex float c; };
+struct wrap_complex { _Complex double c; };
+struct wrap_complexl { _Complex long double c; };
+
+wrap_complexf wcomplexf()
+{
+ wrap_complexf s;
+ s.c = 2.0f+I;
+ return s;
+}
+
+wrap_complex wcomplex()
+{
+ wrap_complex s;
+ s.c = 2.0+I;
+ return s;
+}
+
+wrap_complexl wcomplexl()
+{
+ wrap_complexl s;
+ s.c = 2.0L+I;
+ return s;
+}
+
+void wcomplexf(wrap_complexf s) { cfloat_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+void wcomplex(wrap_complex s) { cdouble_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+void wcomplexl(wrap_complexl s) { creal_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+
+struct soft_complexf { float re; float im; };
+struct soft_complex { double re; double im; };
+struct soft_complexl { long double re; long double im; };
+
+soft_complexf scomplexf()
+{
+ soft_complexf s;
+ s.re = 2.0f; s.im = 1.0f;
+ return s;
+}
+
+soft_complex scomplex()
+{
+ soft_complex s;
+ s.re = 2.0; s.im = 1.0;
+ return s;
+}
+
+soft_complexl scomplexl()
+{
+ soft_complexl s;
+ s.re = 2.0L; s.im = 1.0L;
+ return s;
+}
+
+void scomplexf(soft_complexf s) { assert(s.re == 2 && s.im == 1); }
+void scomplex(soft_complex s) { assert(s.re == 2 && s.im == 1); }
+void scomplexl(soft_complexl s) { assert(s.re == 2 && s.im == 1); }
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test21515.d b/gcc/testsuite/gdc.test/runnable_cxx/test21515.d
new file mode 100644
index 0000000..cc44207
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/test21515.d
@@ -0,0 +1,104 @@
+// https://issues.dlang.org/show_bug.cgi?id=21515
+// EXTRA_CPP_SOURCES: test21515.cpp
+// DISABLED: win32 win64
+
+// ABI layout of native complex
+struct _Complex(T) { T re; T im; }
+
+// Special enum definitions.
+version (Posix)
+{
+ align(float.alignof) enum __c_complex_float : _Complex!float;
+ align(double.alignof) enum __c_complex_double : _Complex!double;
+ align(real.alignof) enum __c_complex_real : _Complex!real;
+}
+else
+{
+ align(float.sizeof * 2) enum __c_complex_float : _Complex!float;
+ align(double.sizeof * 2) enum __c_complex_double : _Complex!double;
+ align(real.alignof) enum __c_complex_real : _Complex!real;
+}
+alias complex_float = __c_complex_float;
+alias complex_double = __c_complex_double;
+alias complex_real = __c_complex_real;
+
+extern(C) complex_float ccomplexf();
+extern(C) complex_double ccomplex();
+extern(C) complex_real ccomplexl();
+extern(C) void ccomplexf2(complex_float c);
+extern(C) void ccomplex2(complex_double c);
+extern(C) void ccomplexl2(complex_real c);
+
+extern(C++) complex_float cpcomplexf();
+extern(C++) complex_double cpcomplex();
+extern(C++) complex_real cpcomplexl();
+extern(C++) void cpcomplexf(complex_float c);
+extern(C++) void cpcomplex(complex_double c);
+extern(C++) void cpcomplexl(complex_real c);
+
+struct wrap_complexf { complex_float c; alias c this; };
+struct wrap_complex { complex_double c; alias c this; };
+struct wrap_complexl { complex_real c; alias c this; };
+
+extern(C++) wrap_complexf wcomplexf();
+extern(C++) wrap_complex wcomplex();
+extern(C++) wrap_complexl wcomplexl();
+extern(C++) void wcomplexf(wrap_complexf c);
+extern(C++) void wcomplex(wrap_complex c);
+extern(C++) void wcomplexl(wrap_complexl c);
+
+struct soft_complexf { float re; float im; };
+struct soft_complex { double re; double im; };
+struct soft_complexl { real re; real im; };
+
+extern(C++) soft_complexf scomplexf();
+extern(C++) soft_complex scomplex();
+extern(C++) soft_complexl scomplexl();
+extern(C++) void scomplexf(soft_complexf c);
+extern(C++) void scomplex(soft_complex c);
+extern(C++) void scomplexl(soft_complexl c);
+
+int main()
+{
+ auto a1 = ccomplexf();
+ auto b1 = ccomplex();
+ auto c1 = ccomplexl();
+ assert(a1.re == 2 && a1.im == 1);
+ assert(b1.re == 2 && b1.im == 1);
+ assert(c1.re == 2 && c1.im == 1);
+ ccomplexf2(a1);
+ ccomplex2(b1);
+ ccomplexl2(c1);
+
+ auto a2 = cpcomplexf();
+ auto b2 = cpcomplex();
+ auto c2 = cpcomplexl();
+ assert(a2.re == 2 && a2.im == 1);
+ assert(b2.re == 2 && b2.im == 1);
+ assert(c2.re == 2 && c2.im == 1);
+ cpcomplexf(a2);
+ cpcomplex(b2);
+ cpcomplexl(c2);
+
+ auto a3 = wcomplexf();
+ auto b3 = wcomplex();
+ auto c3 = wcomplexl();
+ assert(a3.re == 2 && a3.im == 1);
+ assert(b3.re == 2 && b3.im == 1);
+ assert(c3.re == 2 && c3.im == 1);
+ wcomplexf(a3);
+ wcomplex(b3);
+ wcomplexl(c3);
+
+ auto a4 = scomplexf();
+ auto b4 = scomplex();
+ auto c4 = scomplexl();
+ assert(a4.re == 2 && a4.im == 1);
+ assert(b4.re == 2 && b4.im == 1);
+ assert(c4.re == 2 && c4.im == 1);
+ scomplexf(a4);
+ scomplex(b4);
+ scomplexl(c4);
+
+ return 0;
+}
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index a4a9a94..b797682 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-0fd4364c4a4eb2ce0ebb8f613092c5bed7a63bf9
+483bc12977af3c1288fd52e7b4fa14b716896c5a
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 535ca26..2a5c793 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -208,16 +208,17 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
- core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \
- core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
- core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
- core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
- core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
- core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
- core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
- core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
- core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
- core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
+ core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
+ core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
+ core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+ core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
+ core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
+ core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
+ core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+ core/sys/darwin/stdlib.d core/sys/darwin/string.d \
+ core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
+ core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
+ core/sys/darwin/sys/sysctl.d
DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
@@ -275,7 +276,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.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/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 \
@@ -382,22 +384,22 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
core/sys/windows/stacktrace.d core/sys/windows/stat.d \
- core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
- core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
- core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
- core/sys/windows/uuid.d core/sys/windows/vfw.d \
- core/sys/windows/w32api.d core/sys/windows/winbase.d \
- core/sys/windows/winber.d core/sys/windows/wincon.d \
- core/sys/windows/wincrypt.d core/sys/windows/windef.d \
- core/sys/windows/windows.d core/sys/windows/winerror.d \
- core/sys/windows/wingdi.d core/sys/windows/winhttp.d \
- core/sys/windows/wininet.d core/sys/windows/winioctl.d \
- core/sys/windows/winldap.d core/sys/windows/winnetwk.d \
- core/sys/windows/winnls.d core/sys/windows/winnt.d \
- core/sys/windows/winperf.d core/sys/windows/winreg.d \
- core/sys/windows/winsock2.d core/sys/windows/winspool.d \
- core/sys/windows/winsvc.d core/sys/windows/winuser.d \
- core/sys/windows/winver.d core/sys/windows/wtsapi32.d \
- core/sys/windows/wtypes.d
+ core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \
+ core/sys/windows/subauth.d core/sys/windows/threadaux.d \
+ core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \
+ core/sys/windows/unknwn.d core/sys/windows/uuid.d \
+ core/sys/windows/vfw.d core/sys/windows/w32api.d \
+ core/sys/windows/winbase.d core/sys/windows/winber.d \
+ core/sys/windows/wincon.d core/sys/windows/wincrypt.d \
+ core/sys/windows/windef.d core/sys/windows/windows.d \
+ core/sys/windows/winerror.d core/sys/windows/wingdi.d \
+ core/sys/windows/winhttp.d core/sys/windows/wininet.d \
+ core/sys/windows/winioctl.d core/sys/windows/winldap.d \
+ core/sys/windows/winnetwk.d core/sys/windows/winnls.d \
+ core/sys/windows/winnt.d core/sys/windows/winperf.d \
+ core/sys/windows/winreg.d core/sys/windows/winsock2.d \
+ core/sys/windows/winspool.d core/sys/windows/winsvc.d \
+ core/sys/windows/winuser.d core/sys/windows/winver.d \
+ core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
DRUNTIME_DISOURCES = __entrypoint.di __main.di
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 7960add..b00fe02 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -256,8 +256,9 @@ am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
@DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
am__objects_5 = core/sys/darwin/crt_externs.lo \
core/sys/darwin/dlfcn.lo core/sys/darwin/err.lo \
- core/sys/darwin/execinfo.lo core/sys/darwin/ifaddrs.lo \
- core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
+ core/sys/darwin/execinfo.lo core/sys/darwin/fcntl.lo \
+ core/sys/darwin/ifaddrs.lo core/sys/darwin/mach/dyld.lo \
+ core/sys/darwin/mach/getsect.lo \
core/sys/darwin/mach/kern_return.lo \
core/sys/darwin/mach/loader.lo core/sys/darwin/mach/nlist.lo \
core/sys/darwin/mach/port.lo core/sys/darwin/mach/semaphore.lo \
@@ -322,7 +323,8 @@ am__objects_15 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/err.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
+ core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo \
+ core/sys/openbsd/unistd.lo
@DRUNTIME_OS_OPENBSD_TRUE@am__objects_16 = $(am__objects_15)
am__objects_17 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
core/sys/linux/elf.lo core/sys/linux/epoll.lo \
@@ -408,23 +410,24 @@ am__objects_19 = core/sys/windows/accctrl.lo \
core/sys/windows/sql.lo core/sys/windows/sqlext.lo \
core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \
core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \
- core/sys/windows/stat.lo core/sys/windows/stdc/time.lo \
- core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \
- core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \
- core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \
- core/sys/windows/vfw.lo core/sys/windows/w32api.lo \
- core/sys/windows/winbase.lo core/sys/windows/winber.lo \
- core/sys/windows/wincon.lo core/sys/windows/wincrypt.lo \
- core/sys/windows/windef.lo core/sys/windows/windows.lo \
- core/sys/windows/winerror.lo core/sys/windows/wingdi.lo \
- core/sys/windows/winhttp.lo core/sys/windows/wininet.lo \
- core/sys/windows/winioctl.lo core/sys/windows/winldap.lo \
- core/sys/windows/winnetwk.lo core/sys/windows/winnls.lo \
- core/sys/windows/winnt.lo core/sys/windows/winperf.lo \
- core/sys/windows/winreg.lo core/sys/windows/winsock2.lo \
- core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
- core/sys/windows/winuser.lo core/sys/windows/winver.lo \
- core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
+ core/sys/windows/stat.lo core/sys/windows/stdc/malloc.lo \
+ core/sys/windows/stdc/time.lo core/sys/windows/subauth.lo \
+ core/sys/windows/threadaux.lo core/sys/windows/tlhelp32.lo \
+ core/sys/windows/tmschema.lo core/sys/windows/unknwn.lo \
+ core/sys/windows/uuid.lo core/sys/windows/vfw.lo \
+ core/sys/windows/w32api.lo core/sys/windows/winbase.lo \
+ core/sys/windows/winber.lo core/sys/windows/wincon.lo \
+ core/sys/windows/wincrypt.lo core/sys/windows/windef.lo \
+ core/sys/windows/windows.lo core/sys/windows/winerror.lo \
+ core/sys/windows/wingdi.lo core/sys/windows/winhttp.lo \
+ core/sys/windows/wininet.lo core/sys/windows/winioctl.lo \
+ core/sys/windows/winldap.lo core/sys/windows/winnetwk.lo \
+ core/sys/windows/winnls.lo core/sys/windows/winnt.lo \
+ core/sys/windows/winperf.lo core/sys/windows/winreg.lo \
+ core/sys/windows/winsock2.lo core/sys/windows/winspool.lo \
+ core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \
+ core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \
+ core/sys/windows/wtypes.lo
@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
@@ -837,16 +840,17 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
- core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \
- core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
- core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
- core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
- core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
- core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
- core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
- core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
- core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
- core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
+ core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
+ core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
+ core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+ core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
+ core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
+ core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
+ core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+ core/sys/darwin/stdlib.d core/sys/darwin/string.d \
+ core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
+ core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
+ core/sys/darwin/sys/sysctl.d
DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
@@ -904,7 +908,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.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/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 \
@@ -1011,23 +1016,23 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
core/sys/windows/stacktrace.d core/sys/windows/stat.d \
- core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
- core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
- core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
- core/sys/windows/uuid.d core/sys/windows/vfw.d \
- core/sys/windows/w32api.d core/sys/windows/winbase.d \
- core/sys/windows/winber.d core/sys/windows/wincon.d \
- core/sys/windows/wincrypt.d core/sys/windows/windef.d \
- core/sys/windows/windows.d core/sys/windows/winerror.d \
- core/sys/windows/wingdi.d core/sys/windows/winhttp.d \
- core/sys/windows/wininet.d core/sys/windows/winioctl.d \
- core/sys/windows/winldap.d core/sys/windows/winnetwk.d \
- core/sys/windows/winnls.d core/sys/windows/winnt.d \
- core/sys/windows/winperf.d core/sys/windows/winreg.d \
- core/sys/windows/winsock2.d core/sys/windows/winspool.d \
- core/sys/windows/winsvc.d core/sys/windows/winuser.d \
- core/sys/windows/winver.d core/sys/windows/wtsapi32.d \
- core/sys/windows/wtypes.d
+ core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \
+ core/sys/windows/subauth.d core/sys/windows/threadaux.d \
+ core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \
+ core/sys/windows/unknwn.d core/sys/windows/uuid.d \
+ core/sys/windows/vfw.d core/sys/windows/w32api.d \
+ core/sys/windows/winbase.d core/sys/windows/winber.d \
+ core/sys/windows/wincon.d core/sys/windows/wincrypt.d \
+ core/sys/windows/windef.d core/sys/windows/windows.d \
+ core/sys/windows/winerror.d core/sys/windows/wingdi.d \
+ core/sys/windows/winhttp.d core/sys/windows/wininet.d \
+ core/sys/windows/winioctl.d core/sys/windows/winldap.d \
+ core/sys/windows/winnetwk.d core/sys/windows/winnls.d \
+ core/sys/windows/winnt.d core/sys/windows/winperf.d \
+ core/sys/windows/winreg.d core/sys/windows/winsock2.d \
+ core/sys/windows/winspool.d core/sys/windows/winsvc.d \
+ core/sys/windows/winuser.d core/sys/windows/winver.d \
+ core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
DRUNTIME_DISOURCES = __entrypoint.di __main.di
all: all-am
@@ -1346,6 +1351,7 @@ core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/err.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/fcntl.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/ifaddrs.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/mach/$(am__dirstamp):
@$(MKDIR_P) core/sys/darwin/mach
@@ -1510,6 +1516,7 @@ core/sys/openbsd/sys/link_elf.lo: \
core/sys/openbsd/sys/mman.lo: core/sys/openbsd/sys/$(am__dirstamp)
core/sys/openbsd/sys/sysctl.lo: core/sys/openbsd/sys/$(am__dirstamp)
core/sys/openbsd/time.lo: core/sys/openbsd/$(am__dirstamp)
+core/sys/openbsd/unistd.lo: core/sys/openbsd/$(am__dirstamp)
core/sys/linux/$(am__dirstamp):
@$(MKDIR_P) core/sys/linux
@: > core/sys/linux/$(am__dirstamp)
@@ -1690,6 +1697,8 @@ core/sys/windows/stat.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/stdc/$(am__dirstamp):
@$(MKDIR_P) core/sys/windows/stdc
@: > core/sys/windows/stdc/$(am__dirstamp)
+core/sys/windows/stdc/malloc.lo: \
+ core/sys/windows/stdc/$(am__dirstamp)
core/sys/windows/stdc/time.lo: core/sys/windows/stdc/$(am__dirstamp)
core/sys/windows/subauth.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/threadaux.lo: core/sys/windows/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/stdc/complex.d b/libphobos/libdruntime/core/stdc/complex.d
index d878366..b84651f 100644
--- a/libphobos/libdruntime/core/stdc/complex.d
+++ b/libphobos/libdruntime/core/stdc/complex.d
@@ -19,163 +19,97 @@ extern (C):
nothrow:
@nogc:
-///
+// @@@DEPRECATED_2.105@@@
+deprecated:
alias creal complex;
-///
alias ireal imaginary;
-///
cdouble cacos(cdouble z);
-///
cfloat cacosf(cfloat z);
-///
creal cacosl(creal z);
-///
cdouble casin(cdouble z);
-///
cfloat casinf(cfloat z);
-///
creal casinl(creal z);
-///
cdouble catan(cdouble z);
-///
cfloat catanf(cfloat z);
-///
creal catanl(creal z);
-///
cdouble ccos(cdouble z);
-///
cfloat ccosf(cfloat z);
-///
creal ccosl(creal z);
-///
cdouble csin(cdouble z);
-///
cfloat csinf(cfloat z);
-///
creal csinl(creal z);
-///
cdouble ctan(cdouble z);
-///
cfloat ctanf(cfloat z);
-///
creal ctanl(creal z);
-///
cdouble cacosh(cdouble z);
-///
cfloat cacoshf(cfloat z);
-///
creal cacoshl(creal z);
-///
cdouble casinh(cdouble z);
-///
cfloat casinhf(cfloat z);
-///
creal casinhl(creal z);
-///
cdouble catanh(cdouble z);
-///
cfloat catanhf(cfloat z);
-///
creal catanhl(creal z);
-///
cdouble ccosh(cdouble z);
-///
cfloat ccoshf(cfloat z);
-///
creal ccoshl(creal z);
-///
cdouble csinh(cdouble z);
-///
cfloat csinhf(cfloat z);
-///
creal csinhl(creal z);
-///
cdouble ctanh(cdouble z);
-///
cfloat ctanhf(cfloat z);
-///
creal ctanhl(creal z);
-///
cdouble cexp(cdouble z);
-///
cfloat cexpf(cfloat z);
-///
creal cexpl(creal z);
-///
cdouble clog(cdouble z);
-///
cfloat clogf(cfloat z);
-///
creal clogl(creal z);
-///
double cabs(cdouble z);
- ///
float cabsf(cfloat z);
- ///
real cabsl(creal z);
- ///
cdouble cpow(cdouble x, cdouble y);
-///
cfloat cpowf(cfloat x, cfloat y);
-///
creal cpowl(creal x, creal y);
-///
cdouble csqrt(cdouble z);
-///
cfloat csqrtf(cfloat z);
-///
creal csqrtl(creal z);
-///
double carg(cdouble z);
- ///
float cargf(cfloat z);
- ///
real cargl(creal z);
-///
pragma(inline, true) double cimag(cdouble z) { return z.im; }
-///
pragma(inline, true) float cimagf(cfloat z) { return z.im; }
-///
pragma(inline, true) real cimagl(creal z) { return z.im; }
-///
cdouble conj(cdouble z);
-///
cfloat conjf(cfloat z);
-///
creal conjl(creal z);
-///
cdouble cproj(cdouble z);
-///
cfloat cprojf(cfloat z);
-///
creal cprojl(creal z);
// Note: `creal` is a keyword in D and so this function is inaccessible, use `creald` instead
//pragma(inline, true) double creal(cdouble z) { return z.re; }
-///
pragma(inline, true) double creald(cdouble z) { return z.re; }
-///
pragma(inline, true) float crealf(cfloat z) { return z.re; }
-///
pragma(inline, true) real creall(creal z) { return z.re; }
diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d
index cdb987f..802f5b6 100644
--- a/libphobos/libdruntime/core/stdc/config.d
+++ b/libphobos/libdruntime/core/stdc/config.d
@@ -34,6 +34,7 @@ version (StdDdoc)
alias ddoc_long = int;
alias ddoc_ulong = uint;
}
+ struct ddoc_complex(T) { T re; T im; };
}
/***
@@ -89,6 +90,24 @@ version (StdDdoc)
* C++ compiler's `ptrdiff_t` type.
*/
alias cpp_ptrdiff_t = ptrdiff_t;
+
+ /***
+ * Used for a complex floating point type that corresponds in size and ABI to the associated
+ * C compiler's `_Complex float` type.
+ */
+ alias c_complex_float = ddoc_complex!float;
+
+ /***
+ * Used for a complex floating point type that corresponds in size and ABI to the associated
+ * C compiler's `_Complex double` type.
+ */
+ alias c_complex_double = ddoc_complex!double;
+
+ /***
+ * Used for a complex floating point type that corresponds in size and ABI to the associated
+ * C compiler's `_Complex long double` type.
+ */
+ alias c_complex_real = ddoc_complex!real;
}
else
{
@@ -230,4 +249,28 @@ else
alias cpp_size_t = size_t;
alias cpp_ptrdiff_t = ptrdiff_t;
}
+
+// ABI layout of native complex types.
+private struct _Complex(T)
+{
+ T re;
+ T im;
+}
+
+version (Posix)
+{
+ align(float.alignof) enum __c_complex_float : _Complex!float;
+ align(double.alignof) enum __c_complex_double : _Complex!double;
+ align(real.alignof) enum __c_complex_real : _Complex!real;
+}
+else
+{
+ align(float.sizeof * 2) enum __c_complex_float : _Complex!float;
+ align(double.sizeof * 2) enum __c_complex_double : _Complex!double;
+ align(real.alignof) enum __c_complex_real : _Complex!real;
+}
+
+alias c_complex_float = __c_complex_float;
+alias c_complex_double = __c_complex_double;
+alias c_complex_real = __c_complex_real;
}
diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d
index 31f7d11..57bc15d 100644
--- a/libphobos/libdruntime/core/stdc/errno.d
+++ b/libphobos/libdruntime/core/stdc/errno.d
@@ -156,15 +156,9 @@ else version (Haiku)
else
{
///
- @property int errno() { return getErrno(); }
+ extern(C) pragma(mangle, "getErrno") @property int errno();
///
- @property int errno(int n) { return setErrno(n); }
-
- extern (C)
- {
- private int getErrno(); // for internal use
- private int setErrno(int); // for internal use
- }
+ extern(C) pragma(mangle, "setErrno") @property int errno(int n);
}
extern (C):
@@ -1532,7 +1526,11 @@ else version (OpenBSD)
enum EIDRM = 89; /// Identifier removed
enum ENOMSG = 90; /// No message of desired type
enum ENOTSUP = 91; /// Not supported
- enum ELAST = 91; /// Must be equal largest errno
+ enum EBADMSG = 92; /// Bad message
+ enum ENOTRECOVERABLE = 93; /// State not recoverable
+ enum EOWNERDEAD = 94; /// Previous owner died
+ enum EPROTO = 95; /// Protocol error
+ enum ELAST = 95; /// Must be equal largest errno
}
else version (DragonFlyBSD)
{
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index e8d1fa8..fba78ee 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -319,16 +319,12 @@ version (CRuntime_DigitalMars)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassify_f(x); }
+ extern(C) pragma(mangle, "__fpclassify_f") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassify_d(x); }
+ extern(C) pragma(mangle, "__fpclassify_d") pure int fpclassify(double x);
///
- pure int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassify_d(x)
- : __fpclassify_ld(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify_d" : "__fpclassify_ld")
+ pure int fpclassify(real x);
//int isfinite(real-floating x);
///
@@ -442,24 +438,18 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
FP_NAN = 2,
}
- pure private short _fdclass(float x);
- pure private short _dclass(double x);
-
- pure private int _fdsign(float x);
- pure private int _dsign(double x);
-
extern(D)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify()(float x) { return _fdclass(x); }
+ extern(C) pragma(mangle, "_fdclass") pure int fpclassify(float x);
///
- pure int fpclassify()(double x) { return _dclass(x); }
+ extern(C) pragma(mangle, "_dclass") pure int fpclassify(double x);
///
pure int fpclassify()(real x)
{
static if (real.sizeof == double.sizeof)
- return _dclass(cast(double) x);
+ return fpclassify(cast(double) x);
else
static assert(false, "fpclassify(real) not supported by MS C runtime");
}
@@ -495,7 +485,7 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
///
pure int isnan(float x) { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); }
///
- pure int isnan(double x) { return _isnan(x); }
+ extern(C) pragma(mangle, "_isnan") pure int isnan(double x);
///
pure int isnan(real x) { return _isnan(cast(double) x); }
}
@@ -510,14 +500,14 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
//int signbit(real-floating x);
///
- pure int signbit()(float x) { return _fdsign(x); }
+ extern(C) pragma(mangle, "_fdsign") pure int signbit(float x);
///
- pure int signbit()(double x) { return _dsign(x); }
+ extern(C) pragma(mangle, "_dsign") pure int signbit(double x);
///
pure int signbit()(real x)
{
static if (real.sizeof == double.sizeof)
- return _dsign(cast(double) x);
+ return signbit(cast(double) x);
else
return (cast(short*)&(x))[4] & 0x8000;
}
@@ -573,55 +563,39 @@ else version (CRuntime_Glibc)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassify(x); }
+ extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x);
///
- pure int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassify(x)
- : __fpclassifyl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+ pure int fpclassify(real x);
//int isfinite(real-floating x);
///
- pure int isfinite(float x) { return __finitef(x); }
+ extern(C) pragma(mangle, "__finitef") pure int isfinite(float x);
///
- pure int isfinite(double x) { return __finite(x); }
+ extern(C) pragma(mangle, "__finite") pure int isfinite(double x);
///
- pure int isfinite(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __finite(x)
- : __finitel(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel")
+ pure int isfinite(real x);
//int isinf(real-floating x);
///
- pure int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
///
- pure int isinf(double x) { return __isinf(x); }
+ extern(C) pragma(mangle, "__isinf") pure int isinf(double x);
///
- pure int isinf(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isinf(x)
- : __isinfl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl")
+ pure int isinf(real x);
//int isnan(real-floating x);
///
- pure int isnan(float x) { return __isnanf(x); }
+ extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
///
- pure int isnan(double x) { return __isnan(x); }
+ extern(C) pragma(mangle, "__isnan") pure int isnan(double x);
///
- pure int isnan(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isnan(x)
- : __isnanl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+ pure int isnan(real x);
//int isnormal(real-floating x);
///
@@ -633,16 +607,12 @@ else version (CRuntime_Glibc)
//int signbit(real-floating x);
///
- pure int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- pure int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
///
- pure int signbit(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __signbit(x)
- : __signbitl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+ pure int signbit(real x);
}
}
else version (CRuntime_Musl)
@@ -685,16 +655,12 @@ else version (CRuntime_Musl)
{
//int fpclassify(real-floating x);
///
- int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x);
///
- int fpclassify(double x) { return __fpclassify(x); }
+ extern(C) pragma(mangle, "__fpclassify") int fpclassify(double x);
///
- int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassify(x)
- : __fpclassifyl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+ int fpclassify(real x);
private uint __FLOAT_BITS(float __f)
{
union __u_t {
@@ -765,16 +731,12 @@ else version (CRuntime_Musl)
//int signbit(real-floating x);
///
- int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") int signbit(float x);
///
- int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") int signbit(double x);
///
- int signbit(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __signbit(x)
- : __signbitl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+ int signbit(real x);
}
}
else version (CRuntime_UClibc)
@@ -826,52 +788,36 @@ else version (CRuntime_UClibc)
extern (D)
{
///
- int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x);
///
- int fpclassify(double x) { return __fpclassify(x); }
+ extern(C) pragma(mangle, "__fpclassify") int fpclassify(double x);
///
- int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassify(x)
- : __fpclassifyl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+ int fpclassify(real x);
///
- int isfinite(float x) { return __finitef(x); }
+ extern(C) pragma(mangle, "__finitef") int isfinite(float x);
///
- int isfinite(double x) { return __finite(x); }
+ extern(C) pragma(mangle, "__finite") int isfinite(double x);
///
- int isfinite(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __finite(x)
- : __finitel(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel")
+ int isfinite(real x);
///
- int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") int isinf(float x);
///
- int isinf(double x) { return __isinf(x); }
+ extern(C) pragma(mangle, "__isinf") int isinf(double x);
///
- int isinf(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isinf(x)
- : __isinfl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl")
+ int isinf(real x);
///
- int isnan(float x) { return __isnanf(x); }
+ extern(C) pragma(mangle, "__isnanf") int isnan(float x);
///
- int isnan(double x) { return __isnan(x); }
+ extern(C) pragma(mangle, "__isnan") int isnan(double x);
///
- int isnan(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isnan(x)
- : __isnanl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+ int isnan(real x);
///
int isnormal(float x) { return fpclassify(x) == FP_NORMAL; }
@@ -881,16 +827,12 @@ else version (CRuntime_UClibc)
int isnormal(real x) { return fpclassify(x) == FP_NORMAL; }
///
- int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") int signbit(float x);
///
- int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") int signbit(double x);
///
- int signbit(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __signbit(x)
- : __signbitl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+ int signbit(real x);
}
}
else version (MinGW)
@@ -925,16 +867,12 @@ else version (MinGW)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassify(x); }
+ extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x);
///
- pure int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassify(x)
- : __fpclassifyl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+ pure int fpclassify(real x);
//int isfinite(real-floating x);
///
@@ -954,16 +892,12 @@ else version (MinGW)
//int isnan(real-floating x);
///
- pure int isnan(float x) { return __isnanf(x); }
+ extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
///
- pure int isnan(double x) { return __isnan(x); }
+ extern(C) pragma(mangle, "__isnan") pure int isnan(double x);
///
- pure int isnan(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isnan(x)
- : __isnanl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+ pure int isnan(real x);
//int isnormal(real-floating x);
///
@@ -975,16 +909,12 @@ else version (MinGW)
//int signbit(real-floating x);
///
- int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
///
- int signbit(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __signbit(x)
- : __signbitl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+ int signbit(real x);
}
}
else version (Darwin)
@@ -1070,35 +1000,35 @@ else version (Darwin)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassifyd(x); }
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
///
- pure int fpclassify(real x) { return __fpclassifyl(x); }
+ extern(C) pragma(mangle, __fpclassifyl.mangleof) pure int fpclassify(real x);
//int isfinite(real-floating x);
///
- pure int isfinite(float x) { return __isfinitef(x); }
+ extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
///
- pure int isfinite(double x) { return __isfinited(x); }
+ extern(C) pragma(mangle, "__isfinited") pure int isfinite(double x);
///
- pure int isfinite(real x) { return __isfinitel(x); }
+ extern(C) pragma(mangle, __isfinitel.mangleof) pure int isfinite(real x);
//int isinf(real-floating x);
///
- pure int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
///
- pure int isinf(double x) { return __isinfd(x); }
+ extern(C) pragma(mangle, "__isinfd") pure int isinf(double x);
///
- pure int isinf(real x) { return __isinfl(x); }
+ extern(C) pragma(mangle, __isinfl.mangleof) pure int isinf(real x);
//int isnan(real-floating x);
///
- pure int isnan(float x) { return __isnanf(x); }
+ extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
///
- pure int isnan(double x) { return __isnand(x); }
+ extern(C) pragma(mangle, "__isnand") pure int isnan(double x);
///
- pure int isnan(real x) { return __isnanl(x); }
+ extern(C) pragma(mangle, __isnanl.mangleof) pure int isnan(real x);
//int isnormal(real-floating x);
///
@@ -1110,11 +1040,11 @@ else version (Darwin)
//int signbit(real-floating x);
///
- pure int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- pure int signbit(double x) { return __signbitd(x); }
+ extern(C) pragma(mangle, "__signbitd") pure int signbit(double x);
///
- pure int signbit(real x) { return __signbitl(x); }
+ extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
}
}
else version (FreeBSD)
@@ -1163,27 +1093,27 @@ else version (FreeBSD)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassifyd(x); }
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
///
- pure int fpclassify(real x) { return __fpclassifyl(x); }
+ extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
//int isfinite(real-floating x);
///
- pure int isfinite(float x) { return __isfinitef(x); }
+ extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
///
- pure int isfinite(double x) { return __isfinite(x); }
+ extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x);
///
- pure int isfinite(real x) { return __isfinitel(x); }
+ extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
//int isinf(real-floating x);
///
- pure int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
///
pure int isinf(double x) { return __isinfl(x); }
///
- pure int isinf(real x) { return __isinfl(x); }
+ extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
//int isnan(real-floating x);
///
@@ -1191,21 +1121,21 @@ else version (FreeBSD)
///
pure int isnan(double x) { return __isnanl(x); }
///
- pure int isnan(real x) { return __isnanl(x); }
+ extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
//int isnormal(real-floating x);
///
- pure int isnormal(float x) { return __isnormalf(x); }
+ extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
///
- pure int isnormal(double x) { return __isnormal(x); }
+ extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x);
///
- pure int isnormal(real x) { return __isnormall(x); }
+ extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
//int signbit(real-floating x);
///
- pure int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- pure int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
///
pure int signbit(real x) { return __signbit(x); }
}
@@ -1256,27 +1186,27 @@ else version (OpenBSD)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassifyd(x); }
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
///
- pure int fpclassify(real x) { return __fpclassifyl(x); }
+ extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
//int isfinite(real-floating x);
///
- pure int isfinite(float x) { return __isfinitef(x); }
+ extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
///
- pure int isfinite(double x) { return __isfinite(x); }
+ extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x);
///
- pure int isfinite(real x) { return __isfinitel(x); }
+ extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
//int isinf(real-floating x);
///
- pure int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
///
pure int isinf(double x) { return __isinfl(x); }
///
- pure int isinf(real x) { return __isinfl(x); }
+ extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
//int isnan(real-floating x);
///
@@ -1284,21 +1214,21 @@ else version (OpenBSD)
///
pure int isnan(double x) { return __isnanl(x); }
///
- pure int isnan(real x) { return __isnanl(x); }
+ extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
//int isnormal(real-floating x);
///
- pure int isnormal(float x) { return __isnormalf(x); }
+ extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
///
- pure int isnormal(double x) { return __isnormal(x); }
+ extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x);
///
- pure int isnormal(real x) { return __isnormall(x); }
+ extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
//int signbit(real-floating x);
///
- pure int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- pure int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
///
pure int signbit(real x) { return __signbit(x); }
}
@@ -1337,16 +1267,12 @@ else version (NetBSD)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassifyd(x); }
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
///
- pure int fpclassify(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __fpclassifyd(x)
- : __fpclassifyl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassifyd" : "__fpclassifyl")
+ pure int fpclassify(real x);
//int isfinite(real-floating x);
///
@@ -1433,29 +1359,29 @@ else version (DragonFlyBSD)
extern (D)
{
- pure int fpclassify(float x) { return __fpclassifyf(x); }
- pure int fpclassify(double x) { return __fpclassifyd(x); }
- pure int fpclassify(real x) { return __fpclassifyl(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
+ extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
- pure int isfinite(float x) { return __isfinitef(x); }
- pure int isfinite(double x) { return __isfinite(x); }
- pure int isfinite(real x) { return __isfinitel(x); }
+ extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
+ extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x);
+ extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
- pure int isinf(float x) { return __isinff(x); }
- pure int isinf(double x) { return __isinf(x); }
- pure int isinf(real x) { return __isinfl(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
+ extern(C) pragma(mangle, "__isinf") pure int isinf(double x);
+ extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
- pure int isnan(float x) { return __isnanf(x); }
- pure int isnan(double x) { return __isnan(x); }
- pure int isnan(real x) { return __isnanl(x); }
+ extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
+ extern(C) pragma(mangle, "__isnan") pure int isnan(double x);
+ extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
- pure int isnormal(float x) { return __isnormalf(x); }
- pure int isnormal(double x) { return __isnormal(x); }
- pure int isnormal(real x) { return __isnormall(x); }
+ extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
+ extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x);
+ extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
- pure int signbit(float x) { return __signbitf(x); }
- pure int signbit(double x) { return __signbit(x); }
- pure int signbit(real x) { return __signbitl(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
+ extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
}
}
else version (Solaris)
@@ -1468,16 +1394,12 @@ else version (Solaris)
{
//int isnan(real-floating x);
///
- pure int isnan(float x) { return __isnanf(x); }
+ extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
///
- pure int isnan(double x) { return __isnan(x); }
+ extern(C) pragma(mangle, "__isnan") pure int isnan(double x);
///
- pure int isnan(real x)
- {
- return (real.sizeof == double.sizeof)
- ? __isnan(x)
- : __isnanl(x);
- }
+ extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+ pure int isnan(real x);
}
}
else version (CRuntime_Bionic)
@@ -1527,49 +1449,49 @@ else version (CRuntime_Bionic)
{
//int fpclassify(real-floating x);
///
- pure int fpclassify(float x) { return __fpclassifyf(x); }
+ extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
///
- pure int fpclassify(double x) { return __fpclassifyd(x); }
+ extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
///
- pure int fpclassify(real x) { return __fpclassifyl(x); }
+ extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
//int isfinite(real-floating x);
///
- pure int isfinite(float x) { return __isfinitef(x); }
+ extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
///
- pure int isfinite(double x) { return __isfinite(x); }
+ extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x);
///
- pure int isfinite(real x) { return __isfinitel(x); }
+ extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
//int isinf(real-floating x);
///
- pure int isinf(float x) { return __isinff(x); }
+ extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
///
- pure int isinf(double x) { return __isinf(x); }
+ extern(C) pragma(mangle, "__isinf") pure int isinf(double x);
///
- pure int isinf(real x) { return __isinfl(x); }
+ extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
//int isnan(real-floating x);
///
- pure int isnan(float x) { return isnanf(x); }
+ extern(C) pragma(mangle, "isnanf") pure int isnan(float x);
///
- pure int isnan(real x) { return __isnanl(x); }
+ extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
//int isnormal(real-floating x);
///
- pure int isnormal(float x) { return __isnormalf(x); }
+ extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
///
- pure int isnormal(double x) { return __isnormal(x); }
+ extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x);
///
- pure int isnormal(real x) { return __isnormall(x); }
+ extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
//int signbit(real-floating x);
///
- pure int signbit(float x) { return __signbitf(x); }
+ extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
///
- pure int signbit(double x) { return __signbit(x); }
+ extern(C) pragma(mangle, "__signbit") pure int signbit(double x);
///
- pure int signbit(real x) { return __signbitl(x); }
+ extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
}
}
@@ -1841,14 +1763,12 @@ version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) only
///
extern(D) pure real fabsl()(real x) { return fabs(cast(double) x); }
- private double _hypot(double x, double y);
- private float _hypotf(float x, float y);
///
- extern(D) double hypot(double x, double y) { return _hypot(x, y); }
+ extern(C) pragma(mangle, "_hypot") double hypot(double x, double y);
///
- extern(D) float hypotf(float x, float y) { return _hypotf(x, y); }
+ extern(C) pragma(mangle, "_hypotf") float hypotf(float x, float y);
///
- extern(D) real hypotl(real x, real y) { return _hypot(cast(double) x, cast(double) y); }
+ extern(D) real hypotl(real x, real y) { return hypot(cast(double) x, cast(double) y); }
///
double pow(double x, double y);
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 6701159..532a080 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -1166,61 +1166,73 @@ version (MinGW)
// Prefer the MinGW versions over the MSVC ones, as the latter don't handle
// reals at all.
///
+ pragma(printf)
int __mingw_fprintf(FILE* stream, scope const char* format, scope const ...);
///
alias __mingw_fprintf fprintf;
///
+ pragma(scanf)
int __mingw_fscanf(FILE* stream, scope const char* format, scope ...);
///
alias __mingw_fscanf fscanf;
///
+ pragma(printf)
int __mingw_sprintf(scope char* s, scope const char* format, scope const ...);
///
alias __mingw_sprintf sprintf;
///
+ pragma(scanf)
int __mingw_sscanf(scope const char* s, scope const char* format, scope ...);
///
alias __mingw_sscanf sscanf;
///
+ pragma(printf)
int __mingw_vfprintf(FILE* stream, scope const char* format, va_list arg);
///
alias __mingw_vfprintf vfprintf;
///
+ pragma(scanf)
int __mingw_vfscanf(FILE* stream, scope const char* format, va_list arg);
///
alias __mingw_vfscanf vfscanf;
///
+ pragma(printf)
int __mingw_vsprintf(scope char* s, scope const char* format, va_list arg);
///
alias __mingw_vsprintf vsprintf;
///
+ pragma(scanf)
int __mingw_vsscanf(scope const char* s, scope const char* format, va_list arg);
///
alias __mingw_vsscanf vsscanf;
///
+ pragma(printf)
int __mingw_vprintf(scope const char* format, va_list arg);
///
alias __mingw_vprintf vprintf;
///
+ pragma(scanf)
int __mingw_vscanf(scope const char* format, va_list arg);
///
alias __mingw_vscanf vscanf;
///
+ pragma(printf)
int __mingw_printf(scope const char* format, scope const ...);
///
alias __mingw_printf printf;
///
+ pragma(scanf)
int __mingw_scanf(scope const char* format, scope ...);
///
alias __mingw_scanf scanf;
@@ -1228,28 +1240,40 @@ version (MinGW)
else
{
///
+ pragma(printf)
int fprintf(FILE* stream, scope const char* format, scope const ...);
///
+ pragma(scanf)
int fscanf(FILE* stream, scope const char* format, scope ...);
///
+ pragma(printf)
int sprintf(scope char* s, scope const char* format, scope const ...);
///
+ pragma(scanf)
int sscanf(scope const char* s, scope const char* format, scope ...);
///
+ pragma(printf)
int vfprintf(FILE* stream, scope const char* format, va_list arg);
///
+ pragma(scanf)
int vfscanf(FILE* stream, scope const char* format, va_list arg);
///
+ pragma(printf)
int vsprintf(scope char* s, scope const char* format, va_list arg);
///
+ pragma(scanf)
int vsscanf(scope const char* s, scope const char* format, va_list arg);
///
+ pragma(printf)
int vprintf(scope const char* format, va_list arg);
///
+ pragma(scanf)
int vscanf(scope const char* format, va_list arg);
///
+ pragma(printf)
int printf(scope const char* format, scope const ...);
///
+ pragma(scanf)
int scanf(scope const char* format, scope ...);
}
@@ -1278,13 +1302,14 @@ extern (D) @trusted
int getchar()() { return getc(stdin); }
///
int putchar()(int c) { return putc(c,stdout); }
- ///
- int getc()(FILE* stream) { return fgetc(stream); }
- ///
- int putc()(int c, FILE* stream) { return fputc(c,stream); }
}
///
+alias getc = fgetc;
+///
+alias putc = fputc;
+
+///
@trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation.
///
@@ -1323,11 +1348,13 @@ version (CRuntime_DigitalMars)
pure int fileno()(FILE* stream) { return stream._file; }
}
///
+ pragma(printf)
int _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
///
alias _snprintf snprintf;
///
+ pragma(printf)
int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
///
alias _vsnprintf vsnprintf;
@@ -1351,6 +1378,7 @@ else version (CRuntime_Microsoft)
version (MinGW)
{
+ pragma(printf)
int __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
///
alias __mingw_snprintf _snprintf;
@@ -1358,6 +1386,7 @@ else version (CRuntime_Microsoft)
alias __mingw_snprintf snprintf;
///
+ pragma(printf)
int __mingw_vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
///
alias __mingw_vsnprintf _vsnprintf;
@@ -1367,13 +1396,17 @@ else version (CRuntime_Microsoft)
else
{
///
+ pragma(printf)
int _snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
@@ -1410,8 +1443,10 @@ else version (CRuntime_Glibc)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (Darwin)
@@ -1432,8 +1467,10 @@ else version (Darwin)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (FreeBSD)
@@ -1454,8 +1491,10 @@ else version (FreeBSD)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (NetBSD)
@@ -1476,8 +1515,10 @@ else version (NetBSD)
}
///
+ pragma(printf)
int snprintf(char* s, size_t n, const scope char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(char* s, size_t n, const scope char* format, va_list arg);
}
else version (OpenBSD)
@@ -1567,8 +1608,10 @@ else version (OpenBSD)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (DragonFlyBSD)
@@ -1599,7 +1642,9 @@ else version (DragonFlyBSD)
enum __SALC = 0x4000;
enum __SIGN = 0x8000;
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (Solaris)
@@ -1620,8 +1665,10 @@ else version (Solaris)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (CRuntime_Bionic)
@@ -1642,8 +1689,10 @@ else version (CRuntime_Bionic)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (CRuntime_Musl)
@@ -1663,8 +1712,10 @@ else version (CRuntime_Musl)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (CRuntime_UClibc)
@@ -1685,8 +1736,10 @@ else version (CRuntime_UClibc)
}
///
+ pragma(printf)
int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
+ pragma(printf)
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 7caef4c..5d69b88 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -164,13 +164,13 @@ void* realloc(void* ptr, size_t size);
void free(void* ptr);
///
-void abort() @safe;
+noreturn abort() @safe;
///
-void exit(int status);
+noreturn exit(int status);
///
int atexit(void function() func);
///
-void _Exit(int status);
+noreturn _Exit(int status);
///
char* getenv(scope const char* name);
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 4dd1b3c..2ff1522 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -32,12 +32,10 @@ version (NetBSD)
///
alias core.stdc.math.acosl acos;
- ///
- alias core.stdc.complex.cacos acos;
- ///
- alias core.stdc.complex.cacosf acos;
- ///
- alias core.stdc.complex.cacosl acos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacos acos;
+ deprecated alias core.stdc.complex.cacosf acos;
+ deprecated alias core.stdc.complex.cacosl acos;
///
alias core.stdc.math.asin asin;
@@ -46,12 +44,10 @@ version (NetBSD)
///
alias core.stdc.math.asinl asin;
- ///
- alias core.stdc.complex.casin asin;
- ///
- alias core.stdc.complex.casinf asin;
- ///
- alias core.stdc.complex.casinl asin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casin asin;
+ deprecated alias core.stdc.complex.casinf asin;
+ deprecated alias core.stdc.complex.casinl asin;
///
alias core.stdc.math.atan atan;
@@ -60,12 +56,10 @@ version (NetBSD)
///
alias core.stdc.math.atanl atan;
- ///
- alias core.stdc.complex.catan atan;
- ///
- alias core.stdc.complex.catanf atan;
- ///
- alias core.stdc.complex.catanl atan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catan atan;
+ deprecated alias core.stdc.complex.catanf atan;
+ deprecated alias core.stdc.complex.catanl atan;
///
alias core.stdc.math.atan2 atan2;
@@ -81,12 +75,10 @@ version (NetBSD)
///
alias core.stdc.math.cosl cos;
- ///
- alias core.stdc.complex.ccos cos;
- ///
- alias core.stdc.complex.ccosf cos;
- ///
- alias core.stdc.complex.ccosl cos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccos cos;
+ deprecated alias core.stdc.complex.ccosf cos;
+ deprecated alias core.stdc.complex.ccosl cos;
///
alias core.stdc.math.sin sin;
@@ -95,12 +87,10 @@ version (NetBSD)
///
alias core.stdc.math.sinl sin;
- ///
- alias core.stdc.complex.csin csin;
- ///
- alias core.stdc.complex.csinf csin;
- ///
- alias core.stdc.complex.csinl csin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csin csin;
+ deprecated alias core.stdc.complex.csinf csin;
+ deprecated alias core.stdc.complex.csinl csin;
///
alias core.stdc.math.tan tan;
@@ -109,12 +99,10 @@ version (NetBSD)
///
alias core.stdc.math.tanl tan;
- ///
- alias core.stdc.complex.ctan tan;
- ///
- alias core.stdc.complex.ctanf tan;
- ///
- alias core.stdc.complex.ctanl tan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctan tan;
+ deprecated alias core.stdc.complex.ctanf tan;
+ deprecated alias core.stdc.complex.ctanl tan;
///
alias core.stdc.math.acosh acosh;
@@ -123,12 +111,10 @@ version (NetBSD)
///
alias core.stdc.math.acoshl acosh;
- ///
- alias core.stdc.complex.cacosh acosh;
- ///
- alias core.stdc.complex.cacoshf acosh;
- ///
- alias core.stdc.complex.cacoshl acosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacosh acosh;
+ deprecated alias core.stdc.complex.cacoshf acosh;
+ deprecated alias core.stdc.complex.cacoshl acosh;
///
alias core.stdc.math.asinh asinh;
@@ -137,12 +123,10 @@ version (NetBSD)
///
alias core.stdc.math.asinhl asinh;
- ///
- alias core.stdc.complex.casinh asinh;
- ///
- alias core.stdc.complex.casinhf asinh;
- ///
- alias core.stdc.complex.casinhl asinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casinh asinh;
+ deprecated alias core.stdc.complex.casinhf asinh;
+ deprecated alias core.stdc.complex.casinhl asinh;
///
alias core.stdc.math.atanh atanh;
@@ -151,12 +135,10 @@ version (NetBSD)
///
alias core.stdc.math.atanhl atanh;
- ///
- alias core.stdc.complex.catanh atanh;
- ///
- alias core.stdc.complex.catanhf atanh;
- ///
- alias core.stdc.complex.catanhl atanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catanh atanh;
+ deprecated alias core.stdc.complex.catanhf atanh;
+ deprecated alias core.stdc.complex.catanhl atanh;
///
alias core.stdc.math.cosh cosh;
@@ -165,12 +147,10 @@ version (NetBSD)
///
alias core.stdc.math.coshl cosh;
- ///
- alias core.stdc.complex.ccosh cosh;
- ///
- alias core.stdc.complex.ccoshf cosh;
- ///
- alias core.stdc.complex.ccoshl cosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccosh cosh;
+ deprecated alias core.stdc.complex.ccoshf cosh;
+ deprecated alias core.stdc.complex.ccoshl cosh;
///
alias core.stdc.math.sinh sinh;
@@ -179,12 +159,10 @@ version (NetBSD)
///
alias core.stdc.math.sinhl sinh;
- ///
- alias core.stdc.complex.csinh sinh;
- ///
- alias core.stdc.complex.csinhf sinh;
- ///
- alias core.stdc.complex.csinhl sinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csinh sinh;
+ deprecated alias core.stdc.complex.csinhf sinh;
+ deprecated alias core.stdc.complex.csinhl sinh;
///
alias core.stdc.math.tanh tanh;
@@ -193,12 +171,10 @@ version (NetBSD)
///
alias core.stdc.math.tanhl tanh;
- ///
- alias core.stdc.complex.ctanh tanh;
- ///
- alias core.stdc.complex.ctanhf tanh;
- ///
- alias core.stdc.complex.ctanhl tanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctanh tanh;
+ deprecated alias core.stdc.complex.ctanhf tanh;
+ deprecated alias core.stdc.complex.ctanhl tanh;
///
alias core.stdc.math.exp exp;
@@ -207,12 +183,10 @@ version (NetBSD)
///
alias core.stdc.math.expl exp;
- ///
- alias core.stdc.complex.cexp exp;
- ///
- alias core.stdc.complex.cexpf exp;
- ///
- alias core.stdc.complex.cexpl exp;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cexp exp;
+ deprecated alias core.stdc.complex.cexpf exp;
+ deprecated alias core.stdc.complex.cexpl exp;
///
alias core.stdc.math.exp2 exp2;
@@ -256,12 +230,10 @@ version (NetBSD)
///
alias core.stdc.math.logl log;
- ///
- alias core.stdc.complex.clog log;
- ///
- alias core.stdc.complex.clogf log;
- ///
- alias core.stdc.complex.clogl log;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.clog log;
+ deprecated alias core.stdc.complex.clogf log;
+ deprecated alias core.stdc.complex.clogl log;
///
alias core.stdc.math.log10 log10;
@@ -325,12 +297,10 @@ version (NetBSD)
///
alias core.stdc.math.fabsl fabs;
- ///
- alias core.stdc.complex.cabs fabs;
- ///
- alias core.stdc.complex.cabsf fabs;
- ///
- alias core.stdc.complex.cabsl fabs;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cabs fabs;
+ deprecated alias core.stdc.complex.cabsf fabs;
+ deprecated alias core.stdc.complex.cabsl fabs;
///
alias core.stdc.math.hypot hypot;
@@ -346,12 +316,10 @@ version (NetBSD)
///
alias core.stdc.math.powl pow;
- ///
- alias core.stdc.complex.cpow pow;
- ///
- alias core.stdc.complex.cpowf pow;
- ///
- alias core.stdc.complex.cpowl pow;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cpow pow;
+ deprecated alias core.stdc.complex.cpowf pow;
+ deprecated alias core.stdc.complex.cpowl pow;
///
alias core.stdc.math.sqrt sqrt;
@@ -360,12 +328,10 @@ version (NetBSD)
///
alias core.stdc.math.sqrtl sqrt;
- ///
- alias core.stdc.complex.csqrt sqrt;
- ///
- alias core.stdc.complex.csqrtf sqrt;
- ///
- alias core.stdc.complex.csqrtl sqrt;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csqrt sqrt;
+ deprecated alias core.stdc.complex.csqrtf sqrt;
+ deprecated alias core.stdc.complex.csqrtl sqrt;
///
alias core.stdc.math.erf erf;
@@ -539,37 +505,23 @@ version (NetBSD)
///
alias core.stdc.math.fmal fma;
- ///
- alias core.stdc.complex.carg carg;
- ///
- alias core.stdc.complex.cargf carg;
- ///
- alias core.stdc.complex.cargl carg;
-
- ///
- alias core.stdc.complex.cimag cimag;
- ///
- alias core.stdc.complex.cimagf cimag;
- ///
- alias core.stdc.complex.cimagl cimag;
-
- ///
- alias core.stdc.complex.conj conj;
- ///
- alias core.stdc.complex.conjf conj;
- ///
- alias core.stdc.complex.conjl conj;
-
- ///
- alias core.stdc.complex.cproj cproj;
- ///
- alias core.stdc.complex.cprojf cproj;
- ///
- alias core.stdc.complex.cprojl cproj;
-
-// alias core.stdc.complex.creal creal;
-// alias core.stdc.complex.crealf creal;
-// alias core.stdc.complex.creall creal;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.carg carg;
+ deprecated alias core.stdc.complex.cargf carg;
+ deprecated alias core.stdc.complex.cargl carg;
+ deprecated alias core.stdc.complex.cimag cimag;
+ deprecated alias core.stdc.complex.cimagf cimag;
+ deprecated alias core.stdc.complex.cimagl cimag;
+ deprecated alias core.stdc.complex.conj conj;
+ deprecated alias core.stdc.complex.conjf conj;
+ deprecated alias core.stdc.complex.conjl conj;
+ deprecated alias core.stdc.complex.cproj cproj;
+ deprecated alias core.stdc.complex.cprojf cproj;
+ deprecated alias core.stdc.complex.cprojl cproj;
+
+// deprecated alias core.stdc.complex.creal creal;
+// deprecated alias core.stdc.complex.crealf creal;
+// deprecated alias core.stdc.complex.creall creal;
}
else version (OpenBSD)
{
@@ -580,12 +532,10 @@ else version (OpenBSD)
///
alias core.stdc.math.acosl acos;
- ///
- alias core.stdc.complex.cacos acos;
- ///
- alias core.stdc.complex.cacosf acos;
- ///
- alias core.stdc.complex.cacosl acos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacos acos;
+ deprecated alias core.stdc.complex.cacosf acos;
+ deprecated alias core.stdc.complex.cacosl acos;
///
alias core.stdc.math.asin asin;
@@ -594,12 +544,10 @@ else version (OpenBSD)
///
alias core.stdc.math.asinl asin;
- ///
- alias core.stdc.complex.casin asin;
- ///
- alias core.stdc.complex.casinf asin;
- ///
- alias core.stdc.complex.casinl asin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casin asin;
+ deprecated alias core.stdc.complex.casinf asin;
+ deprecated alias core.stdc.complex.casinl asin;
///
alias core.stdc.math.atan atan;
@@ -608,12 +556,10 @@ else version (OpenBSD)
///
alias core.stdc.math.atanl atan;
- ///
- alias core.stdc.complex.catan atan;
- ///
- alias core.stdc.complex.catanf atan;
- ///
- alias core.stdc.complex.catanl atan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catan atan;
+ deprecated alias core.stdc.complex.catanf atan;
+ deprecated alias core.stdc.complex.catanl atan;
///
alias core.stdc.math.atan2 atan2;
@@ -629,12 +575,10 @@ else version (OpenBSD)
///
alias core.stdc.math.cosl cos;
- ///
- alias core.stdc.complex.ccos cos;
- ///
- alias core.stdc.complex.ccosf cos;
- ///
- alias core.stdc.complex.ccosl cos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccos cos;
+ deprecated alias core.stdc.complex.ccosf cos;
+ deprecated alias core.stdc.complex.ccosl cos;
///
alias core.stdc.math.sin sin;
@@ -643,12 +587,10 @@ else version (OpenBSD)
///
alias core.stdc.math.sinl sin;
- ///
- alias core.stdc.complex.csin csin;
- ///
- alias core.stdc.complex.csinf csin;
- ///
- alias core.stdc.complex.csinl csin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csin csin;
+ deprecated alias core.stdc.complex.csinf csin;
+ deprecated alias core.stdc.complex.csinl csin;
///
alias core.stdc.math.tan tan;
@@ -657,12 +599,10 @@ else version (OpenBSD)
///
alias core.stdc.math.tanl tan;
- ///
- alias core.stdc.complex.ctan tan;
- ///
- alias core.stdc.complex.ctanf tan;
- ///
- alias core.stdc.complex.ctanl tan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctan tan;
+ deprecated alias core.stdc.complex.ctanf tan;
+ deprecated alias core.stdc.complex.ctanl tan;
///
alias core.stdc.math.acosh acosh;
@@ -671,12 +611,10 @@ else version (OpenBSD)
///
alias core.stdc.math.acoshl acosh;
- ///
- alias core.stdc.complex.cacosh acosh;
- ///
- alias core.stdc.complex.cacoshf acosh;
- ///
- alias core.stdc.complex.cacoshl acosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacosh acosh;
+ deprecated alias core.stdc.complex.cacoshf acosh;
+ deprecated alias core.stdc.complex.cacoshl acosh;
///
alias core.stdc.math.asinh asinh;
@@ -685,12 +623,10 @@ else version (OpenBSD)
///
alias core.stdc.math.asinhl asinh;
- ///
- alias core.stdc.complex.casinh asinh;
- ///
- alias core.stdc.complex.casinhf asinh;
- ///
- alias core.stdc.complex.casinhl asinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casinh asinh;
+ deprecated alias core.stdc.complex.casinhf asinh;
+ deprecated alias core.stdc.complex.casinhl asinh;
///
alias core.stdc.math.atanh atanh;
@@ -699,12 +635,10 @@ else version (OpenBSD)
///
alias core.stdc.math.atanhl atanh;
- ///
- alias core.stdc.complex.catanh atanh;
- ///
- alias core.stdc.complex.catanhf atanh;
- ///
- alias core.stdc.complex.catanhl atanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catanh atanh;
+ deprecated alias core.stdc.complex.catanhf atanh;
+ deprecated alias core.stdc.complex.catanhl atanh;
///
alias core.stdc.math.cosh cosh;
@@ -713,12 +647,10 @@ else version (OpenBSD)
///
alias core.stdc.math.coshl cosh;
- ///
- alias core.stdc.complex.ccosh cosh;
- ///
- alias core.stdc.complex.ccoshf cosh;
- ///
- alias core.stdc.complex.ccoshl cosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccosh cosh;
+ deprecated alias core.stdc.complex.ccoshf cosh;
+ deprecated alias core.stdc.complex.ccoshl cosh;
///
alias core.stdc.math.sinh sinh;
@@ -727,12 +659,10 @@ else version (OpenBSD)
///
alias core.stdc.math.sinhl sinh;
- ///
- alias core.stdc.complex.csinh sinh;
- ///
- alias core.stdc.complex.csinhf sinh;
- ///
- alias core.stdc.complex.csinhl sinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csinh sinh;
+ deprecated alias core.stdc.complex.csinhf sinh;
+ deprecated alias core.stdc.complex.csinhl sinh;
///
alias core.stdc.math.tanh tanh;
@@ -741,12 +671,10 @@ else version (OpenBSD)
///
alias core.stdc.math.tanhl tanh;
- ///
- alias core.stdc.complex.ctanh tanh;
- ///
- alias core.stdc.complex.ctanhf tanh;
- ///
- alias core.stdc.complex.ctanhl tanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctanh tanh;
+ deprecated alias core.stdc.complex.ctanhf tanh;
+ deprecated alias core.stdc.complex.ctanhl tanh;
///
alias core.stdc.math.exp exp;
@@ -755,12 +683,10 @@ else version (OpenBSD)
///
alias core.stdc.math.expl exp;
- ///
- alias core.stdc.complex.cexp exp;
- ///
- alias core.stdc.complex.cexpf exp;
- ///
- alias core.stdc.complex.cexpl exp;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cexp exp;
+ deprecated alias core.stdc.complex.cexpf exp;
+ deprecated alias core.stdc.complex.cexpl exp;
///
alias core.stdc.math.exp2 exp2;
@@ -804,12 +730,10 @@ else version (OpenBSD)
///
alias core.stdc.math.logl log;
- ///
- alias core.stdc.complex.clog log;
- ///
- alias core.stdc.complex.clogf log;
- ///
- alias core.stdc.complex.clogl log;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.clog log;
+ deprecated alias core.stdc.complex.clogf log;
+ deprecated alias core.stdc.complex.clogl log;
///
alias core.stdc.math.log10 log10;
@@ -874,12 +798,10 @@ else version (OpenBSD)
///
alias core.stdc.math.fabsl fabs;
- ///
- alias core.stdc.complex.cabs fabs;
- ///
- alias core.stdc.complex.cabsf fabs;
- ///
- alias core.stdc.complex.cabsl fabs;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cabs fabs;
+ deprecated alias core.stdc.complex.cabsf fabs;
+ deprecated alias core.stdc.complex.cabsl fabs;
///
alias core.stdc.math.hypot hypot;
@@ -895,12 +817,10 @@ else version (OpenBSD)
///
alias core.stdc.math.powl pow;
- ///
- alias core.stdc.complex.cpow pow;
- ///
- alias core.stdc.complex.cpowf pow;
- ///
- alias core.stdc.complex.cpowl pow;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cpow pow;
+ deprecated alias core.stdc.complex.cpowf pow;
+ deprecated alias core.stdc.complex.cpowl pow;
///
alias core.stdc.math.sqrt sqrt;
@@ -909,12 +829,10 @@ else version (OpenBSD)
///
alias core.stdc.math.sqrtl sqrt;
- ///
- alias core.stdc.complex.csqrt sqrt;
- ///
- alias core.stdc.complex.csqrtf sqrt;
- ///
- alias core.stdc.complex.csqrtl sqrt;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csqrt sqrt;
+ deprecated alias core.stdc.complex.csqrtf sqrt;
+ deprecated alias core.stdc.complex.csqrtl sqrt;
///
alias core.stdc.math.erf erf;
@@ -1077,37 +995,23 @@ else version (OpenBSD)
///
alias core.stdc.math.fmal fma;
- ///
- alias core.stdc.complex.carg carg;
- ///
- alias core.stdc.complex.cargf carg;
- ///
- alias core.stdc.complex.cargl carg;
-
- ///
- alias core.stdc.complex.cimag cimag;
- ///
- alias core.stdc.complex.cimagf cimag;
- ///
- alias core.stdc.complex.cimagl cimag;
-
- ///
- alias core.stdc.complex.conj conj;
- ///
- alias core.stdc.complex.conjf conj;
- ///
- alias core.stdc.complex.conjl conj;
-
- ///
- alias core.stdc.complex.cproj cproj;
- ///
- alias core.stdc.complex.cprojf cproj;
- ///
- alias core.stdc.complex.cprojl cproj;
-
-// alias core.stdc.complex.creal creal;
-// alias core.stdc.complex.crealf creal;
-// alias core.stdc.complex.creall creal;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.carg carg;
+ deprecated alias core.stdc.complex.cargf carg;
+ deprecated alias core.stdc.complex.cargl carg;
+ deprecated alias core.stdc.complex.cimag cimag;
+ deprecated alias core.stdc.complex.cimagf cimag;
+ deprecated alias core.stdc.complex.cimagl cimag;
+ deprecated alias core.stdc.complex.conj conj;
+ deprecated alias core.stdc.complex.conjf conj;
+ deprecated alias core.stdc.complex.conjl conj;
+ deprecated alias core.stdc.complex.cproj cproj;
+ deprecated alias core.stdc.complex.cprojf cproj;
+ deprecated alias core.stdc.complex.cprojl cproj;
+
+// deprecated alias core.stdc.complex.creal creal;
+// deprecated alias core.stdc.complex.crealf creal;
+// deprecated alias core.stdc.complex.creall creal;
}
else
{
@@ -1118,12 +1022,10 @@ else
///
alias core.stdc.math.acosl acos;
- ///
- alias core.stdc.complex.cacos acos;
- ///
- alias core.stdc.complex.cacosf acos;
- ///
- alias core.stdc.complex.cacosl acos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacos acos;
+ deprecated alias core.stdc.complex.cacosf acos;
+ deprecated alias core.stdc.complex.cacosl acos;
///
alias core.stdc.math.asin asin;
@@ -1132,12 +1034,10 @@ else
///
alias core.stdc.math.asinl asin;
- ///
- alias core.stdc.complex.casin asin;
- ///
- alias core.stdc.complex.casinf asin;
- ///
- alias core.stdc.complex.casinl asin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casin asin;
+ deprecated alias core.stdc.complex.casinf asin;
+ deprecated alias core.stdc.complex.casinl asin;
///
alias core.stdc.math.atan atan;
@@ -1146,12 +1046,10 @@ else
///
alias core.stdc.math.atanl atan;
- ///
- alias core.stdc.complex.catan atan;
- ///
- alias core.stdc.complex.catanf atan;
- ///
- alias core.stdc.complex.catanl atan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catan atan;
+ deprecated alias core.stdc.complex.catanf atan;
+ deprecated alias core.stdc.complex.catanl atan;
///
alias core.stdc.math.atan2 atan2;
@@ -1167,12 +1065,10 @@ else
///
alias core.stdc.math.cosl cos;
- ///
- alias core.stdc.complex.ccos cos;
- ///
- alias core.stdc.complex.ccosf cos;
- ///
- alias core.stdc.complex.ccosl cos;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccos cos;
+ deprecated alias core.stdc.complex.ccosf cos;
+ deprecated alias core.stdc.complex.ccosl cos;
///
alias core.stdc.math.sin sin;
@@ -1181,12 +1077,10 @@ else
///
alias core.stdc.math.sinl sin;
- ///
- alias core.stdc.complex.csin csin;
- ///
- alias core.stdc.complex.csinf csin;
- ///
- alias core.stdc.complex.csinl csin;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csin csin;
+ deprecated alias core.stdc.complex.csinf csin;
+ deprecated alias core.stdc.complex.csinl csin;
///
alias core.stdc.math.tan tan;
@@ -1195,12 +1089,10 @@ else
///
alias core.stdc.math.tanl tan;
- ///
- alias core.stdc.complex.ctan tan;
- ///
- alias core.stdc.complex.ctanf tan;
- ///
- alias core.stdc.complex.ctanl tan;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctan tan;
+ deprecated alias core.stdc.complex.ctanf tan;
+ deprecated alias core.stdc.complex.ctanl tan;
///
alias core.stdc.math.acosh acosh;
@@ -1209,12 +1101,10 @@ else
///
alias core.stdc.math.acoshl acosh;
- ///
- alias core.stdc.complex.cacosh acosh;
- ///
- alias core.stdc.complex.cacoshf acosh;
- ///
- alias core.stdc.complex.cacoshl acosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cacosh acosh;
+ deprecated alias core.stdc.complex.cacoshf acosh;
+ deprecated alias core.stdc.complex.cacoshl acosh;
///
alias core.stdc.math.asinh asinh;
@@ -1223,12 +1113,10 @@ else
///
alias core.stdc.math.asinhl asinh;
- ///
- alias core.stdc.complex.casinh asinh;
- ///
- alias core.stdc.complex.casinhf asinh;
- ///
- alias core.stdc.complex.casinhl asinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.casinh asinh;
+ deprecated alias core.stdc.complex.casinhf asinh;
+ deprecated alias core.stdc.complex.casinhl asinh;
///
alias core.stdc.math.atanh atanh;
@@ -1237,12 +1125,10 @@ else
///
alias core.stdc.math.atanhl atanh;
- ///
- alias core.stdc.complex.catanh atanh;
- ///
- alias core.stdc.complex.catanhf atanh;
- ///
- alias core.stdc.complex.catanhl atanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.catanh atanh;
+ deprecated alias core.stdc.complex.catanhf atanh;
+ deprecated alias core.stdc.complex.catanhl atanh;
///
alias core.stdc.math.cosh cosh;
@@ -1251,12 +1137,10 @@ else
///
alias core.stdc.math.coshl cosh;
- ///
- alias core.stdc.complex.ccosh cosh;
- ///
- alias core.stdc.complex.ccoshf cosh;
- ///
- alias core.stdc.complex.ccoshl cosh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ccosh cosh;
+ deprecated alias core.stdc.complex.ccoshf cosh;
+ deprecated alias core.stdc.complex.ccoshl cosh;
///
alias core.stdc.math.sinh sinh;
@@ -1265,12 +1149,10 @@ else
///
alias core.stdc.math.sinhl sinh;
- ///
- alias core.stdc.complex.csinh sinh;
- ///
- alias core.stdc.complex.csinhf sinh;
- ///
- alias core.stdc.complex.csinhl sinh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csinh sinh;
+ deprecated alias core.stdc.complex.csinhf sinh;
+ deprecated alias core.stdc.complex.csinhl sinh;
///
alias core.stdc.math.tanh tanh;
@@ -1279,12 +1161,10 @@ else
///
alias core.stdc.math.tanhl tanh;
- ///
- alias core.stdc.complex.ctanh tanh;
- ///
- alias core.stdc.complex.ctanhf tanh;
- ///
- alias core.stdc.complex.ctanhl tanh;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.ctanh tanh;
+ deprecated alias core.stdc.complex.ctanhf tanh;
+ deprecated alias core.stdc.complex.ctanhl tanh;
///
alias core.stdc.math.exp exp;
@@ -1293,12 +1173,10 @@ else
///
alias core.stdc.math.expl exp;
- ///
- alias core.stdc.complex.cexp exp;
- ///
- alias core.stdc.complex.cexpf exp;
- ///
- alias core.stdc.complex.cexpl exp;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cexp exp;
+ deprecated alias core.stdc.complex.cexpf exp;
+ deprecated alias core.stdc.complex.cexpl exp;
///
alias core.stdc.math.exp2 exp2;
@@ -1342,12 +1220,10 @@ else
///
alias core.stdc.math.logl log;
- ///
- alias core.stdc.complex.clog log;
- ///
- alias core.stdc.complex.clogf log;
- ///
- alias core.stdc.complex.clogl log;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.clog log;
+ deprecated alias core.stdc.complex.clogf log;
+ deprecated alias core.stdc.complex.clogl log;
///
alias core.stdc.math.log10 log10;
@@ -1418,12 +1294,10 @@ else
alias core.stdc.math.fabsl fabs;
}
- ///
- alias core.stdc.complex.cabs fabs;
- ///
- alias core.stdc.complex.cabsf fabs;
- ///
- alias core.stdc.complex.cabsl fabs;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cabs fabs;
+ deprecated alias core.stdc.complex.cabsf fabs;
+ deprecated alias core.stdc.complex.cabsl fabs;
///
alias core.stdc.math.hypot hypot;
@@ -1439,12 +1313,10 @@ else
///
alias core.stdc.math.powl pow;
- ///
- alias core.stdc.complex.cpow pow;
- ///
- alias core.stdc.complex.cpowf pow;
- ///
- alias core.stdc.complex.cpowl pow;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.cpow pow;
+ deprecated alias core.stdc.complex.cpowf pow;
+ deprecated alias core.stdc.complex.cpowl pow;
///
alias core.stdc.math.sqrt sqrt;
@@ -1453,12 +1325,10 @@ else
///
alias core.stdc.math.sqrtl sqrt;
- ///
- alias core.stdc.complex.csqrt sqrt;
- ///
- alias core.stdc.complex.csqrtf sqrt;
- ///
- alias core.stdc.complex.csqrtl sqrt;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.csqrt sqrt;
+ deprecated alias core.stdc.complex.csqrtf sqrt;
+ deprecated alias core.stdc.complex.csqrtl sqrt;
///
alias core.stdc.math.erf erf;
@@ -1635,35 +1505,20 @@ else
///
alias core.stdc.math.fmal fma;
- ///
- alias core.stdc.complex.carg carg;
- ///
- alias core.stdc.complex.cargf carg;
- ///
- alias core.stdc.complex.cargl carg;
-
- ///
- alias core.stdc.complex.cimag cimag;
- ///
- alias core.stdc.complex.cimagf cimag;
- ///
- alias core.stdc.complex.cimagl cimag;
-
- ///
- alias core.stdc.complex.conj conj;
- ///
- alias core.stdc.complex.conjf conj;
- ///
- alias core.stdc.complex.conjl conj;
-
- ///
- alias core.stdc.complex.cproj cproj;
- ///
- alias core.stdc.complex.cprojf cproj;
- ///
- alias core.stdc.complex.cprojl cproj;
-
-// alias core.stdc.complex.creal creal;
-// alias core.stdc.complex.crealf creal;
-// alias core.stdc.complex.creall creal;
+ // @@@DEPRECATED_2.105@@@
+ deprecated alias core.stdc.complex.carg carg;
+ deprecated alias core.stdc.complex.cargf carg;
+ deprecated alias core.stdc.complex.cargl carg;
+ deprecated alias core.stdc.complex.cimag cimag;
+ deprecated alias core.stdc.complex.cimagf cimag;
+ deprecated alias core.stdc.complex.cimagl cimag;
+ deprecated alias core.stdc.complex.conj conj;
+ deprecated alias core.stdc.complex.conjf conj;
+ deprecated alias core.stdc.complex.conjl conj;
+ deprecated alias core.stdc.complex.cproj cproj;
+ deprecated alias core.stdc.complex.cprojf cproj;
+ deprecated alias core.stdc.complex.cprojl cproj;
+// deprecated alias core.stdc.complex.creal creal;
+// deprecated alias core.stdc.complex.crealf creal;
+// deprecated alias core.stdc.complex.creall creal;
}
diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d
index eecc8ef..6da5618 100644
--- a/libphobos/libdruntime/core/stdc/wchar_.d
+++ b/libphobos/libdruntime/core/stdc/wchar_.d
@@ -173,12 +173,13 @@ extern (D) @trusted
wint_t getwchar() { return fgetwc(stdin); }
///
wint_t putwchar(wchar_t c) { return fputwc(c,stdout); }
- ///
- wint_t getwc(FILE* stream) { return fgetwc(stream); }
- ///
- wint_t putwc(wchar_t c, FILE* stream) { return fputwc(c, stream); }
}
+///
+alias getwc = fgetwc;
+///
+alias putwc = fputwc;
+
// No unsafe pointer manipulation.
@trusted
{
diff --git a/libphobos/libdruntime/core/sys/darwin/fcntl.d b/libphobos/libdruntime/core/sys/darwin/fcntl.d
new file mode 100644
index 0000000..47d895a
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/darwin/fcntl.d
@@ -0,0 +1,20 @@
+module core.sys.darwin.fcntl;
+
+public import core.sys.posix.fcntl;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (Darwin):
+extern (C):
+nothrow:
+@nogc:
+@system:
+
+enum F_FULLFSYNC = 51;
diff --git a/libphobos/libdruntime/core/sys/linux/epoll.d b/libphobos/libdruntime/core/sys/linux/epoll.d
index 0c3aed9..f5ff7db 100644
--- a/libphobos/libdruntime/core/sys/linux/epoll.d
+++ b/libphobos/libdruntime/core/sys/linux/epoll.d
@@ -10,6 +10,8 @@ module core.sys.linux.epoll;
version (linux):
+import core.sys.posix.signal : sigset_t;
+
extern (C):
@system:
@nogc:
@@ -52,16 +54,19 @@ enum
EPOLLHUP = 0x010,
EPOLLRDHUP = 0x2000, // since Linux 2.6.17
EPOLLEXCLUSIVE = 1u << 28, // since Linux 4.5
+ EPOLLWAKEUP = 1u << 29,
EPOLLONESHOT = 1u << 30,
EPOLLET = 1u << 31
}
-/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */
+/**
+ * Valid opcodes ( "op" parameter ) to issue to epoll_ctl().
+ */
enum
{
- EPOLL_CTL_ADD = 1, // Add a file descriptor to the interface.
- EPOLL_CTL_DEL = 2, // Remove a file descriptor from the interface.
- EPOLL_CTL_MOD = 3, // Change file descriptor epoll_event structure.
+ EPOLL_CTL_ADD = 1, /// Add a file descriptor to the interface.
+ EPOLL_CTL_DEL = 2, /// Remove a file descriptor from the interface.
+ EPOLL_CTL_MOD = 3, /// Change file descriptor epoll_event structure.
}
version (X86_Any)
@@ -142,7 +147,82 @@ union epoll_data_t
ulong u64;
}
+/**
+ * Creates an epoll instance.
+ *
+ * Params:
+ * size = a hint specifying the number of file descriptors to be associated
+ * with the new instance. T
+ * Returns: an fd for the new instance. The fd returned by epoll_create() should
+ * be closed with close().
+ * See_also: epoll_create1 (int flags)
+ */
int epoll_create (int size);
+
+/* Same as epoll_create but with an FLAGS parameter. The unused SIZE
+ parameter has been dropped. */
+
+/**
+ * Creates an epoll instance.
+ *
+ * Params:
+ * flags = a specified flag. If flags is 0, then, other than the fact that the
+ * obsolete size argument is dropped, epoll_create1() is the same as
+ * epoll_create().
+ * Returns: an fd for the new instance. The fd returned by epoll_create() should
+ * be closed with close().
+ * See_also: epoll_create (int size)
+ */
int epoll_create1 (int flags);
+
+/**
+ * Manipulate an epoll instance
+ *
+ * Params:
+ * epfd = an epoll file descriptor instance
+ * op = one of the EPOLL_CTL_* constants
+ * fd = target file descriptor of the operation
+ * event = describes which events the caller is interested in and any
+ * associated user dat
+ * Returns: 0 in case of success, -1 in case of error ( the "errno" variable
+ * will contain the specific error code )
+ */
int epoll_ctl (int epfd, int op, int fd, epoll_event *event);
+
+
+/**
+ * Wait for events on an epoll instance.
+ *
+ *
+ * Params:
+ * epfd = an epoll file descriptor instance
+ * events = a buffer that will contain triggered events
+ * maxevents = the maximum number of events to be returned ( usually size of
+ * "events" )
+ * timeout = specifies the maximum wait time in milliseconds (-1 == infinite)
+ *
+ * Returns: the number of triggered events returned in "events" buffer. Or -1 in
+ * case of error with the "errno" variable set to the specific error
+ * code.
+ */
int epoll_wait (int epfd, epoll_event *events, int maxevents, int timeout);
+
+/**
+ * Wait for events on an epoll instance
+ *
+ *
+ * Params:
+ * epfd = an epoll file descriptor instance
+ * events = a buffer that will contain triggered events
+ * maxevents = the maximum number of events to be returned ( usually size of
+ * "events" )
+ * timeout = specifies the maximum wait time in milliseconds (-1 == infinite)
+ * ss = a signal set. May be specified as `null`, in which case epoll_pwait() is
+ * equivalent to epoll_wait().
+ *
+ * Returns: the number of triggered events returned in "events" buffer. Or -1 in
+ * case of error with the "errno" variable set to the specific error
+ * code.
+ */
+int epoll_pwait (int epfd, epoll_event *events, int maxevents, int timeout,
+ const sigset_t *ss);
diff --git a/libphobos/libdruntime/core/sys/openbsd/string.d b/libphobos/libdruntime/core/sys/openbsd/string.d
index 8d35b9c..cb978c8 100644
--- a/libphobos/libdruntime/core/sys/openbsd/string.d
+++ b/libphobos/libdruntime/core/sys/openbsd/string.d
@@ -18,4 +18,6 @@ nothrow:
static if (__BSD_VISIBLE)
{
pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+ pure int timingsafe_bcmp(scope const void*, scope const void*, size_t);
+ pure int timingsafe_memcmp(scope const void*, scope const void*, size_t);
}
diff --git a/libphobos/libdruntime/core/sys/openbsd/unistd.d b/libphobos/libdruntime/core/sys/openbsd/unistd.d
new file mode 100644
index 0000000..ddd102c
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/openbsd/unistd.d
@@ -0,0 +1,17 @@
+/**
+ * D header file for OpenBSD unistd.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.unistd;
+public import core.sys.posix.unistd;
+
+version (OpenBSD):
+extern (C):
+nothrow:
+@nogc:
+
+int pledge(const scope char*, const scope char*);
+int unveil(const scope char*, const scope char*);
diff --git a/libphobos/libdruntime/core/sys/posix/config.d b/libphobos/libdruntime/core/sys/posix/config.d
index c02debff..3b575fa 100644
--- a/libphobos/libdruntime/core/sys/posix/config.d
+++ b/libphobos/libdruntime/core/sys/posix/config.d
@@ -117,6 +117,7 @@ else version (CRuntime_UClibc)
else version (CRuntime_Bionic)
{
enum _GNU_SOURCE = false;
+ enum __USE_FILE_OFFSET64 = false; // see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
enum __USE_GNU = _GNU_SOURCE;
version (D_LP64)
diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d
index e97c7ea..2477e26 100644
--- a/libphobos/libdruntime/core/sys/posix/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d
@@ -139,7 +139,7 @@ else version (Darwin)
char* dlerror();
void* dlopen(const scope char*, int);
void* dlsym(void*, const scope char*);
- int dladdr(void* addr, Dl_info* info);
+ int dladdr(scope const void* addr, Dl_info* info);
struct Dl_info
{
@@ -294,6 +294,15 @@ else version (CRuntime_Musl)
const(char)* dlerror();
void* dlopen(const scope char*, int);
void* dlsym(void*, const scope char*);
+
+ int dladdr(scope const void *addr, Dl_info *info);
+ struct Dl_info
+ {
+ const(char)* dli_fname;
+ void* dli_fbase;
+ const(char)* dli_sname;
+ void* dli_saddr;
+ }
}
else version (CRuntime_UClibc)
{
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index 44f45f2..0dce8c5 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -3503,7 +3503,7 @@ struct sigevent
pthread_attr_t* sigev_notify_attributes;
}
-int sigqueue(pid_t, int, in sigval);
+int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
*/
@@ -3543,7 +3543,7 @@ version (CRuntime_Glibc)
} _sigev_un_t _sigev_un;
}
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
@@ -3566,7 +3566,7 @@ else version (FreeBSD)
}
}
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
@@ -3581,7 +3581,7 @@ else version (NetBSD)
void /* pthread_attr_t */*sigev_notify_attributes;
}
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
@@ -3613,7 +3613,7 @@ else version (DragonFlyBSD)
void function(_sigval_t) sigev_notify_function;
}
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
@@ -3640,7 +3640,7 @@ else version (Solaris)
int __sigev_pad2;
}
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
@@ -3717,7 +3717,7 @@ else version (CRuntime_UClibc)
@property void function(sigval) sigev_notify_function(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._function; }
@property void* sigev_notify_attributes(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._attribute; }
- int sigqueue(pid_t, int, in sigval);
+ int sigqueue(pid_t, int, const sigval);
int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
diff --git a/libphobos/libdruntime/core/sys/posix/unistd.d b/libphobos/libdruntime/core/sys/posix/unistd.d
index a691884..d996556 100644
--- a/libphobos/libdruntime/core/sys/posix/unistd.d
+++ b/libphobos/libdruntime/core/sys/posix/unistd.d
@@ -2722,3 +2722,51 @@ else version (CRuntime_UClibc)
int truncate(const scope char*, off_t);
}
}
+
+// Non-standard definition to access user process environment
+version (CRuntime_Glibc)
+{
+ extern __gshared const char** environ;
+}
+else version (Darwin)
+{
+ extern (D) @property const(char**) environ()()
+ {
+ pragma (inline, true);
+ import core.sys.darwin.crt_externs : _NSGetEnviron;
+ return *_NSGetEnviron();
+ }
+}
+else version (FreeBSD)
+{
+ extern __gshared const char** environ;
+}
+else version (NetBSD)
+{
+ extern __gshared const char** environ;
+}
+else version (OpenBSD)
+{
+ extern __gshared const char** environ;
+}
+else version (DragonFlyBSD)
+{
+ extern __gshared const char** environ;
+}
+else version (CRuntime_Bionic)
+{
+ extern __gshared const char** environ;
+}
+else version (CRuntime_Musl)
+{
+ extern __gshared const char** environ;
+}
+else version (Solaris)
+{
+ extern __gshared const char** environ;
+}
+else version (CRuntime_UClibc)
+{
+ extern __gshared const char** __environ;
+ alias environ = __environ;
+}
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 90a2943..88007ad 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -39,16 +39,16 @@ public import core.sys.windows.winerror :
RPC_E_CHANGED_MODE;
public import core.sys.windows.wtypes :
- OLECHAR, LPOLESTR, LPCOLESTR;
-
-alias CLSCTX_INPROC_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER ;
-alias CLSCTX_INPROC_HANDLER = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER ;
-alias CLSCTX_LOCAL_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_LOCAL_SERVER ;
-alias CLSCTX_INPROC_SERVER16 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER16 ;
-alias CLSCTX_REMOTE_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_REMOTE_SERVER ;
-alias CLSCTX_INPROC_HANDLER16 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER16 ;
-alias CLSCTX_INPROC_SERVERX86 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVERX86 ;
-alias CLSCTX_INPROC_HANDLERX86 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLERX86;
+ CLSCTX, OLECHAR, LPOLESTR, LPCOLESTR;
+
+alias CLSCTX_INPROC_SERVER = CLSCTX.CLSCTX_INPROC_SERVER ;
+alias CLSCTX_INPROC_HANDLER = CLSCTX.CLSCTX_INPROC_HANDLER ;
+alias CLSCTX_LOCAL_SERVER = CLSCTX.CLSCTX_LOCAL_SERVER ;
+alias CLSCTX_INPROC_SERVER16 = CLSCTX.CLSCTX_INPROC_SERVER16 ;
+alias CLSCTX_REMOTE_SERVER = CLSCTX.CLSCTX_REMOTE_SERVER ;
+alias CLSCTX_INPROC_HANDLER16 = CLSCTX.CLSCTX_INPROC_HANDLER16 ;
+alias CLSCTX_INPROC_SERVERX86 = CLSCTX.CLSCTX_INPROC_SERVERX86 ;
+alias CLSCTX_INPROC_HANDLERX86 = CLSCTX.CLSCTX_INPROC_HANDLERX86;
alias COINIT_APARTMENTTHREADED = COINIT.COINIT_APARTMENTTHREADED;
alias COINIT_MULTITHREADED = COINIT.COINIT_MULTITHREADED ;
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 9f36ac3..3df0d7f 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -31,17 +31,7 @@ public import core.sys.windows.threadaux;
// not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend
extern (C)
{
- version (MinGW)
- {
- extern __gshared void* _tls_start;
- extern __gshared void* _tls_end;
- extern __gshared void* __xl_a;
-
- alias _tls_start _tlsstart;
- alias _tls_end _tlsend;
- alias __xl_a _tls_callbacks_a;
- }
- else version (Win32)
+ version (Win32)
{
version (CRuntime_DigitalMars)
{
diff --git a/libphobos/libdruntime/core/sys/windows/stdc/malloc.d b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d
new file mode 100644
index 0000000..f52ba37
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d
@@ -0,0 +1,26 @@
+/**
+ * D header file for Windows malloc.h.
+ *
+ * Translated from MinGW Windows headers
+ *
+ * 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)
+ */
+module core.sys.windows.stdc.malloc;
+version (CRuntime_Microsoft):
+extern (C):
+@system:
+nothrow:
+@nogc:
+
+export void* _recalloc(void*, size_t, size_t);
+
+export void _aligned_free(void*);
+export void* _aligned_malloc(size_t, size_t);
+
+export void* _aligned_offset_malloc(size_t, size_t, size_t);
+export void* _aligned_realloc(void*, size_t, size_t);
+export void* _aligned_recalloc(void*, size_t, size_t, size_t);
+export void* _aligned_offset_realloc(void*, size_t, size_t, size_t);
+export void* _aligned_offset_recalloc(void*, size_t, size_t, size_t, size_t);
diff --git a/libphobos/libdruntime/gc/impl/conservative/gc.d b/libphobos/libdruntime/gc/impl/conservative/gc.d
index b7bb9b0..300a32a 100644
--- a/libphobos/libdruntime/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/gc/impl/conservative/gc.d
@@ -76,7 +76,7 @@ debug(PRINTF_TO_FILE)
gcStartTick = MonoTime.currTime;
immutable timeElapsed = MonoTime.currTime - gcStartTick;
immutable secondsAsDouble = timeElapsed.total!"hnsecs" / cast(double)convert!("seconds", "hnsecs")(1);
- len = fprintf(gcx_fh, "%10.6lf: ", secondsAsDouble);
+ len = fprintf(gcx_fh, "%10.6f: ", secondsAsDouble);
}
len += fprintf(gcx_fh, fmt, args);
fflush(gcx_fh);
@@ -159,7 +159,7 @@ debug (LOGGING)
printf(" p = %p, size = %zd, parent = %p ", p, size, parent);
if (file)
{
- printf("%s(%u)", file, line);
+ printf("%s(%u)", file, cast(uint)line);
}
printf("\n");
}
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 04d5457..c05643b 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -19,10 +19,11 @@ private
alias size_t = typeof(int.sizeof);
alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
-alias sizediff_t = ptrdiff_t; //For backwards compatibility only.
+alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
+alias noreturn = typeof(*null); /// bottom type
-alias hash_t = size_t; //For backwards compatibility only.
-alias equals_t = bool; //For backwards compatibility only.
+alias hash_t = size_t; // For backwards compatibility only.
+alias equals_t = bool; // For backwards compatibility only.
alias string = immutable(char)[];
alias wstring = immutable(wchar)[];
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 6de04b4..4f6a168 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-9d575282edeccecbc061e615bf2486fd07e8c084
+f89dc217a680fa1a83f2999fea04b7c562f705ee
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 0dc2a26..2dedc74 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -135,11 +135,11 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/sqlite3.d etc/c/zlib.d \
std/regex/internal/backtracking.d std/regex/internal/generator.d \
std/regex/internal/ir.d std/regex/internal/kickstart.d \
std/regex/internal/parser.d std/regex/internal/tests.d \
- std/regex/internal/thompson.d std/regex/package.d std/signals.d \
- std/socket.d std/stdint.d std/stdio.d std/string.d std/system.d \
- std/traits.d std/typecons.d std/typetuple.d std/uni.d std/uri.d \
- std/utf.d std/uuid.d std/variant.d std/windows/charset.d \
- std/windows/registry.d std/windows/syserror.d std/xml.d std/zip.d \
- std/zlib.d
+ std/regex/internal/tests2.d std/regex/internal/thompson.d \
+ std/regex/package.d std/signals.d std/socket.d std/stdint.d \
+ std/stdio.d std/string.d std/system.d std/traits.d std/typecons.d \
+ std/typetuple.d std/uni.d std/uri.d std/utf.d std/uuid.d std/variant.d \
+ std/windows/charset.d std/windows/registry.d std/windows/syserror.d \
+ std/xml.d std/zip.d std/zlib.d
endif
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 3345351..9e410e5 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -249,6 +249,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/kickstart.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/parser.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests.lo \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests2.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/thompson.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/package.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/signals.lo std/socket.lo \
@@ -572,12 +573,12 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/backtracking.d std/regex/internal/generator.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/ir.d std/regex/internal/kickstart.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/parser.d std/regex/internal/tests.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/thompson.d std/regex/package.d std/signals.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/socket.d std/stdint.d std/stdio.d std/string.d std/system.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/traits.d std/typecons.d std/typetuple.d std/uni.d std/uri.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/utf.d std/uuid.d std/variant.d std/windows/charset.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/registry.d std/windows/syserror.d std/xml.d std/zip.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/zlib.d
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests2.d std/regex/internal/thompson.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/package.d std/signals.d std/socket.d std/stdint.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/stdio.d std/string.d std/system.d std/traits.d std/typecons.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/typetuple.d std/uni.d std/uri.d std/utf.d std/uuid.d std/variant.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/charset.d std/windows/registry.d std/windows/syserror.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/xml.d std/zip.d std/zlib.d
# Source file definitions. Boring stuff, auto-generated with
@@ -851,6 +852,7 @@ std/regex/internal/ir.lo: std/regex/internal/$(am__dirstamp)
std/regex/internal/kickstart.lo: std/regex/internal/$(am__dirstamp)
std/regex/internal/parser.lo: std/regex/internal/$(am__dirstamp)
std/regex/internal/tests.lo: std/regex/internal/$(am__dirstamp)
+std/regex/internal/tests2.lo: std/regex/internal/$(am__dirstamp)
std/regex/internal/thompson.lo: std/regex/internal/$(am__dirstamp)
std/regex/$(am__dirstamp):
@$(MKDIR_P) std/regex
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index c77792d..19cfb77 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -769,9 +769,9 @@ private struct MapResult(alias fun, Range)
string s1 = "hello world!";
dstring s2 = "日本語";
dstring s3 = "hello world!"d;
- auto ms1 = map!(std.ascii.toUpper)(s1);
- auto ms2 = map!(std.ascii.toUpper)(s2);
- auto ms3 = map!(std.ascii.toUpper)(s3);
+ auto ms1 = map!(toUpper)(s1);
+ auto ms2 = map!(toUpper)(s2);
+ auto ms3 = map!(toUpper)(s3);
static assert(!is(ms1[0])); //narrow strings can't be indexed
assert(ms2[0] == '日');
assert(ms3[0] == 'H');
@@ -4450,7 +4450,7 @@ private struct SplitterResult(alias isTerminator, Range)
["là", "dove", "terminava", "quella", "valle"]
));
assert(equal(
- splitter!(std.uni.isWhite)("là dove terminava quella valle"),
+ splitter!(isWhite)("là dove terminava quella valle"),
["là", "dove", "terminava", "quella", "valle"]
));
assert(equal(splitter!"a=='本'"("日本語"), ["日", "語"]));
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 6468a87..09073f6 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -959,8 +959,8 @@ if (isInputRange!R &&
import std.ascii : isDigit;
import std.uni : isWhite;
- assert(countUntil!(std.uni.isWhite)("hello world") == 5);
- assert(countUntil!(std.ascii.isDigit)("hello world") == -1);
+ assert(countUntil!(isWhite)("hello world") == 5);
+ assert(countUntil!(isDigit)("hello world") == -1);
assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3);
}
diff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d
index 861da5e..5e31ac2 100644
--- a/libphobos/src/std/container/rbtree.d
+++ b/libphobos/src/std/container/rbtree.d
@@ -1814,8 +1814,8 @@ assert(equal(rbt[], [5]));
test!byte();
}
-import std.range.primitives : isInputRange, isSomeString, ElementType;
-import std.traits : isArray;
+import std.range.primitives : isInputRange, ElementType;
+import std.traits : isArray, isSomeString;
/++
Convenience function for creating a $(D RedBlackTree!E) from a list of
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 31cc651..3560d13 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -3967,7 +3967,7 @@ if (isOctalLiteral(num))
/// Ditto
template octal(alias decimalInteger)
-if (isIntegral!(typeof(decimalInteger)))
+if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger)))
{
enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger));
}
diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d
index b229191..913d360 100644
--- a/libphobos/src/std/datetime/systime.d
+++ b/libphobos/src/std/datetime/systime.d
@@ -9569,7 +9569,7 @@ afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
}
// year
- auto found = value[2 .. value.length].find!(not!(std.ascii.isDigit))();
+ auto found = value[2 .. value.length].find!(not!(isDigit))();
size_t yearLen = value.length - found.length;
if (found.length == 0)
throw new DateTimeException("Invalid year");
@@ -9659,7 +9659,7 @@ afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
case "J": case "j": throw new DateTimeException("Invalid timezone");
default:
{
- if (all!(std.ascii.isAlpha)(value[0 .. tzLen]))
+ if (all!(isAlpha)(value[0 .. tzLen]))
{
tz = new immutable SimpleTimeZone(Duration.zero);
break;
diff --git a/libphobos/src/std/experimental/logger/nulllogger.d b/libphobos/src/std/experimental/logger/nulllogger.d
index fa511be..0c55377 100644
--- a/libphobos/src/std/experimental/logger/nulllogger.d
+++ b/libphobos/src/std/experimental/logger/nulllogger.d
@@ -31,7 +31,7 @@ class NullLogger : Logger
///
@safe unittest
{
- import std.experimental.logger.nulllogger : LogLevel;
+ import std.experimental.logger.core : LogLevel;
auto nl1 = new NullLogger(LogLevel.all);
nl1.info("You will never read this.");
diff --git a/libphobos/src/std/experimental/typecons.d b/libphobos/src/std/experimental/typecons.d
index 6906f05..07eed8f 100644
--- a/libphobos/src/std/experimental/typecons.d
+++ b/libphobos/src/std/experimental/typecons.d
@@ -23,8 +23,7 @@ module std.experimental.typecons;
import std.meta; // : AliasSeq, allSatisfy;
import std.traits;
-import std.typecons : Tuple, tuple, Bind, DerivedFunctionType,
- isImplicitlyConvertible, mixinAll, staticIota,
+import std.typecons : Tuple, tuple, Bind, DerivedFunctionType, mixinAll, staticIota,
GetOverloadedMethods;
private
@@ -113,7 +112,8 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets))
else
{
enum foundFunc = findCovariantFunction!(TargetMembers[i], Source, SourceMembers);
- debug
+ version (unittest) {}
+ else debug
{
static if (foundFunc == -1)
pragma(msg, "Could not locate matching function for: ",
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index 13a3db0..99530cb 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -2301,7 +2301,7 @@ if (isConvertibleToString!R)
@safe unittest
{
- import std.path : mkdir;
+ import std.file : mkdir;
static assert(__traits(compiles, mkdir(TestAliasedString(null))));
}
@@ -4112,7 +4112,8 @@ auto dirEntries(string path, SpanMode mode, bool followSymlink = true)
import std.algorithm.searching : startsWith;
import std.array : array;
import std.conv : to;
- import std.path : dirEntries, buildPath, absolutePath;
+ import std.path : buildPath, absolutePath;
+ import std.file : dirEntries;
import std.process : thisProcessID;
import std.range.primitives : walkLength;
diff --git a/libphobos/src/std/format.d b/libphobos/src/std/format.d
index 64b1bd3..17e5906 100644
--- a/libphobos/src/std/format.d
+++ b/libphobos/src/std/format.d
@@ -5199,7 +5199,7 @@ body
}
debug (unformatRange) printf("\t");
debug (unformatRange) if (!input.empty) printf("input.front = %c, ", input.front);
- debug (unformatRange) printf("cont = %.*s\n", cont);
+ debug (unformatRange) printf("cont = %.*s\n", cast(int) cont.length, cont.ptr);
bool checkEnd()
{
@@ -5246,7 +5246,7 @@ body
auto sep = spec.sep !is null ? spec.sep
: fmt.trailing;
debug (unformatRange) {
- if (!sep.empty && !input.empty) printf("-> %c, sep = %.*s\n", input.front, sep);
+ if (!sep.empty && !input.empty) printf("-> %c, sep = %.*s\n", input.front, cast(int) sep.length, sep.ptr);
else printf("\n");
}
diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d
index f5cd769..6fc2d16 100644
--- a/libphobos/src/std/internal/math/biguintcore.d
+++ b/libphobos/src/std/internal/math/biguintcore.d
@@ -2503,13 +2503,13 @@ pure nothrow
void printBiguint(const uint [] data)
{
char [] buff = biguintToHex(new char[data.length*9], data, '_');
- printf("%.*s\n", buff.length, buff.ptr);
+ printf("%.*s\n", cast(int) buff.length, buff.ptr);
}
void printDecimalBigUint(BigUint data)
{
auto str = data.toDecimalString(0);
- printf("%.*s\n", str.length, str.ptr);
+ printf("%.*s\n", cast(int) str.length, str.ptr);
}
uint [] a, b;
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index ff368b7..336c11a 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -263,8 +263,8 @@ version (unittest)
alias real_t = double;
else
alias real_t = real;
- ix = sprintf(bufx.ptr, "%.*Lg", ndigits, cast(real_t) x);
- iy = sprintf(bufy.ptr, "%.*Lg", ndigits, cast(real_t) y);
+ ix = sprintf(bufx.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) x);
+ iy = sprintf(bufy.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) y);
assert(ix < bufx.length && ix > 0);
assert(ix < bufy.length && ix > 0);
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index 43a1ba5..61d5cea 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -4000,7 +4000,7 @@ version (unittest)
import std.array : split;
import std.conv : text;
import std.exception : assertThrown;
- import std.math : approxEqual, sqrt, log;
+ import std.math : approxEqual, sqrt, log, abs;
import std.range : indexed, iota, join;
import std.typecons : Tuple, tuple;
@@ -4329,7 +4329,7 @@ version (unittest)
assert(equal(iota(1_000_000), bufTrickTest));
- auto myTask = task!(std.math.abs)(-1);
+ auto myTask = task!(abs)(-1);
taskPool.put(myTask);
assert(myTask.spinForce == 1);
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index 13601cb..deedb68 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -11379,7 +11379,6 @@ if (isInputRange!R && isIntegral!(ElementType!R))
bw.popFront();
assert(bw[2 * bitsNum - 3] == true);
- import core.exception : Error;
import std.exception : assertThrown;
// Check out of bounds error
diff --git a/libphobos/src/std/regex/internal/tests.d b/libphobos/src/std/regex/internal/tests.d
index 1c4f295..fe75ce0 100644
--- a/libphobos/src/std/regex/internal/tests.d
+++ b/libphobos/src/std/regex/internal/tests.d
@@ -8,7 +8,7 @@ package(std.regex):
import std.conv, std.exception, std.meta, std.range,
std.typecons, std.regex;
-import std.regex.internal.parser : Escapables; // characters that need escaping
+import std.regex.internal.ir : Escapables; // characters that need escaping
alias Sequence(int B, int E) = staticIota!(B, E);
@@ -467,654 +467,3 @@ alias Sequence(int B, int E) = staticIota!(B, E);
run_tests!match(); //thompson VM
}
-@safe unittest
-{
- auto cr = ctRegex!("abc");
- assert(bmatch("abc",cr).hit == "abc");
- auto cr2 = ctRegex!("ab*c");
- assert(bmatch("abbbbc",cr2).hit == "abbbbc");
-}
-@safe unittest
-{
- auto cr3 = ctRegex!("^abc$");
- assert(bmatch("abc",cr3).hit == "abc");
- auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`);
- assert(array(match("azb",cr4).captures) == ["azb", "azb"]);
-}
-
-@safe unittest
-{
- auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}");
- assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb");
- auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w);
- assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w);
-}
-
-@safe unittest
-{
- auto cr7 = ctRegex!(`\r.*?$`,"sm");
- assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy");
- auto greed = ctRegex!("<packet.*?/packet>");
- assert(bmatch("<packet>text</packet><packet>text</packet>", greed).hit
- == "<packet>text</packet>");
-}
-
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto cr8 = ctRegex!("^(a)(b)?(c*)");
- auto m8 = bmatch("abcc",cr8);
- assert(m8);
- assert(m8.captures[1] == "a");
- assert(m8.captures[2] == "b");
- assert(m8.captures[3] == "cc");
- auto cr9 = ctRegex!("q(a|b)*q");
- auto m9 = match("xxqababqyy",cr9);
- assert(m9);
- assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"]));
-}
-
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto rtr = regex("a|b|c");
- enum ctr = regex("a|b|c");
- assert(equal(rtr.ir,ctr.ir));
- //CTFE parser BUG is triggered by group
- //in the middle of alternation (at least not first and not last)
- enum testCT = regex(`abc|(edf)|xyz`);
- auto testRT = regex(`abc|(edf)|xyz`);
- assert(equal(testCT.ir,testRT.ir));
-}
-
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- import std.algorithm.iteration : map;
- enum cx = ctRegex!"(A|B|C)";
- auto mx = match("B",cx);
- assert(mx);
- assert(equal(mx.captures, [ "B", "B"]));
- enum cx2 = ctRegex!"(A|B)*";
- assert(match("BAAA",cx2));
-
- enum cx3 = ctRegex!("a{3,4}","i");
- auto mx3 = match("AaA",cx3);
- assert(mx3);
- assert(mx3.captures[0] == "AaA");
- enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i");
- auto mx4 = match("aaaabc", cx4);
- assert(mx4);
- assert(mx4.captures[0] == "aaaab");
- auto cr8 = ctRegex!("(a)(b)?(c*)");
- auto m8 = bmatch("abcc",cr8);
- assert(m8);
- assert(m8.captures[1] == "a");
- assert(m8.captures[2] == "b");
- assert(m8.captures[3] == "cc");
- auto cr9 = ctRegex!(".*$", "gm");
- auto m9 = match("First\rSecond", cr9);
- assert(m9);
- assert(equal(map!"a.hit"(m9), ["First", "", "Second"]));
-}
-
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- import std.algorithm.iteration : map;
-//global matching
- void test_body(alias matchFn)()
- {
- string s = "a quick brown fox jumps over a lazy dog";
- auto r1 = regex("\\b[a-z]+\\b","g");
- string[] test;
- foreach (m; matchFn(s, r1))
- test ~= m.hit;
- assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"]));
- auto free_reg = regex(`
-
- abc
- \s+
- "
- (
- [^"]+
- | \\ "
- )+
- "
- z
- `, "x");
- auto m = match(`abc "quoted string with \" inside"z`,free_reg);
- assert(m);
- string mails = " hey@you.com no@spam.net ";
- auto rm = regex(`@(?<=\S+@)\S+`,"g");
- assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"]));
- auto m2 = matchFn("First line\nSecond line",regex(".*$","gm"));
- assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"]));
- auto m2a = matchFn("First line\nSecond line",regex(".+$","gm"));
- assert(equal(map!"a[0]"(m2a), ["First line", "Second line"]));
- auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm"));
- assert(equal(map!"a[0]"(m2b), ["First line", "Second line"]));
- debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!");
- }
- test_body!bmatch();
- test_body!match();
-}
-
-//tests for accumulated std.regex issues and other regressions
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- import std.algorithm.iteration : map;
- void test_body(alias matchFn)()
- {
- //issue 5857
- //matching goes out of control if ... in (...){x} has .*/.+
- auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures;
- assert(c[0] == "axxxzayyyyyzd");
- assert(c[1] == "ayyyyyz");
- auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures;
- assert(c2[0] == "axxxayyyyyd");
- assert(c2[1] == "ayyyyy");
- //issue 2108
- //greedy vs non-greedy
- auto nogreed = regex("<packet.*?/packet>");
- assert(matchFn("<packet>text</packet><packet>text</packet>", nogreed).hit
- == "<packet>text</packet>");
- auto greed = regex("<packet.*/packet>");
- assert(matchFn("<packet>text</packet><packet>text</packet>", greed).hit
- == "<packet>text</packet><packet>text</packet>");
- //issue 4574
- //empty successful match still advances the input
- string[] pres, posts, hits;
- foreach (m; matchFn("abcabc", regex("","g")))
- {
- pres ~= m.pre;
- posts ~= m.post;
- assert(m.hit.empty);
-
- }
- auto heads = [
- "abcabc",
- "abcab",
- "abca",
- "abc",
- "ab",
- "a",
- ""
- ];
- auto tails = [
- "abcabc",
- "bcabc",
- "cabc",
- "abc",
- "bc",
- "c",
- ""
- ];
- assert(pres == array(retro(heads)));
- assert(posts == tails);
- //issue 6076
- //regression on .*
- auto re = regex("c.*|d");
- auto m = matchFn("mm", re);
- assert(!m);
- debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!");
- auto rprealloc = regex(`((.){5}.{1,10}){5}`);
- auto arr = array(repeat('0',100));
- auto m2 = matchFn(arr, rprealloc);
- assert(m2);
- assert(collectException(
- regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$")
- ) is null);
- foreach (ch; [Escapables])
- {
- assert(match(to!string(ch),regex(`[\`~ch~`]`)));
- assert(!match(to!string(ch),regex(`[^\`~ch~`]`)));
- assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`)));
- }
- //bugzilla 7718
- string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'";
- auto reStrCmd = regex (`(".*")|('.*')`, "g");
- assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)),
- [`"/GIT/Ruby Apps/sec"`, `'notimer'`]));
- }
- test_body!bmatch();
- test_body!match();
-}
-
-// tests for replace
-@safe unittest
-{
- void test(alias matchFn)()
- {
- import std.uni : toUpper;
-
- foreach (i, v; AliasSeq!(string, wstring, dstring))
- {
- auto baz(Cap)(Cap m)
- if (is(Cap == Captures!(Cap.String)))
- {
- return toUpper(m.hit);
- }
- alias String = v;
- assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c"))
- == to!String("ack rapacity"));
- assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c"))
- == to!String("ack capacity"));
- assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]"))
- == to!String("[n]oon"));
- assert(std.regex.replace!(matchFn)(
- to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'")
- ) == to!String(": test2 test1 :"));
- auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."),
- regex(to!String("[ar]"), "g"));
- assert(s == "StRAp A Rocket engine on A chicken.");
- }
- debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!");
- }
- test!(bmatch)();
- test!(match)();
-}
-
-// tests for splitter
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto s1 = ", abc, de, fg, hi, ";
- auto sp1 = splitter(s1, regex(", *"));
- auto w1 = ["", "abc", "de", "fg", "hi", ""];
- assert(equal(sp1, w1));
-
- auto s2 = ", abc, de, fg, hi";
- auto sp2 = splitter(s2, regex(", *"));
- auto w2 = ["", "abc", "de", "fg", "hi"];
-
- uint cnt;
- foreach (e; sp2)
- {
- assert(w2[cnt++] == e);
- }
- assert(equal(sp2, w2));
-}
-
-@safe unittest
-{
- char[] s1 = ", abc, de, fg, hi, ".dup;
- auto sp2 = splitter(s1, regex(", *"));
-}
-
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto s1 = ", abc, de, fg, hi, ";
- auto w1 = ["", "abc", "de", "fg", "hi", ""];
- assert(equal(split(s1, regex(", *")), w1[]));
-}
-
-@safe unittest
-{ // bugzilla 7141
- string pattern = `[a\--b]`;
- assert(match("-", pattern));
- assert(match("b", pattern));
- string pattern2 = `[&-z]`;
- assert(match("b", pattern2));
-}
-@safe unittest
-{//bugzilla 7111
- assert(match("", regex("^")));
-}
-@safe unittest
-{//bugzilla 7300
- assert(!match("a"d, "aa"d));
-}
-
-// bugzilla 7551
-@safe unittest
-{
- auto r = regex("[]abc]*");
- assert("]ab".matchFirst(r).hit == "]ab");
- assertThrown(regex("[]"));
- auto r2 = regex("[]abc--ab]*");
- assert("]ac".matchFirst(r2).hit == "]");
-}
-
-@safe unittest
-{//bugzilla 7674
- assert("1234".replace(regex("^"), "$$") == "$1234");
- assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?");
- assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?");
-}
-@safe unittest
-{// bugzilla 7679
- import std.algorithm.comparison : equal;
- foreach (S; AliasSeq!(string, wstring, dstring))
- (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
- enum re = ctRegex!(to!S(r"\."));
- auto str = to!S("a.b");
- assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")]));
- assert(split(str, re) == [to!S("a"), to!S("b")]);
- }();
-}
-@safe unittest
-{//bugzilla 8203
- string data = "
- NAME = XPAW01_STA:STATION
- NAME = XPAW01_STA
- ";
- auto uniFileOld = data;
- auto r = regex(
- r"^NAME = (?P<comp>[a-zA-Z0-9_]+):*(?P<blk>[a-zA-Z0-9_]*)","gm");
- auto uniCapturesNew = match(uniFileOld, r);
- for (int i = 0; i < 20; i++)
- foreach (matchNew; uniCapturesNew) {}
- //a second issue with same symptoms
- auto r2 = regex(`([а-яА-Я\-_]+\s*)+(?<=[\s\.,\^])`);
- match("аллея Театральная", r2);
-}
-@safe unittest
-{// bugzilla 8637 purity of enforce
- auto m = match("hello world", regex("world"));
- enforce(m);
-}
-
-// bugzilla 8725
-@safe unittest
-{
- static italic = regex( r"\*
- (?!\s+)
- (.*?)
- (?!\s+)
- \*", "gx" );
- string input = "this * is* interesting, *very* interesting";
- assert(replace(input, italic, "<i>$1</i>") ==
- "this * is* interesting, <i>very</i> interesting");
-}
-
-// bugzilla 8349
-@safe unittest
-{
- enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)</a>";
- enum peakRegex = ctRegex!(peakRegexStr);
- //note that the regex pattern itself is probably bogus
- assert(match(r"\>wgEncode-blah-Tfbs.narrow</a>", peakRegex));
-}
-
-// bugzilla 9211
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto rx_1 = regex(r"^(\w)*(\d)");
- auto m = match("1234", rx_1);
- assert(equal(m.front, ["1234", "3", "4"]));
- auto rx_2 = regex(r"^([0-9])*(\d)");
- auto m2 = match("1234", rx_2);
- assert(equal(m2.front, ["1234", "3", "4"]));
-}
-
-// bugzilla 9280
-@safe unittest
-{
- string tomatch = "a!b@c";
- static r = regex(r"^(?P<nick>.*?)!(?P<ident>.*?)@(?P<host>.*?)$");
- auto nm = match(tomatch, r);
- assert(nm);
- auto c = nm.captures;
- assert(c[1] == "a");
- assert(c["nick"] == "a");
-}
-
-
-// bugzilla 9579
-@safe unittest
-{
- char[] input = ['a', 'b', 'c'];
- string format = "($1)";
- // used to give a compile error:
- auto re = regex(`(a)`, "g");
- auto r = replace(input, re, format);
- assert(r == "(a)bc");
-}
-
-// bugzilla 9634
-@safe unittest
-{
- auto re = ctRegex!"(?:a+)";
- assert(match("aaaa", re).hit == "aaaa");
-}
-
-//bugzilla 10798
-@safe unittest
-{
- auto cr = ctRegex!("[abcd--c]*");
- auto m = "abc".match(cr);
- assert(m);
- assert(m.hit == "ab");
-}
-
-// bugzilla 10913
-@system unittest
-{
- @system static string foo(const(char)[] s)
- {
- return s.dup;
- }
- @safe static string bar(const(char)[] s)
- {
- return s.dup;
- }
- () @system {
- replace!((a) => foo(a.hit))("blah", regex(`a`));
- }();
- () @safe {
- replace!((a) => bar(a.hit))("blah", regex(`a`));
- }();
-}
-
-// bugzilla 11262
-@safe unittest
-{
- enum reg = ctRegex!(r",", "g");
- auto str = "This,List";
- str = str.replace(reg, "-");
- assert(str == "This-List");
-}
-
-// bugzilla 11775
-@safe unittest
-{
- assert(collectException(regex("a{1,0}")));
-}
-
-// bugzilla 11839
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- assert(regex(`(?P<var1>\w+)`).namedCaptures.equal(["var1"]));
- assert(collectException(regex(`(?P<1>\w+)`)));
- assert(regex(`(?P<v1>\w+)`).namedCaptures.equal(["v1"]));
- assert(regex(`(?P<__>\w+)`).namedCaptures.equal(["__"]));
- assert(regex(`(?P<я>\w+)`).namedCaptures.equal(["я"]));
-}
-
-// bugzilla 12076
-@safe unittest
-{
- auto RE = ctRegex!(r"(?<!x[a-z]+)\s([a-z]+)");
- string s = "one two";
- auto m = match(s, RE);
-}
-
-// bugzilla 12105
-@safe unittest
-{
- auto r = ctRegex!`.*?(?!a)`;
- assert("aaab".matchFirst(r).hit == "aaa");
- auto r2 = ctRegex!`.*(?!a)`;
- assert("aaab".matchFirst(r2).hit == "aaab");
-}
-
-//bugzilla 11784
-@safe unittest
-{
- assert("abcdefghijklmnopqrstuvwxyz"
- .matchFirst("[a-z&&[^aeiuo]]").hit == "b");
-}
-
-//bugzilla 12366
-@safe unittest
-{
- auto re = ctRegex!(`^((?=(xx+?)\2+$)((?=\2+$)(?=(x+)(\4+$))\5){2})*x?$`);
- assert("xxxxxxxx".match(re).empty);
- assert(!"xxxx".match(re).empty);
-}
-
-// bugzilla 12582
-@safe unittest
-{
- auto r = regex(`(?P<a>abc)`);
- assert(collectException("abc".matchFirst(r)["b"]));
-}
-
-// bugzilla 12691
-@safe unittest
-{
- assert(bmatch("e@", "^([a-z]|)*$").empty);
- assert(bmatch("e@", ctRegex!`^([a-z]|)*$`).empty);
-}
-
-//bugzilla 12713
-@safe unittest
-{
- assertThrown(regex("[[a-z]([a-z]|(([[a-z])))"));
-}
-
-//bugzilla 12747
-@safe unittest
-{
- assertThrown(regex(`^x(\1)`));
- assertThrown(regex(`^(x(\1))`));
- assertThrown(regex(`^((x)(?=\1))`));
-}
-
-// bugzilla 14504
-@safe unittest
-{
- auto p = ctRegex!("a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?" ~
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
-}
-
-// bugzilla 14529
-@safe unittest
-{
- auto ctPat2 = regex(r"^[CDF]$", "i");
- foreach (v; ["C", "c", "D", "d", "F", "f"])
- assert(matchAll(v, ctPat2).front.hit == v);
-}
-
-// bugzilla 14615
-@safe unittest
-{
- import std.array : appender;
- import std.regex : replaceFirst, replaceFirstInto, regex;
- import std.stdio : writeln;
-
- auto example = "Hello, world!";
- auto pattern = regex("^Hello, (bug)"); // won't find this one
- auto result = replaceFirst(example, pattern, "$1 Sponge Bob");
- assert(result == "Hello, world!"); // Ok.
-
- auto sink = appender!string;
- replaceFirstInto(sink, example, pattern, "$1 Sponge Bob");
- assert(sink.data == "Hello, world!");
- replaceAllInto(sink, example, pattern, "$1 Sponge Bob");
- assert(sink.data == "Hello, world!Hello, world!");
-}
-
-// bugzilla 15573
-@safe unittest
-{
- auto rx = regex("[c d]", "x");
- assert("a b".matchFirst(rx));
-}
-
-// bugzilla 15864
-@safe unittest
-{
- regex(`(<a (?:(?:\w+=\"[^"]*\")?\s*)*href="\.\.?)"`);
-}
-
-@safe unittest
-{
- auto r = regex("(?# comment)abc(?# comment2)");
- assert("abc".matchFirst(r));
- assertThrown(regex("(?#..."));
-}
-
-// bugzilla 17075
-@safe unittest
-{
- enum titlePattern = `<title>(.+)</title>`;
- static titleRegex = ctRegex!titlePattern;
- string input = "<title>" ~ "<".repeat(100_000).join;
- assert(input.matchFirst(titleRegex).empty);
-}
-
-// bugzilla 17212
-@safe unittest
-{
- auto r = regex(" [a] ", "x");
- assert("a".matchFirst(r));
-}
-
-// bugzilla 17157
-@safe unittest
-{
- import std.algorithm.comparison : equal;
- auto ctr = ctRegex!"(a)|(b)|(c)|(d)";
- auto r = regex("(a)|(b)|(c)|(d)", "g");
- auto s = "--a--b--c--d--";
- auto outcomes = [
- ["a", "a", "", "", ""],
- ["b", "", "b", "", ""],
- ["c", "", "", "c", ""],
- ["d", "", "", "", "d"]
- ];
- assert(equal!equal(s.matchAll(ctr), outcomes));
- assert(equal!equal(s.bmatch(r), outcomes));
-}
-
-// bugzilla 17667
-@safe unittest
-{
- import std.algorithm.searching : canFind;
- void willThrow(T, size_t line = __LINE__)(T arg, string msg)
- {
- auto e = collectException(regex(arg));
- assert(e.msg.canFind(msg), to!string(line) ~ ": " ~ e.msg);
- }
- willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class");
- willThrow([r"[\", r"123"], "no matching ']' found while parsing character class");
- willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class");
- willThrow([r"[a-\", r"123"], "invalid escape sequence");
- willThrow([r"\", r"123"], "invalid escape sequence");
-}
-
-// bugzilla 17668
-@safe unittest
-{
- import std.algorithm.searching;
- auto e = collectException!RegexException(regex(q"<[^]>"));
- assert(e.msg.canFind("no operand for '^'"));
-}
-
-// bugzilla 17673
-@safe unittest
-{
- string str = `<">`;
- string[] regexps = ["abc", "\"|x"];
- auto regexp = regex(regexps);
- auto c = matchFirst(str, regexp);
- assert(c);
- assert(c.whichPattern == 2);
-}
-
diff --git a/libphobos/src/std/regex/internal/tests2.d b/libphobos/src/std/regex/internal/tests2.d
new file mode 100644
index 0000000..420f8d3
--- /dev/null
+++ b/libphobos/src/std/regex/internal/tests2.d
@@ -0,0 +1,662 @@
+// Split-up due to DMD's enormous memory consumption
+
+module std.regex.internal.tests2;
+
+package(std.regex):
+
+import std.conv, std.exception, std.meta, std.range,
+ std.typecons, std.regex;
+
+import std.regex.internal.ir : Escapables; // characters that need escaping
+
+@safe unittest
+{
+ auto cr = ctRegex!("abc");
+ assert(bmatch("abc",cr).hit == "abc");
+ auto cr2 = ctRegex!("ab*c");
+ assert(bmatch("abbbbc",cr2).hit == "abbbbc");
+}
+@safe unittest
+{
+ auto cr3 = ctRegex!("^abc$");
+ assert(bmatch("abc",cr3).hit == "abc");
+ auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`);
+ assert(array(match("azb",cr4).captures) == ["azb", "azb"]);
+}
+
+@safe unittest
+{
+ auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}");
+ assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb");
+ auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w);
+ assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w);
+}
+
+@safe unittest
+{
+ auto cr7 = ctRegex!(`\r.*?$`,"sm");
+ assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy");
+ auto greed = ctRegex!("<packet.*?/packet>");
+ assert(bmatch("<packet>text</packet><packet>text</packet>", greed).hit
+ == "<packet>text</packet>");
+}
+
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto cr8 = ctRegex!("^(a)(b)?(c*)");
+ auto m8 = bmatch("abcc",cr8);
+ assert(m8);
+ assert(m8.captures[1] == "a");
+ assert(m8.captures[2] == "b");
+ assert(m8.captures[3] == "cc");
+ auto cr9 = ctRegex!("q(a|b)*q");
+ auto m9 = match("xxqababqyy",cr9);
+ assert(m9);
+ assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"]));
+}
+
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto rtr = regex("a|b|c");
+ enum ctr = regex("a|b|c");
+ assert(equal(rtr.ir,ctr.ir));
+ //CTFE parser BUG is triggered by group
+ //in the middle of alternation (at least not first and not last)
+ enum testCT = regex(`abc|(edf)|xyz`);
+ auto testRT = regex(`abc|(edf)|xyz`);
+ assert(equal(testCT.ir,testRT.ir));
+}
+
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ import std.algorithm.iteration : map;
+ enum cx = ctRegex!"(A|B|C)";
+ auto mx = match("B",cx);
+ assert(mx);
+ assert(equal(mx.captures, [ "B", "B"]));
+ enum cx2 = ctRegex!"(A|B)*";
+ assert(match("BAAA",cx2));
+
+ enum cx3 = ctRegex!("a{3,4}","i");
+ auto mx3 = match("AaA",cx3);
+ assert(mx3);
+ assert(mx3.captures[0] == "AaA");
+ enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i");
+ auto mx4 = match("aaaabc", cx4);
+ assert(mx4);
+ assert(mx4.captures[0] == "aaaab");
+ auto cr8 = ctRegex!("(a)(b)?(c*)");
+ auto m8 = bmatch("abcc",cr8);
+ assert(m8);
+ assert(m8.captures[1] == "a");
+ assert(m8.captures[2] == "b");
+ assert(m8.captures[3] == "cc");
+ auto cr9 = ctRegex!(".*$", "gm");
+ auto m9 = match("First\rSecond", cr9);
+ assert(m9);
+ assert(equal(map!"a.hit"(m9), ["First", "", "Second"]));
+}
+
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ import std.algorithm.iteration : map;
+//global matching
+ void test_body(alias matchFn)()
+ {
+ string s = "a quick brown fox jumps over a lazy dog";
+ auto r1 = regex("\\b[a-z]+\\b","g");
+ string[] test;
+ foreach (m; matchFn(s, r1))
+ test ~= m.hit;
+ assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"]));
+ auto free_reg = regex(`
+
+ abc
+ \s+
+ "
+ (
+ [^"]+
+ | \\ "
+ )+
+ "
+ z
+ `, "x");
+ auto m = match(`abc "quoted string with \" inside"z`,free_reg);
+ assert(m);
+ string mails = " hey@you.com no@spam.net ";
+ auto rm = regex(`@(?<=\S+@)\S+`,"g");
+ assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"]));
+ auto m2 = matchFn("First line\nSecond line",regex(".*$","gm"));
+ assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"]));
+ auto m2a = matchFn("First line\nSecond line",regex(".+$","gm"));
+ assert(equal(map!"a[0]"(m2a), ["First line", "Second line"]));
+ auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm"));
+ assert(equal(map!"a[0]"(m2b), ["First line", "Second line"]));
+ debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!");
+ }
+ test_body!bmatch();
+ test_body!match();
+}
+
+//tests for accumulated std.regex issues and other regressions
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ import std.algorithm.iteration : map;
+ void test_body(alias matchFn)()
+ {
+ //issue 5857
+ //matching goes out of control if ... in (...){x} has .*/.+
+ auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures;
+ assert(c[0] == "axxxzayyyyyzd");
+ assert(c[1] == "ayyyyyz");
+ auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures;
+ assert(c2[0] == "axxxayyyyyd");
+ assert(c2[1] == "ayyyyy");
+ //issue 2108
+ //greedy vs non-greedy
+ auto nogreed = regex("<packet.*?/packet>");
+ assert(matchFn("<packet>text</packet><packet>text</packet>", nogreed).hit
+ == "<packet>text</packet>");
+ auto greed = regex("<packet.*/packet>");
+ assert(matchFn("<packet>text</packet><packet>text</packet>", greed).hit
+ == "<packet>text</packet><packet>text</packet>");
+ //issue 4574
+ //empty successful match still advances the input
+ string[] pres, posts, hits;
+ foreach (m; matchFn("abcabc", regex("","g")))
+ {
+ pres ~= m.pre;
+ posts ~= m.post;
+ assert(m.hit.empty);
+
+ }
+ auto heads = [
+ "abcabc",
+ "abcab",
+ "abca",
+ "abc",
+ "ab",
+ "a",
+ ""
+ ];
+ auto tails = [
+ "abcabc",
+ "bcabc",
+ "cabc",
+ "abc",
+ "bc",
+ "c",
+ ""
+ ];
+ assert(pres == array(retro(heads)));
+ assert(posts == tails);
+ //issue 6076
+ //regression on .*
+ auto re = regex("c.*|d");
+ auto m = matchFn("mm", re);
+ assert(!m);
+ debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!");
+ auto rprealloc = regex(`((.){5}.{1,10}){5}`);
+ auto arr = array(repeat('0',100));
+ auto m2 = matchFn(arr, rprealloc);
+ assert(m2);
+ assert(collectException(
+ regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$")
+ ) is null);
+ foreach (ch; [Escapables])
+ {
+ assert(match(to!string(ch),regex(`[\`~ch~`]`)));
+ assert(!match(to!string(ch),regex(`[^\`~ch~`]`)));
+ assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`)));
+ }
+ //bugzilla 7718
+ string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'";
+ auto reStrCmd = regex (`(".*")|('.*')`, "g");
+ assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)),
+ [`"/GIT/Ruby Apps/sec"`, `'notimer'`]));
+ }
+ test_body!bmatch();
+ test_body!match();
+}
+
+// tests for replace
+@safe unittest
+{
+ void test(alias matchFn)()
+ {
+ import std.uni : toUpper;
+
+ foreach (i, v; AliasSeq!(string, wstring, dstring))
+ {
+ auto baz(Cap)(Cap m)
+ if (is(Cap == Captures!(Cap.String)))
+ {
+ return toUpper(m.hit);
+ }
+ alias String = v;
+ assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c"))
+ == to!String("ack rapacity"));
+ assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c"))
+ == to!String("ack capacity"));
+ assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]"))
+ == to!String("[n]oon"));
+ assert(std.regex.replace!(matchFn)(
+ to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'")
+ ) == to!String(": test2 test1 :"));
+ auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."),
+ regex(to!String("[ar]"), "g"));
+ assert(s == "StRAp A Rocket engine on A chicken.");
+ }
+ debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!");
+ }
+ test!(bmatch)();
+ test!(match)();
+}
+
+// tests for splitter
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto s1 = ", abc, de, fg, hi, ";
+ auto sp1 = splitter(s1, regex(", *"));
+ auto w1 = ["", "abc", "de", "fg", "hi", ""];
+ assert(equal(sp1, w1));
+
+ auto s2 = ", abc, de, fg, hi";
+ auto sp2 = splitter(s2, regex(", *"));
+ auto w2 = ["", "abc", "de", "fg", "hi"];
+
+ uint cnt;
+ foreach (e; sp2)
+ {
+ assert(w2[cnt++] == e);
+ }
+ assert(equal(sp2, w2));
+}
+
+@safe unittest
+{
+ char[] s1 = ", abc, de, fg, hi, ".dup;
+ auto sp2 = splitter(s1, regex(", *"));
+}
+
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto s1 = ", abc, de, fg, hi, ";
+ auto w1 = ["", "abc", "de", "fg", "hi", ""];
+ assert(equal(split(s1, regex(", *")), w1[]));
+}
+
+@safe unittest
+{ // bugzilla 7141
+ string pattern = `[a\--b]`;
+ assert(match("-", pattern));
+ assert(match("b", pattern));
+ string pattern2 = `[&-z]`;
+ assert(match("b", pattern2));
+}
+@safe unittest
+{//bugzilla 7111
+ assert(match("", regex("^")));
+}
+@safe unittest
+{//bugzilla 7300
+ assert(!match("a"d, "aa"d));
+}
+
+// bugzilla 7551
+@safe unittest
+{
+ auto r = regex("[]abc]*");
+ assert("]ab".matchFirst(r).hit == "]ab");
+ assertThrown(regex("[]"));
+ auto r2 = regex("[]abc--ab]*");
+ assert("]ac".matchFirst(r2).hit == "]");
+}
+
+@safe unittest
+{//bugzilla 7674
+ assert("1234".replace(regex("^"), "$$") == "$1234");
+ assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?");
+ assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?");
+}
+@safe unittest
+{// bugzilla 7679
+ import std.algorithm.comparison : equal;
+ foreach (S; AliasSeq!(string, wstring, dstring))
+ (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
+ enum re = ctRegex!(to!S(r"\."));
+ auto str = to!S("a.b");
+ assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")]));
+ assert(split(str, re) == [to!S("a"), to!S("b")]);
+ }();
+}
+@safe unittest
+{//bugzilla 8203
+ string data = "
+ NAME = XPAW01_STA:STATION
+ NAME = XPAW01_STA
+ ";
+ auto uniFileOld = data;
+ auto r = regex(
+ r"^NAME = (?P<comp>[a-zA-Z0-9_]+):*(?P<blk>[a-zA-Z0-9_]*)","gm");
+ auto uniCapturesNew = match(uniFileOld, r);
+ for (int i = 0; i < 20; i++)
+ foreach (matchNew; uniCapturesNew) {}
+ //a second issue with same symptoms
+ auto r2 = regex(`([а-яА-Я\-_]+\s*)+(?<=[\s\.,\^])`);
+ match("аллея Театральная", r2);
+}
+@safe unittest
+{// bugzilla 8637 purity of enforce
+ auto m = match("hello world", regex("world"));
+ enforce(m);
+}
+
+// bugzilla 8725
+@safe unittest
+{
+ static italic = regex( r"\*
+ (?!\s+)
+ (.*?)
+ (?!\s+)
+ \*", "gx" );
+ string input = "this * is* interesting, *very* interesting";
+ assert(replace(input, italic, "<i>$1</i>") ==
+ "this * is* interesting, <i>very</i> interesting");
+}
+
+// bugzilla 8349
+@safe unittest
+{
+ enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)</a>";
+ enum peakRegex = ctRegex!(peakRegexStr);
+ //note that the regex pattern itself is probably bogus
+ assert(match(r"\>wgEncode-blah-Tfbs.narrow</a>", peakRegex));
+}
+
+// bugzilla 9211
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto rx_1 = regex(r"^(\w)*(\d)");
+ auto m = match("1234", rx_1);
+ assert(equal(m.front, ["1234", "3", "4"]));
+ auto rx_2 = regex(r"^([0-9])*(\d)");
+ auto m2 = match("1234", rx_2);
+ assert(equal(m2.front, ["1234", "3", "4"]));
+}
+
+// bugzilla 9280
+@safe unittest
+{
+ string tomatch = "a!b@c";
+ static r = regex(r"^(?P<nick>.*?)!(?P<ident>.*?)@(?P<host>.*?)$");
+ auto nm = match(tomatch, r);
+ assert(nm);
+ auto c = nm.captures;
+ assert(c[1] == "a");
+ assert(c["nick"] == "a");
+}
+
+
+// bugzilla 9579
+@safe unittest
+{
+ char[] input = ['a', 'b', 'c'];
+ string format = "($1)";
+ // used to give a compile error:
+ auto re = regex(`(a)`, "g");
+ auto r = replace(input, re, format);
+ assert(r == "(a)bc");
+}
+
+// bugzilla 9634
+@safe unittest
+{
+ auto re = ctRegex!"(?:a+)";
+ assert(match("aaaa", re).hit == "aaaa");
+}
+
+//bugzilla 10798
+@safe unittest
+{
+ auto cr = ctRegex!("[abcd--c]*");
+ auto m = "abc".match(cr);
+ assert(m);
+ assert(m.hit == "ab");
+}
+
+// bugzilla 10913
+@system unittest
+{
+ @system static string foo(const(char)[] s)
+ {
+ return s.dup;
+ }
+ @safe static string bar(const(char)[] s)
+ {
+ return s.dup;
+ }
+ () @system {
+ replace!((a) => foo(a.hit))("blah", regex(`a`));
+ }();
+ () @safe {
+ replace!((a) => bar(a.hit))("blah", regex(`a`));
+ }();
+}
+
+// bugzilla 11262
+@safe unittest
+{
+ enum reg = ctRegex!(r",", "g");
+ auto str = "This,List";
+ str = str.replace(reg, "-");
+ assert(str == "This-List");
+}
+
+// bugzilla 11775
+@safe unittest
+{
+ assert(collectException(regex("a{1,0}")));
+}
+
+// bugzilla 11839
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ assert(regex(`(?P<var1>\w+)`).namedCaptures.equal(["var1"]));
+ assert(collectException(regex(`(?P<1>\w+)`)));
+ assert(regex(`(?P<v1>\w+)`).namedCaptures.equal(["v1"]));
+ assert(regex(`(?P<__>\w+)`).namedCaptures.equal(["__"]));
+ assert(regex(`(?P<я>\w+)`).namedCaptures.equal(["я"]));
+}
+
+// bugzilla 12076
+@safe unittest
+{
+ auto RE = ctRegex!(r"(?<!x[a-z]+)\s([a-z]+)");
+ string s = "one two";
+ auto m = match(s, RE);
+}
+
+// bugzilla 12105
+@safe unittest
+{
+ auto r = ctRegex!`.*?(?!a)`;
+ assert("aaab".matchFirst(r).hit == "aaa");
+ auto r2 = ctRegex!`.*(?!a)`;
+ assert("aaab".matchFirst(r2).hit == "aaab");
+}
+
+//bugzilla 11784
+@safe unittest
+{
+ assert("abcdefghijklmnopqrstuvwxyz"
+ .matchFirst("[a-z&&[^aeiuo]]").hit == "b");
+}
+
+//bugzilla 12366
+@safe unittest
+{
+ auto re = ctRegex!(`^((?=(xx+?)\2+$)((?=\2+$)(?=(x+)(\4+$))\5){2})*x?$`);
+ assert("xxxxxxxx".match(re).empty);
+ assert(!"xxxx".match(re).empty);
+}
+
+// bugzilla 12582
+@safe unittest
+{
+ auto r = regex(`(?P<a>abc)`);
+ assert(collectException("abc".matchFirst(r)["b"]));
+}
+
+// bugzilla 12691
+@safe unittest
+{
+ assert(bmatch("e@", "^([a-z]|)*$").empty);
+ assert(bmatch("e@", ctRegex!`^([a-z]|)*$`).empty);
+}
+
+//bugzilla 12713
+@safe unittest
+{
+ assertThrown(regex("[[a-z]([a-z]|(([[a-z])))"));
+}
+
+//bugzilla 12747
+@safe unittest
+{
+ assertThrown(regex(`^x(\1)`));
+ assertThrown(regex(`^(x(\1))`));
+ assertThrown(regex(`^((x)(?=\1))`));
+}
+
+// bugzilla 14504
+@safe unittest
+{
+ auto p = ctRegex!("a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?" ~
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+}
+
+// bugzilla 14529
+@safe unittest
+{
+ auto ctPat2 = regex(r"^[CDF]$", "i");
+ foreach (v; ["C", "c", "D", "d", "F", "f"])
+ assert(matchAll(v, ctPat2).front.hit == v);
+}
+
+// bugzilla 14615
+@safe unittest
+{
+ import std.array : appender;
+ import std.regex : replaceFirst, replaceFirstInto, regex;
+ import std.stdio : writeln;
+
+ auto example = "Hello, world!";
+ auto pattern = regex("^Hello, (bug)"); // won't find this one
+ auto result = replaceFirst(example, pattern, "$1 Sponge Bob");
+ assert(result == "Hello, world!"); // Ok.
+
+ auto sink = appender!string;
+ replaceFirstInto(sink, example, pattern, "$1 Sponge Bob");
+ assert(sink.data == "Hello, world!");
+ replaceAllInto(sink, example, pattern, "$1 Sponge Bob");
+ assert(sink.data == "Hello, world!Hello, world!");
+}
+
+// bugzilla 15573
+@safe unittest
+{
+ auto rx = regex("[c d]", "x");
+ assert("a b".matchFirst(rx));
+}
+
+// bugzilla 15864
+@safe unittest
+{
+ regex(`(<a (?:(?:\w+=\"[^"]*\")?\s*)*href="\.\.?)"`);
+}
+
+@safe unittest
+{
+ auto r = regex("(?# comment)abc(?# comment2)");
+ assert("abc".matchFirst(r));
+ assertThrown(regex("(?#..."));
+}
+
+// bugzilla 17075
+@safe unittest
+{
+ enum titlePattern = `<title>(.+)</title>`;
+ static titleRegex = ctRegex!titlePattern;
+ string input = "<title>" ~ "<".repeat(100_000).join;
+ assert(input.matchFirst(titleRegex).empty);
+}
+
+// bugzilla 17212
+@safe unittest
+{
+ auto r = regex(" [a] ", "x");
+ assert("a".matchFirst(r));
+}
+
+// bugzilla 17157
+@safe unittest
+{
+ import std.algorithm.comparison : equal;
+ auto ctr = ctRegex!"(a)|(b)|(c)|(d)";
+ auto r = regex("(a)|(b)|(c)|(d)", "g");
+ auto s = "--a--b--c--d--";
+ auto outcomes = [
+ ["a", "a", "", "", ""],
+ ["b", "", "b", "", ""],
+ ["c", "", "", "c", ""],
+ ["d", "", "", "", "d"]
+ ];
+ assert(equal!equal(s.matchAll(ctr), outcomes));
+ assert(equal!equal(s.bmatch(r), outcomes));
+}
+
+// bugzilla 17667
+@safe unittest
+{
+ import std.algorithm.searching : canFind;
+ void willThrow(T, size_t line = __LINE__)(T arg, string msg)
+ {
+ auto e = collectException(regex(arg));
+ assert(e.msg.canFind(msg), to!string(line) ~ ": " ~ e.msg);
+ }
+ willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class");
+ willThrow([r"[\", r"123"], "no matching ']' found while parsing character class");
+ willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class");
+ willThrow([r"[a-\", r"123"], "invalid escape sequence");
+ willThrow([r"\", r"123"], "invalid escape sequence");
+}
+
+// bugzilla 17668
+@safe unittest
+{
+ import std.algorithm.searching;
+ auto e = collectException!RegexException(regex(q"<[^]>"));
+ assert(e.msg.canFind("no operand for '^'"));
+}
+
+// bugzilla 17673
+@safe unittest
+{
+ string str = `<">`;
+ string[] regexps = ["abc", "\"|x"];
+ auto regexp = regex(regexps);
+ auto c = matchFirst(str, regexp);
+ assert(c);
+ assert(c.whichPattern == 2);
+}
+
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index ecb2c8b..d7de153 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -85,10 +85,10 @@ else version (Posix)
}
}
+ public import core.sys.posix.netinet.in_;
import core.sys.posix.arpa.inet;
import core.sys.posix.fcntl;
import core.sys.posix.netdb;
- import core.sys.posix.netinet.in_;
import core.sys.posix.netinet.tcp;
import core.sys.posix.sys.select;
import core.sys.posix.sys.socket;
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index a63227c..55119fc 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -4204,10 +4204,11 @@ package template OverloadSet(string nam, T...)
/*
Used by MemberFunctionGenerator.
*/
-package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func))
+package template FuncInfo(alias func)
+if (is(typeof(&func)))
{
- alias RT = ReturnType!T;
- alias PT = Parameters!T;
+ alias RT = ReturnType!(typeof(&func));
+ alias PT = Parameters!(typeof(&func));
}
package template FuncInfo(Func)
{
@@ -4248,6 +4249,7 @@ private static:
// Internal stuffs
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
import std.format;
+ alias format = std.format.format;
enum CONSTRUCTOR_NAME = "__ctor";
@@ -5024,7 +5026,7 @@ package template GetOverloadedMethods(T)
enum isMethod = false;
}
alias follows = AliasSeq!(
- std.meta.Filter!(isMethod, __traits(getOverloads, T, name)),
+ Filter!(isMethod, __traits(getOverloads, T, name)),
follows!(i + 1));
}
}
diff --git a/libphobos/src/std/zip.d b/libphobos/src/std/zip.d
index 8b130ea..9e55d19 100644
--- a/libphobos/src/std/zip.d
+++ b/libphobos/src/std/zip.d
@@ -263,8 +263,8 @@ final class ArchiveMember
{
void print()
{
- printf("name = '%.*s'\n", name.length, name.ptr);
- printf("\tcomment = '%.*s'\n", comment.length, comment.ptr);
+ printf("name = '%.*s'\n", cast(int) name.length, name.ptr);
+ printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr);
printf("\tmadeVersion = x%04x\n", _madeVersion);
printf("\textractVersion = x%04x\n", extractVersion);
printf("\tflags = x%04x\n", flags);
@@ -348,7 +348,7 @@ final class ZipArchive
printf("\tdiskStartDir = %u\n", diskStartDir);
printf("\tnumEntries = %u\n", numEntries);
printf("\ttotalEntries = %u\n", totalEntries);
- printf("\tcomment = '%.*s'\n", comment.length, comment.ptr);
+ printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr);
}
}
diff --git a/libphobos/testsuite/libphobos.exceptions/chain.d b/libphobos/testsuite/libphobos.exceptions/chain.d
index 462ba24..0305707 100644
--- a/libphobos/testsuite/libphobos.exceptions/chain.d
+++ b/libphobos/testsuite/libphobos.exceptions/chain.d
@@ -65,14 +65,14 @@ void main()
string prefix = "";
for ({ size_t i; Throwable ex = original; } ex; ex = ex.next, ++i)
{
- printf("%.*s%.*s\n", prefix.length, prefix.ptr, ex.msg.length, ex.msg.ptr);
+ printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr);
prefix = prefix~" ";
}
printf("Bypassed chain was:\n");
prefix = "";
for ({ size_t i; Throwable ex = original.bypassedException; } ex; ex = ex.next, ++i)
{
- printf("%.*s%.*s\n", prefix.length, prefix.ptr, ex.msg.length, ex.msg.ptr);
+ printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr);
prefix = prefix~" ";
}
}
diff --git a/libphobos/testsuite/libphobos.exceptions/line_trace.d b/libphobos/testsuite/libphobos.exceptions/line_trace.d
index 7b75d3a..70762ff 100644
--- a/libphobos/testsuite/libphobos.exceptions/line_trace.d
+++ b/libphobos/testsuite/libphobos.exceptions/line_trace.d
@@ -9,7 +9,7 @@ void main()
{
import core.stdc.stdio;
auto str = e.toString();
- printf("%.*s\n", str.length, str.ptr);
+ printf("%.*s\n", cast(int)str.length, str.ptr);
}
}