diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-04-02 13:29:22 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-04-04 01:26:20 +0200 |
commit | 5a0aa603b2452dca48ad86d97d4b918187d259fc (patch) | |
tree | 67439099b8129248a45826b5791912b20ff3c3fb | |
parent | ba0f6902666430e5d065a92b3d5292cba91813d3 (diff) | |
download | gcc-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.
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); } } |