d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9

D front-end changes:

    - Import latest fixes from dmd v2.107.0-beta.1.
    - Hex strings can now be cast to integer arrays.
    - Add support for Interpolated Expression Sequences.

D runtime changes:

    - Import latest fixes from druntime v2.107.0-beta.1.
    - New core.interpolation module to provide run-time support for D
      interpolated expression sequence literals.

Phobos changes:

    - Import latest fixes from phobos v2.107.0-beta.1.
    - `std.range.primitives.isBidirectionalRange', and
      `std.range.primitives.isRandomAccessRange' now take an optional
      element type.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd e770945277.
	* Make-lang.in (D_FRONTEND_OBJS): Add d/basicmangle.o, d/enumsem.o,
	d/funcsem.o, d/templatesem.o.
	* d-builtins.cc (build_frontend_type): Update for new front-end
	interface.
	* d-codegen.cc (declaration_type): Likewise.
	(parameter_type): Likewise.
	* d-incpath.cc (add_globalpaths): Likewise.
	(add_filepaths): Likewise.
	(add_import_paths): Likewise.
	* d-lang.cc (d_init_options): Likewise.
	(d_handle_option): Likewise.
	(d_parse_file): Likewise.
	* decl.cc (DeclVisitor::finish_vtable): Likewise.
	(DeclVisitor::visit (FuncDeclaration *)): Likewise.
	(get_symbol_decl): Likewise.
	* expr.cc (ExprVisitor::visit (StringExp *)): Likewise.
	Implement support for 8-byte hexadecimal strings.
	* typeinfo.cc (create_tinfo_types): Update internal TypeInfo
	representation.
	(TypeInfoVisitor::visit (TypeInfoConstDeclaration *)): Update for new
	front-end interface.
	(TypeInfoVisitor::visit (TypeInfoInvariantDeclaration *)): Likewise.
	(TypeInfoVisitor::visit (TypeInfoSharedDeclaration *)): Likewise.
	(TypeInfoVisitor::visit (TypeInfoWildDeclaration *)): Likewise.
	(TypeInfoVisitor::visit (TypeInfoClassDeclaration *)): Move data for
	TypeInfo_Class.nameSig to the end of the object.
	(create_typeinfo): Update for new front-end interface.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime e770945277.
	* libdruntime/Makefile.am (DRUNTIME_SOURCES): Add
	core/interpolation.d.
	* libdruntime/Makefile.in: Regenerate.
	* src/MERGE: Merge upstream phobos 6d6e0b9b9.
This commit is contained in:
Iain Buclaw 2024-01-28 12:23:14 +01:00
parent 854b8555bd
commit 51c4eb28c1
136 changed files with 4336 additions and 3051 deletions

View file

@ -87,6 +87,7 @@ D_FRONTEND_OBJS = \
d/ast_node.o \
d/astcodegen.o \
d/astenums.o \
d/basicmangle.o \
d/blockexit.o \
d/builtin.o \
d/canthrow.o \
@ -122,6 +123,7 @@ D_FRONTEND_OBJS = \
d/dtoh.o \
d/dversion.o \
d/entity.o \
d/enumsem.o \
d/errors.o \
d/errorsink.o \
d/escape.o \
@ -130,6 +132,7 @@ D_FRONTEND_OBJS = \
d/file_manager.o \
d/foreachvar.o \
d/func.o \
d/funcsem.o \
d/globals.o \
d/gluelayer.o \
d/hdrgen.o \
@ -192,6 +195,7 @@ D_FRONTEND_OBJS = \
d/stmtstate.o \
d/target.o \
d/templateparamsem.o \
d/templatesem.o \
d/tokens.o \
d/traits.o \
d/transitivevisitor.o \

View file

@ -240,7 +240,7 @@ build_frontend_type (tree type)
sdecl->sizeok = Sizeok::done;
sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
sdecl->type->ctype = type;
sdecl->type->merge2 ();
merge2 (sdecl->type);
/* Add both named and anonymous fields as members of the struct.
Anonymous fields still need a name in D, so call them "__pad%u". */

View file

@ -150,7 +150,7 @@ declaration_type (Declaration *decl)
TypeFunction *tf = TypeFunction::create (NULL, decl->type,
VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
return build_ctype (merge2 (t));
}
/* Static array va_list have array->pointer conversions applied. */
@ -200,7 +200,7 @@ parameter_type (Parameter *arg)
TypeFunction *tf = TypeFunction::create (NULL, arg->type,
VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
return build_ctype (merge2 (t));
}
/* Static array va_list have array->pointer conversions applied. */

View file

@ -71,9 +71,6 @@ add_globalpaths (Strings *paths)
{
if (paths)
{
if (!global.path)
global.path = d_gc_malloc<Strings> ();
for (size_t i = 0; i < paths->length; i++)
{
const char *path = (*paths)[i];
@ -86,7 +83,7 @@ add_globalpaths (Strings *paths)
continue;
}
global.path->push (target);
global.path.push (target);
}
}
}
@ -98,9 +95,6 @@ add_filepaths (Strings *paths)
{
if (paths)
{
if (!global.filePath)
global.filePath = d_gc_malloc<Strings> ();
for (size_t i = 0; i < paths->length; i++)
{
const char *path = (*paths)[i];
@ -112,7 +106,7 @@ add_filepaths (Strings *paths)
continue;
}
global.filePath->push (target);
global.filePath.push (target);
}
}
}
@ -143,9 +137,9 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
/* Ignore duplicate entries. */
bool found = false;
for (size_t i = 0; i < global.params.imppath->length; i++)
for (size_t i = 0; i < global.params.imppath.length; i++)
{
if (strcmp (path, (*global.params.imppath)[i]) == 0)
if (strcmp (path, global.params.imppath[i]) == 0)
{
found = true;
break;
@ -162,33 +156,26 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
if (imultilib)
{
char *target_path = concat (path, "/", imultilib, NULL);
global.params.imppath->shift (target_path);
global.params.imppath.shift (target_path);
}
global.params.imppath->shift (path);
global.params.imppath.shift (path);
}
}
/* Add import search paths. */
if (global.params.imppath)
for (size_t i = 0; i < global.params.imppath.length; i++)
{
for (size_t i = 0; i < global.params.imppath->length; i++)
{
const char *path = (*global.params.imppath)[i];
if (path)
add_globalpaths (FileName::splitPath (path));
}
const char *path = global.params.imppath[i];
if (path)
add_globalpaths (FileName::splitPath (path));
}
/* Add string import search paths. */
if (global.params.fileImppath)
for (size_t i = 0; i < global.params.fileImppath.length; i++)
{
for (size_t i = 0; i < global.params.fileImppath->length; i++)
{
const char *path = (*global.params.fileImppath)[i];
if (path)
add_filepaths (FileName::splitPath (path));
}
const char *path = global.params.fileImppath[i];
if (path)
add_filepaths (FileName::splitPath (path));
}
}

View file

@ -306,9 +306,6 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
global.params.v.errorLimit = flag_max_errors;
global.params.v.messageStyle = MessageStyle::gnu;
global.params.imppath = d_gc_malloc<Strings> ();
global.params.fileImppath = d_gc_malloc<Strings> ();
/* Extra GDC-specific options. */
d_option.fonly = NULL;
d_option.multilib = NULL;
@ -724,11 +721,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_I:
global.params.imppath->push (arg);
global.params.imppath.push (arg);
break;
case OPT_J:
global.params.fileImppath->push (arg);
global.params.fileImppath.push (arg);
break;
case OPT_MM:
@ -1045,25 +1042,24 @@ d_parse_file (void)
{
if (global.params.v.verbose)
{
/* Dump information about the D compiler and language version. */
message ("binary %s", global.params.argv0.ptr);
message ("version %s", global.versionChars ());
if (global.versionids)
/* Dump all predefined version identifiers. */
obstack buffer;
gcc_obstack_init (&buffer);
obstack_grow (&buffer, "predefs ", 9);
for (size_t i = 0; i < global.versionids.length; i++)
{
obstack buffer;
gcc_obstack_init (&buffer);
obstack_grow (&buffer, "predefs ", 9);
for (size_t i = 0; i < global.versionids->length; i++)
{
Identifier *id = (*global.versionids)[i];
const char *str = id->toChars ();
obstack_1grow (&buffer, ' ');
obstack_grow (&buffer, str, strlen (str));
}
obstack_1grow (&buffer, '\0');
message ("%s", (char *) obstack_finish (&buffer));
Identifier *id = global.versionids[i];
const char *str = id->toChars ();
obstack_1grow (&buffer, ' ');
obstack_grow (&buffer, str, strlen (str));
}
obstack_1grow (&buffer, '\0');
message ("%s", (char *) obstack_finish (&buffer));
}
/* Start the main input file, if the debug writer wants it. */

View file

@ -539,7 +539,7 @@ public:
continue;
/* Ensure function has a return value. */
if (!fd->functionSemantic ())
if (!functionSemantic (fd))
has_errors = true;
/* No name hiding to check for. */
@ -563,20 +563,23 @@ public:
if (fd2->isFuture ())
continue;
if (fd->leastAsSpecialized (fd2, NULL) != MATCH::nomatch
|| fd2->leastAsSpecialized (fd, NULL) != MATCH::nomatch)
{
error_at (make_location_t (fd->loc), "use of %qs",
fd->toPrettyChars ());
inform (make_location_t (fd2->loc), "is hidden by %qs",
fd2->toPrettyChars ());
inform (make_location_t (d->loc),
"use %<alias %s = %s.%s;%> to introduce base class "
"overload set", fd->toChars (),
fd->parent->toChars (), fd->toChars ());
has_errors = true;
break;
}
if (FuncDeclaration::leastAsSpecialized (fd, fd2, NULL)
== MATCH::nomatch
&& FuncDeclaration::leastAsSpecialized (fd2, fd, NULL)
== MATCH::nomatch)
continue;
/* Hiding detected; same name, overlapping specializations. */
error_at (make_location_t (fd->loc), "use of %qs",
fd->toPrettyChars ());
inform (make_location_t (fd2->loc), "is hidden by %qs",
fd2->toPrettyChars ());
inform (make_location_t (d->loc),
"use %<alias %s = %s.%s;%> to introduce base class "
"overload set", fd->toChars (),
fd->parent->toChars (), fd->toChars ());
has_errors = true;
break;
}
}
@ -943,7 +946,7 @@ public:
gcc_assert (!doing_semantic_analysis_p);
doing_semantic_analysis_p = true;
d->functionSemantic3 ();
functionSemantic3 (d);
Module::runDeferredSemantic3 ();
doing_semantic_analysis_p = false;
}
@ -1231,7 +1234,7 @@ get_symbol_decl (Declaration *decl)
if (fd)
{
/* Run full semantic on functions we need to know about. */
if (!fd->functionSemantic ())
if (!functionSemantic (fd))
{
decl->csym = error_mark_node;
return decl->csym;

View file

@ -1,4 +1,4 @@
bce5c1f7b521d22dcf1ea4e2bc3f76d9d28274fa
e7709452775d374c1e2dfb67566668ada3dec5fc
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -110,6 +110,8 @@ Note that these groups have no strict meaning, the category assignments are a bi
| File | Purpose |
|-------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
| [dsymbolsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d) | Do semantic 1 pass (symbol identifiers/types) |
| [enumsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/enumsem.d) | Enum semantics |
| [funcsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/funcsem.d) | Function semantics |
| [semantic2.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic2.d) | Do semantic 2 pass (symbol initializers) |
| [semantic3.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic3.d) | Do semantic 3 pass (function bodies) |
| [inline.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inline.d) | Do inline pass (optimization pass that dmd does in the front-end) |
@ -117,6 +119,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| [expressionsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expressionsem.d) | Do semantic analysis for expressions |
| [statementsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statementsem.d) | Do semantic analysis for statements |
| [initsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/initsem.d) | Do semantic analysis for initializers |
| [templatesem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templatesem.d) | Do semantic analysis for templates |
| [templateparamsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templateparamsem.d) | Do semantic analysis for template parameters |
| [typesem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typesem.d) | Do semantic analysis for types |
@ -230,6 +233,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
|-----------------------------------------------------------------------------------|------------------------------------------------------------------|
| [cppmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmangle.d) | C++ name mangling |
| [cppmanglewin.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmanglewin.d) | C++ name mangling for Windows |
| [basicmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/basicmangle.d) | D name mangling for basic types |
| [dmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmangle.d) | D [name mangling](https://dlang.org/spec/abi.html#name_mangling) |
### Linking

View file

@ -234,7 +234,8 @@ struct ClassFlags
hasTypeInfo = 0x20,
isAbstract = 0x40,
isCPPclass = 0x80,
hasDtor = 0x100
hasDtor = 0x100,
hasNameSig = 0x200,
};
};

109
gcc/d/dmd/basicmangle.d Normal file
View file

@ -0,0 +1,109 @@
/**
* Defines the building blocks for creating the mangled names for basic types.
*
* Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/basicmangle.d, _basicmangle.d)
* Documentation: https://dlang.org/phobos/dmd_basicmangle.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/basicmangle.d
*/
module dmd.basicmangle;
import dmd.astenums;
import dmd.common.outbuffer : OutBuffer;
/// Type mangling mapping for basic, derived and user defined types
immutable char[TMAX] mangleChar =
[
Tchar : 'a',
Tbool : 'b',
Tcomplex80 : 'c',
Tfloat64 : 'd',
Tfloat80 : 'e',
Tfloat32 : 'f',
Tint8 : 'g',
Tuns8 : 'h',
Tint32 : 'i',
Timaginary80 : 'j',
Tuns32 : 'k',
Tint64 : 'l',
Tuns64 : 'm',
Tnull : 'n',
Timaginary32 : 'o',
Timaginary64 : 'p',
Tcomplex32 : 'q',
Tcomplex64 : 'r',
Tint16 : 's',
Tuns16 : 't',
Twchar : 'u',
Tvoid : 'v',
Tdchar : 'w',
// x // const
// y // immutable
Tint128 : 'z', // zi
Tuns128 : 'z', // zk
Tarray : 'A',
Ttuple : 'B',
Tclass : 'C',
Tdelegate : 'D',
Tenum : 'E',
Tfunction : 'F', // D function
Tsarray : 'G',
Taarray : 'H',
// I // in
// J // out
// K // ref
// L // lazy
// M // has this, or scope
// N // Nh:vector Ng:wild Nn:noreturn
// O // shared
Tpointer : 'P',
// Q // Type/symbol/identifier backward reference
Treference : 'R',
Tstruct : 'S',
// T // Ttypedef
// U // C function
// W // Windows function
// X // variadic T t...)
// Y // variadic T t,...)
// Z // not variadic, end of parameters
// '@' shouldn't appear anywhere in the deco'd names
Tnone : '@',
Tident : '@',
Tinstance : '@',
Terror : '@',
Ttypeof : '@',
Tslice : '@',
Treturn : '@',
Tvector : '@',
Ttraits : '@',
Tmixin : '@',
Ttag : '@',
Tnoreturn : '@', // becomes 'Nn'
];
unittest
{
foreach (i, mangle; mangleChar)
{
if (mangle == char.init)
{
import core.stdc.stdio;
fprintf(stderr, "ty = %u\n", cast(uint)i);
assert(0);
}
}
}
/***********************
* Mangle basic type ty to buf.
*/
void tyToDecoBuffer(ref OutBuffer buf, int ty) @safe
{
const c = mangleChar[ty];
buf.writeByte(c);
if (c == 'z')
buf.writeByte(ty == Tint128 ? 'i' : 'k');
}

View file

@ -27,6 +27,7 @@ import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@ -905,7 +906,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
a.addMember(sc, ad); // temporarily add to symbol table
}
sdv.dtor.functionSemantic();
functionSemantic(sdv.dtor);
stc = mergeFuncAttrs(stc, sdv.dtor);
if (stc & STC.disable)
@ -1154,7 +1155,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
ad.members.push(func);
func.addMember(sc2, ad);
func.dsymbolSemantic(sc2);
func.functionSemantic(); // to infer attributes
functionSemantic(func); // to infer attributes
sc2.pop();
return func;
@ -1336,7 +1337,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
// perform semantic on the member postblit in order to
// be able to aggregate it later on with the rest of the
// postblits
sdv.postblit.functionSemantic();
functionSemantic(sdv.postblit);
stc = mergeFuncAttrs(stc, sdv.postblit);
stc = mergeFuncAttrs(stc, sdv.dtor);
@ -1401,7 +1402,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
*/
if (sdv.dtor)
{
sdv.dtor.functionSemantic();
functionSemantic(sdv.dtor);
// keep a list of fields that need to be destroyed in case
// of a future postblit failure

View file

@ -755,6 +755,25 @@ struct OutBuffer
} while (value);
}
/**
* Write an array as a string of hexadecimal digits
* Params:
* data = bytes to write
* upperCase = whether to upper case hex digits A-F
*/
void writeHexString(scope const(ubyte)[] data, bool upperCase) pure nothrow @safe
{
auto slice = this.allocate(2 * data.length);
const a = upperCase ? 'A' : 'a';
foreach (i, c; data)
{
char hi = (c >> 4) & 0xF;
slice[i * 2] = cast(char)(hi < 10 ? hi + '0' : hi - 10 + a);
char lo = c & 0xF;
slice[i * 2 + 1] = cast(char)(lo < 10 ? lo + '0' : lo - 10 + a);
}
}
/**
Destructively saves the contents of `this` to `filename`. As an
optimization, if the file already has identical contents with the buffer,
@ -943,3 +962,11 @@ unittest
else
assert(buf[] == "\nabc\n\n");
}
unittest
{
OutBuffer buf;
buf.writeHexString([0xAA, 0xBB], false);
buf.writeHexString([0xCC], true);
assert(buf[] == "aabbCC");
}

View file

@ -548,8 +548,6 @@ extern (C++) final class DebugCondition : DVCondition
/// Ditto
extern(D) static void addGlobalIdent(const(char)[] ident)
{
if (!global.debugids)
global.debugids = new Identifiers();
global.debugids.push(Identifier.idPool(ident));
}
@ -579,7 +577,7 @@ extern (C++) final class DebugCondition : DVCondition
bool definedInModule = false;
if (ident)
{
if (findCondition(mod.debugids, ident))
if (mod.debugids && findCondition(*mod.debugids, ident))
{
inc = Include.yes;
definedInModule = true;
@ -830,8 +828,6 @@ extern (C++) final class VersionCondition : DVCondition
/// Ditto
extern(D) static void addPredefinedGlobalIdent(const(char)[] ident)
{
if (!global.versionids)
global.versionids = new Identifiers();
global.versionids.push(Identifier.idPool(ident));
}
@ -861,7 +857,7 @@ extern (C++) final class VersionCondition : DVCondition
bool definedInModule = false;
if (ident)
{
if (findCondition(mod.versionids, ident))
if (mod.versionids && findCondition(*mod.versionids, ident))
{
inc = Include.yes;
definedInModule = true;
@ -983,15 +979,12 @@ extern (C++) final class StaticIfCondition : Condition
* Returns:
* true if found
*/
bool findCondition(Identifiers* ids, Identifier ident) @safe nothrow pure
bool findCondition(ref Identifiers ids, Identifier ident) @safe nothrow pure
{
if (ids)
foreach (id; ids)
{
foreach (id; *ids)
{
if (id == ident)
return true;
}
if (id == ident)
return true;
}
return false;
}

View file

@ -711,7 +711,7 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
cmp = 1; // if dim1 winds up being 0
foreach (i; 0 .. dim1)
{
uinteger_t c = es1.getCodeUnit(i);
uinteger_t c = es1.getIndex(i);
auto ee2 = es2[i];
if (ee2.isConst() != 1)
{
@ -1119,7 +1119,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
}
else
{
emplaceExp!(IntegerExp)(&ue, loc, es1.getCodeUnit(cast(size_t) i), type);
emplaceExp!(IntegerExp)(&ue, loc, es1.getIndex(cast(size_t) i), type);
}
}
else if (e1.type.toBasetype().ty == Tsarray && e2.op == EXP.int64)
@ -1282,7 +1282,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp existingAE, const StringE
Type elemType = existingAE.type.nextOf();
foreach (j; 0 .. len)
{
const val = newval.getCodeUnit(j);
const val = newval.getIndex(j);
(*existingAE.elements)[j + firstIndex] = new IntegerExp(newval.loc, val, elemType);
}
}

View file

@ -568,6 +568,9 @@ StringExp createBlockDuplicatedStringLiteral(UnionExp* pue, const ref Loc loc, T
case 4:
(cast(dchar*)s)[elemi] = value;
break;
case 8:
(cast(ulong*)s)[elemi] = value;
break;
default:
assert(0);
}
@ -1494,7 +1497,7 @@ Expression ctfeIndex(UnionExp* pue, const ref Loc loc, Type type, Expression e1,
error(loc, "string index %llu is out of bounds `[0 .. %llu]`", indx, cast(ulong)es1.len);
return CTFEExp.cantexp;
}
emplaceExp!IntegerExp(pue, loc, es1.getCodeUnit(cast(size_t) indx), type);
emplaceExp!IntegerExp(pue, loc, es1.getIndex(cast(size_t) indx), type);
return pue.exp();
}
@ -1704,7 +1707,7 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
void* s = mem.xcalloc(newlen + 1, oldse.sz);
const data = oldse.peekData();
memcpy(s, data.ptr, copylen * oldse.sz);
const defaultValue = cast(uint)defaultElem.toInteger();
const defaultValue = cast(ulong)defaultElem.toInteger();
foreach (size_t elemi; copylen .. newlen)
{
switch (oldse.sz)
@ -1718,6 +1721,9 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
case 4:
(cast(dchar*)s)[cast(size_t)(indxlo + elemi)] = cast(dchar)defaultValue;
break;
case 8:
(cast(ulong*)s)[cast(size_t)(indxlo + elemi)] = cast(ulong)defaultValue;
break;
default:
assert(0);
}

View file

@ -123,6 +123,7 @@ extern (C++) struct BaseClass
}
}
// These must match the values in druntime/src/object.d
enum ClassFlags : uint
{
none = 0x0,
@ -135,6 +136,7 @@ enum ClassFlags : uint
isAbstract = 0x40,
isCPPclass = 0x80,
hasDtor = 0x100,
hasNameSig = 0x200,
}
/***********************************************************

View file

@ -30,6 +30,9 @@ class StructDeclaration;
struct IntRange;
struct AttributeViolation;
bool functionSemantic(FuncDeclaration* fd);
bool functionSemantic3(FuncDeclaration* fd);
//enum STC : ulong from astenums.d:
#define STCundefined 0ULL
@ -698,14 +701,12 @@ public:
FuncDeclaration *fdensure(FuncDeclaration *fde);
Expressions *fdrequireParams(Expressions *fdrp);
Expressions *fdensureParams(Expressions *fdep);
bool functionSemantic();
bool functionSemantic3();
bool equals(const RootObject * const o) const override final;
int findVtblIndex(Dsymbols *vtbl, int dim);
bool overloadInsert(Dsymbol *s) override;
bool inUnittest();
MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names);
static MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc);
const char *toPrettyChars(bool QualifyTypes = false) override;
const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure'

View file

@ -122,91 +122,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return isSpecialEnumIdent(ident) && memtype;
}
Expression getDefaultValue(const ref Loc loc)
{
Expression handleErrors(){
defaultval = ErrorExp.get();
return defaultval;
}
//printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
// https://issues.dlang.org/show_bug.cgi?id=23904
// Return defaultval only if it is not ErrorExp.
// A speculative context may set defaultval to ErrorExp;
// subsequent non-speculative contexts need to be able
// to print the error.
if (defaultval && !defaultval.isErrorExp())
return defaultval;
if (isCsymbol())
return memtype.defaultInit(loc, true);
if (_scope)
dsymbolSemantic(this, _scope);
if (errors)
return handleErrors();
if (!members)
{
if (isSpecial())
{
/* Allow these special enums to not need a member list
*/
return defaultval = memtype.defaultInit(loc);
}
error(loc, "%s `%s` is opaque and has no default initializer", kind, toPrettyChars);
return handleErrors();
}
foreach (const i; 0 .. members.length)
{
EnumMember em = (*members)[i].isEnumMember();
if (em)
{
if (em.semanticRun < PASS.semanticdone)
{
error(loc, "%s `%s` forward reference of `%s.init`", kind, toPrettyChars, toChars());
return handleErrors();
}
defaultval = em.value;
return defaultval;
}
}
return handleErrors();
}
Type getMemtype(const ref Loc loc)
{
if (_scope)
{
/* Enum is forward referenced. We don't need to resolve the whole thing,
* just the base type
*/
if (memtype)
{
Loc locx = loc.isValid() ? loc : this.loc;
memtype = memtype.typeSemantic(locx, _scope);
}
else
{
// Run semantic to get the type from a possible first member value
dsymbolSemantic(this, _scope);
}
}
if (!memtype)
{
if (!isAnonymous() && (members || semanticRun >= PASS.semanticdone))
memtype = Type.tint32;
else
{
Loc locx = loc.isValid() ? loc : this.loc;
error(locx, "is forward referenced looking for base type");
return Type.terror;
}
}
return memtype;
}
override inout(EnumDeclaration) isEnumDeclaration() inout
{
return this;

View file

@ -33,6 +33,7 @@ import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -440,7 +441,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
fdError("circular dependency. Functions cannot be interpreted while being compiled");
return CTFEExp.cantexp;
}
if (!fd.functionSemantic3())
if (!functionSemantic3(fd))
return CTFEExp.cantexp;
if (fd.semanticRun < PASS.semantic3done)
{
@ -6097,11 +6098,35 @@ public:
result.type = e.to;
return;
}
// Disallow array type painting, except for conversions between built-in
// types of identical size.
if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
{
auto se = e1.isStringExp();
// Allow casting a hex string literal to short[], int[] or long[]
if (se && se.hexString && se.postfix == StringExp.NoPostfix)
{
const sz = cast(size_t) e.to.nextOf().size;
if ((se.len % sz) != 0)
{
error(e.loc, "hex string length %d must be a multiple of %d to cast to `%s`",
cast(int) se.len, cast(int) sz, e.to.toChars());
result = CTFEExp.cantexp;
return;
}
auto str = arrayCastBigEndian((cast(const ubyte[]) se.peekString()), sz);
emplaceExp!(StringExp)(pue, e1.loc, str, se.len / sz, cast(ubyte) sz);
result = pue.exp();
result.type = e.to;
return;
}
error(e.loc, "array cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
if (se && se.hexString && se.postfix != StringExp.NoPostfix)
errorSupplemental(e.loc, "perhaps remove postfix `%s` from hex string",
(cast(char) se.postfix ~ "\0").ptr);
result = CTFEExp.cantexp;
return;
}
@ -7719,3 +7744,44 @@ private void removeHookTraceImpl(ref CallExp ce, ref FuncDeclaration fd)
if (global.params.v.verbose)
message("strip %s =>\n %s", oldCE.toChars(), ce.toChars());
}
/**
* Cast a `ubyte[]` to an array of larger integers as if we are on a big endian architecture
* Params:
* data = array with big endian data
* size = 1 for ubyte[], 2 for ushort[], 4 for uint[], 8 for ulong[]
* Returns: copy of `data`, with bytes shuffled if compiled for `version(LittleEndian)`
*/
ubyte[] arrayCastBigEndian(const ubyte[] data, size_t size)
{
ubyte[] impl(T)()
{
auto result = new T[](data.length / T.sizeof);
foreach (i; 0 .. result.length)
{
result[i] = 0;
foreach (j; 0 .. T.sizeof)
{
result[i] |= T(data[i * T.sizeof + j]) << ((T.sizeof - 1 - j) * 8);
}
}
return cast(ubyte[]) result;
}
switch (size)
{
case 1: return data.dup;
case 2: return impl!ushort;
case 4: return impl!uint;
case 8: return impl!ulong;
default: assert(0);
}
}
unittest
{
ubyte[] data = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22];
assert(cast(ulong[]) arrayCastBigEndian(data, 8) == [0xAABBCCDDEEFF1122]);
assert(cast(uint[]) arrayCastBigEndian(data, 4) == [0xAABBCCDD, 0xEEFF1122]);
assert(cast(ushort[]) arrayCastBigEndian(data, 2) == [0xAABB, 0xCCDD, 0xEEFF, 0x1122]);
assert(cast(ubyte[]) arrayCastBigEndian(data, 1) == data);
}

View file

@ -137,6 +137,7 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.basicmangle;
import dmd.dclass;
import dmd.declaration;
import dmd.dinterpret;
@ -161,89 +162,6 @@ import dmd.target;
import dmd.tokens;
import dmd.visitor;
private immutable char[TMAX] mangleChar =
[
Tchar : 'a',
Tbool : 'b',
Tcomplex80 : 'c',
Tfloat64 : 'd',
Tfloat80 : 'e',
Tfloat32 : 'f',
Tint8 : 'g',
Tuns8 : 'h',
Tint32 : 'i',
Timaginary80 : 'j',
Tuns32 : 'k',
Tint64 : 'l',
Tuns64 : 'm',
Tnull : 'n',
Timaginary32 : 'o',
Timaginary64 : 'p',
Tcomplex32 : 'q',
Tcomplex64 : 'r',
Tint16 : 's',
Tuns16 : 't',
Twchar : 'u',
Tvoid : 'v',
Tdchar : 'w',
// x // const
// y // immutable
Tint128 : 'z', // zi
Tuns128 : 'z', // zk
Tarray : 'A',
Ttuple : 'B',
Tclass : 'C',
Tdelegate : 'D',
Tenum : 'E',
Tfunction : 'F', // D function
Tsarray : 'G',
Taarray : 'H',
// I // in
// J // out
// K // ref
// L // lazy
// M // has this, or scope
// N // Nh:vector Ng:wild Nn:noreturn
// O // shared
Tpointer : 'P',
// Q // Type/symbol/identifier backward reference
Treference : 'R',
Tstruct : 'S',
// T // Ttypedef
// U // C function
// W // Windows function
// X // variadic T t...)
// Y // variadic T t,...)
// Z // not variadic, end of parameters
// '@' shouldn't appear anywhere in the deco'd names
Tnone : '@',
Tident : '@',
Tinstance : '@',
Terror : '@',
Ttypeof : '@',
Tslice : '@',
Treturn : '@',
Tvector : '@',
Ttraits : '@',
Tmixin : '@',
Ttag : '@',
Tnoreturn : '@', // becomes 'Nn'
];
unittest
{
foreach (i, mangle; mangleChar)
{
if (mangle == char.init)
{
fprintf(stderr, "ty = %u\n", cast(uint)i);
assert(0);
}
}
}
/************************************************
* Append the mangling of type `t` to `buf`.
* Params:
@ -584,6 +502,20 @@ public:
toBuffer(*buf, id.toString(), s);
}
void mangleInteger(dinteger_t v)
{
if (cast(sinteger_t) v < 0)
{
buf.writeByte('N');
buf.print(-v);
}
else
{
buf.writeByte('i');
buf.print(v);
}
}
////////////////////////////////////////////////////////////////////////////
void mangleDecl(Declaration sthis)
{
@ -991,17 +923,7 @@ public:
override void visit(IntegerExp e)
{
const v = e.toInteger();
if (cast(sinteger_t)v < 0)
{
buf.writeByte('N');
buf.print(-v);
}
else
{
buf.writeByte('i');
buf.print(v);
}
mangleInteger(e.toInteger());
}
override void visit(RealExp e)
@ -1028,6 +950,7 @@ public:
char m;
OutBuffer tmp;
const(char)[] q;
/* Write string in UTF-8 format
*/
switch (e.sz)
@ -1065,7 +988,15 @@ public:
q = tmp[];
break;
}
case 8:
// String of size 8 has to be hexstring cast to long[], mangle as array literal
buf.writeByte('A');
buf.print(e.len);
foreach (i; 0 .. e.len)
{
mangleInteger(e.getIndex(i));
}
return;
default:
assert(0);
}
@ -1073,14 +1004,7 @@ public:
buf.writeByte(m);
buf.print(q.length);
buf.writeByte('_'); // nbytes <= 11
auto slice = buf.allocate(2 * q.length);
foreach (i, c; q)
{
char hi = (c >> 4) & 0xF;
slice[i * 2] = cast(char)(hi < 10 ? hi + '0' : hi - 10 + 'a');
char lo = c & 0xF;
slice[i * 2 + 1] = cast(char)(lo < 10 ? lo + '0' : lo - 10 + 'a');
}
buf.writeHexString(cast(const(ubyte)[]) q, false);
}
override void visit(ArrayLiteralExp e)
@ -1168,6 +1092,7 @@ private struct Backref
{
if (t.isFunction_Delegate_PtrToFunction())
{
import dmd.typesem : merge2;
t = t.merge2();
}
}
@ -1213,19 +1138,6 @@ private struct Backref
AssocArray!(Identifier, size_t) idents; /// Identifier => (offset+1) in buf
}
/***********************
* Mangle basic type ty to buf.
*/
private void tyToDecoBuffer(ref OutBuffer buf, int ty) @safe
{
const c = mangleChar[ty];
buf.writeByte(c);
if (c == 'z')
buf.writeByte(ty == Tint128 ? 'i' : 'k');
}
/*********************************
* Mangling for mod.
*/

View file

@ -490,7 +490,7 @@ extern (C++) final class Module : Package
extern (D) static const(char)[] find(const(char)[] filename)
{
return global.fileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null);
return global.fileManager.lookForSourceFile(filename, global.path[]);
}
extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
@ -644,9 +644,9 @@ extern (C++) final class Module : Package
{
/* Print path
*/
if (global.path)
if (global.path.length)
{
foreach (i, p; *global.path)
foreach (i, p; global.path[])
fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, p);
}
else

View file

@ -5204,6 +5204,7 @@ void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
highlight = "$(D_COMMENT ";
break;
case TOK.string_:
case TOK.interpolated:
highlight = "$(D_STRING ";
break;
default:
@ -5216,7 +5217,7 @@ void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
res.writestring(highlight);
size_t o = res.length;
highlightCode3(sc, res, tok.ptr, lex.p);
if (tok.value == TOK.comment || tok.value == TOK.string_)
if (tok.value == TOK.comment || tok.value == TOK.string_ || tok.value == TOK.interpolated)
/* https://issues.dlang.org/show_bug.cgi?id=7656
* https://issues.dlang.org/show_bug.cgi?id=7715
* https://issues.dlang.org/show_bug.cgi?id=10519

View file

@ -616,7 +616,7 @@ bool _isZeroInit(Expression exp)
foreach (i; 0 .. se.len)
{
if (se.getCodeUnit(i))
if (se.getIndex(i) != 0)
return false;
}
return true;

View file

@ -38,11 +38,13 @@ import dmd.dstruct;
import dmd.dsymbol;
import dmd.dtemplate;
import dmd.dversion;
import dmd.enumsem;
import dmd.errors;
import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@ -440,6 +442,15 @@ private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc
return false;
}
// Save the scope and defer semantic analysis on the Dsymbol.
void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
{
s._scope = scx ? scx : sc.copy();
s._scope.setNoFree();
Module.addDeferredSemantic(s);
}
private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
alias visit = Visitor.visit;
@ -450,14 +461,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
this.sc = sc;
}
// Save the scope and defer semantic analysis on the Dsymbol.
private void deferDsymbolSemantic(Dsymbol s, Scope *scx)
{
s._scope = scx ? scx : sc.copy();
s._scope.setNoFree();
Module.addDeferredSemantic(s);
}
override void visit(Dsymbol dsym)
{
.error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
@ -2301,543 +2304,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(EnumDeclaration ed)
{
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
//printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
if (ed.semanticRun >= PASS.semanticdone)
return; // semantic() already completed
if (ed.semanticRun == PASS.semantic)
{
assert(ed.memtype);
error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
ed.errors = true;
ed.semanticRun = PASS.semanticdone;
return;
}
Scope* scx = null;
if (ed._scope)
{
sc = ed._scope;
scx = ed._scope; // save so we don't make redundant copies
ed._scope = null;
}
if (!sc)
return;
ed.parent = sc.parent;
ed.type = ed.type.typeSemantic(ed.loc, sc);
ed.visibility = sc.visibility;
if (sc.stc & STC.deprecated_)
ed.isdeprecated = true;
ed.userAttribDecl = sc.userAttribDecl;
ed.cppnamespace = sc.namespace;
ed.semanticRun = PASS.semantic;
UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
checkMustUseReserved(ed);
if (!ed.members && !ed.memtype) // enum ident;
{
ed.semanticRun = PASS.semanticdone;
return;
}
if (!ed.symtab)
ed.symtab = new DsymbolTable();
/* The separate, and distinct, cases are:
* 1. enum { ... }
* 2. enum : memtype { ... }
* 3. enum ident { ... }
* 4. enum ident : memtype { ... }
* 5. enum ident : memtype;
* 6. enum ident;
*/
if (ed.memtype)
{
ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
/* Check to see if memtype is forward referenced
*/
if (auto te = ed.memtype.isTypeEnum())
{
auto sym = te.toDsymbol(sc).isEnumDeclaration();
// Special enums like __c_[u]long[long] are fine to forward reference
// see https://issues.dlang.org/show_bug.cgi?id=20599
if (!sym.isSpecial() && (!sym.memtype || !sym.members || !sym.symtab || sym._scope))
{
// memtype is forward referenced, so try again later
deferDsymbolSemantic(ed, scx);
//printf("\tdeferring %s\n", toChars());
ed.semanticRun = PASS.initial;
return;
}
else
// Ensure that semantic is run to detect. e.g. invalid forward references
sym.dsymbolSemantic(sc);
}
if (ed.memtype.ty == Tvoid)
{
.error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
ed.memtype = Type.terror;
}
if (ed.memtype.ty == Terror)
{
ed.errors = true;
// poison all the members
ed.members.foreachDsymbol( (s) { s.errors = true; } );
ed.semanticRun = PASS.semanticdone;
return;
}
}
if (!ed.members) // enum ident : memtype;
{
ed.semanticRun = PASS.semanticdone;
return;
}
if (ed.members.length == 0)
{
.error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
ed.errors = true;
ed.semanticRun = PASS.semanticdone;
return;
}
if (!(sc.flags & SCOPE.Cfile)) // C enum remains incomplete until members are done
ed.semanticRun = PASS.semanticdone;
version (none)
{
// @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.100
// Make an error in 2.110
if (sc.stc & STC.scope_)
deprecation(ed.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
}
Scope* sce;
if (ed.isAnonymous())
sce = sc;
else
{
sce = sc.push(ed);
sce.parent = ed;
}
sce = sce.startCTFE();
sce.setNoFree(); // needed for getMaxMinValue()
/* Each enum member gets the sce scope
*/
ed.members.foreachDsymbol( (s)
{
EnumMember em = s.isEnumMember();
if (em)
em._scope = sce;
});
/* addMember() is not called when the EnumDeclaration appears as a function statement,
* so we have to do what addMember() does and install the enum members in the right symbol
* table
*/
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
if (sc.flags & SCOPE.Cfile)
{
/* C11 6.7.2.2
*/
Type commonType = ed.memtype;
if (!commonType)
commonType = Type.tint32;
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
// C11 6.7.2.2-2 value must be representable as an int.
// The sizemask represents all values that int will fit into,
// from 0..uint.max. We want to cover int.min..uint.max.
IntRange ir = IntRange.fromType(commonType);
void emSemantic(EnumMember em, ref ulong nextValue)
{
static void errorReturn(EnumMember em)
{
em.value = ErrorExp.get();
em.errors = true;
em.semanticRun = PASS.semanticdone;
}
em.semanticRun = PASS.semantic;
em.type = commonType;
em._linkage = LINK.c;
em.storage_class |= STC.manifest;
if (em.value)
{
Expression e = em.value;
assert(e.dyncast() == DYNCAST.expression);
/* To merge the type of e with commonType, add 0 of type commonType
*/
if (!ed.memtype)
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
e = e.expressionSemantic(sc);
e = resolveProperties(sc, e);
e = e.integralPromotions(sc);
e = e.ctfeInterpret();
if (e.op == EXP.error)
return errorReturn(em);
auto ie = e.isIntegerExp();
if (!ie)
{
// C11 6.7.2.2-2
.error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
return errorReturn(em);
}
if (ed.memtype && !ir.contains(getIntRange(ie)))
{
// C11 6.7.2.2-2
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
return errorReturn(em);
}
nextValue = ie.toInteger();
if (!ed.memtype)
commonType = e.type;
em.value = new IntegerExp(em.loc, nextValue, commonType);
}
else
{
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
bool first = (em == (*em.ed.members)[0]);
if (!first)
{
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
if (nextValue == max.toInteger())
{
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
return errorReturn(em);
}
nextValue += 1;
}
em.value = new IntegerExp(em.loc, nextValue, commonType);
}
em.type = commonType;
em.semanticRun = PASS.semanticdone;
}
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
emSemantic(em, nextValue);
});
if (!ed.memtype)
{
// cast all members to commonType
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
{
em.type = commonType;
em.value = em.value.castTo(sc, commonType);
}
});
}
ed.memtype = commonType;
ed.semanticRun = PASS.semanticdone;
return;
}
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
em.dsymbolSemantic(em._scope);
});
//printf("defaultval = %lld\n", defaultval);
//if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars());
//printf("members = %s\n", members.toChars());
enumSemantic(sc, ed);
}
override void visit(EnumMember em)
{
//printf("EnumMember::semantic() %s\n", em.toChars());
void errorReturn()
{
em.errors = true;
em.semanticRun = PASS.semanticdone;
}
if (em.errors || em.semanticRun >= PASS.semanticdone)
return;
if (em.semanticRun == PASS.semantic)
{
.error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
return errorReturn();
}
assert(em.ed);
em.ed.dsymbolSemantic(sc);
if (em.ed.errors)
return errorReturn();
if (em.errors || em.semanticRun >= PASS.semanticdone)
return;
if (em._scope)
sc = em._scope;
if (!sc)
return;
em.semanticRun = PASS.semantic;
em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
em._linkage = LINK.d;
em.storage_class |= STC.manifest;
// https://issues.dlang.org/show_bug.cgi?id=9701
if (em.ed.isAnonymous())
{
if (em.userAttribDecl)
em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
else
em.userAttribDecl = em.ed.userAttribDecl;
}
// Eval UDA in this same scope. Issues 19344, 20835, 21122
if (em.userAttribDecl)
{
// Set scope but avoid extra sc.uda attachment inside setScope()
auto inneruda = em.userAttribDecl.userAttribDecl;
em.userAttribDecl.setScope(sc);
em.userAttribDecl.userAttribDecl = inneruda;
em.userAttribDecl.dsymbolSemantic(sc);
}
// The first enum member is special
bool first = (em == (*em.ed.members)[0]);
if (em.origType)
{
em.origType = em.origType.typeSemantic(em.loc, sc);
em.type = em.origType;
assert(em.value); // "type id;" is not a valid enum member declaration
}
if (em.value)
{
Expression e = em.value;
assert(e.dyncast() == DYNCAST.expression);
e = e.expressionSemantic(sc);
e = resolveProperties(sc, e);
e = e.ctfeInterpret();
if (e.op == EXP.error)
return errorReturn();
if (first && !em.ed.memtype && !em.ed.isAnonymous())
{
em.ed.memtype = e.type;
if (em.ed.memtype.ty == Terror)
{
em.ed.errors = true;
return errorReturn();
}
if (em.ed.memtype.ty != Terror)
{
/* https://issues.dlang.org/show_bug.cgi?id=11746
* All of named enum members should have same type
* with the first member. If the following members were referenced
* during the first member semantic, their types should be unified.
*/
em.ed.members.foreachDsymbol( (s)
{
EnumMember enm = s.isEnumMember();
if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
return;
//printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
Expression ev = enm.value;
ev = ev.implicitCastTo(sc, em.ed.memtype);
ev = ev.ctfeInterpret();
ev = ev.castTo(sc, em.ed.type);
if (ev.op == EXP.error)
em.ed.errors = true;
enm.value = ev;
});
if (em.ed.errors)
{
em.ed.memtype = Type.terror;
return errorReturn();
}
}
}
if (em.ed.memtype && !em.origType)
{
e = e.implicitCastTo(sc, em.ed.memtype);
e = e.ctfeInterpret();
// save origValue for better json output
em.origValue = e;
if (!em.ed.isAnonymous())
{
e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
e = e.ctfeInterpret();
}
}
else if (em.origType)
{
e = e.implicitCastTo(sc, em.origType);
e = e.ctfeInterpret();
assert(em.ed.isAnonymous());
// save origValue for better json output
em.origValue = e;
}
em.value = e;
}
else if (first)
{
Type t;
if (em.ed.memtype)
t = em.ed.memtype;
else
{
t = Type.tint32;
if (!em.ed.isAnonymous())
em.ed.memtype = t;
}
const errors = global.startGagging();
Expression e = new IntegerExp(em.loc, 0, t);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
t.toChars(), em.toChars());
}
// save origValue for better json output
em.origValue = e;
if (!em.ed.isAnonymous())
{
e = e.castTo(sc, em.ed.type);
e = e.ctfeInterpret();
}
em.value = e;
}
else
{
/* Find the previous enum member,
* and set this to be the previous value + 1
*/
EnumMember emprev = null;
em.ed.members.foreachDsymbol( (s)
{
if (auto enm = s.isEnumMember())
{
if (enm == em)
return 1; // found
emprev = enm;
}
return 0; // continue
});
assert(emprev);
if (emprev.semanticRun < PASS.semanticdone) // if forward reference
emprev.dsymbolSemantic(emprev._scope); // resolve it
if (emprev.errors)
return errorReturn();
auto errors = global.startGagging();
Expression eprev = emprev.value;
assert(eprev);
// .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
? em.ed.memtype
: eprev.type;
/*
https://issues.dlang.org/show_bug.cgi?id=20777
Previously this used getProperty, which doesn't consider anything user defined,
this construct does do that and thus fixes the bug.
*/
Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
emax = emax.expressionSemantic(sc);
emax = emax.ctfeInterpret();
// check that (eprev != emax)
Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
e = e.expressionSemantic(sc);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
// display an introductory error before showing what actually failed
error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
// rerun to show errors
Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
e2 = e2.expressionSemantic(sc);
e2 = e2.ctfeInterpret();
e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
e2 = e2.expressionSemantic(sc);
e2 = e2.ctfeInterpret();
}
// now any errors are for generating a value
if (e.toInteger())
{
auto mt = em.ed.memtype;
if (!mt)
mt = eprev.type;
.error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
emprev.ed.toChars(), emprev.toChars(), mt.toChars());
return errorReturn();
}
errors = global.startGagging();
// Now set e to (eprev + 1)
e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
e = e.expressionSemantic(sc);
e = e.castTo(sc, eprev.type);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
// rerun to show errors
Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
e2 = e2.expressionSemantic(sc);
e2 = e2.castTo(sc, eprev.type);
e2 = e2.ctfeInterpret();
}
// save origValue (without cast) for better json output
if (e.op != EXP.error) // avoid duplicate diagnostics
{
assert(emprev.origValue);
em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
em.origValue = em.origValue.expressionSemantic(sc);
em.origValue = em.origValue.ctfeInterpret();
}
if (e.op == EXP.error)
return errorReturn();
if (e.type.isfloating())
{
// Check that e != eprev (not always true for floats)
Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
etest = etest.expressionSemantic(sc);
etest = etest.ctfeInterpret();
if (etest.toInteger())
{
.error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
return errorReturn();
}
}
em.value = e;
}
if (!em.origType)
em.type = em.value.type;
assert(em.origValue);
em.semanticRun = PASS.semanticdone;
enumMemberSemantic(sc, em);
}
override void visit(TemplateDeclaration tempdecl)
@ -3026,7 +2498,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (tm.semanticRun == PASS.initial) // forward reference had occurred
{
//printf("forward reference - deferring\n");
return deferDsymbolSemantic(tm, scx);
return deferDsymbolSemantic(sc, tm, scx);
}
tm.inst = tm;
@ -3740,7 +3212,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
continue;
if (cbd.parent && cbd.parent.isTemplateInstance())
{
if (!f2.functionSemantic())
if (!functionSemantic(f2))
goto Ldone;
}
may_override = true;
@ -4945,7 +4417,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sc2.pop();
if (log) printf("\tdeferring %s\n", sd.toChars());
return deferDsymbolSemantic(sd, scx);
return deferDsymbolSemantic(sc, sd, scx);
}
/* Look for special member functions.
@ -5336,7 +4808,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
// Forward referencee of one or more bases, try again later
//printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
return deferDsymbolSemantic(cldec, scx);
return deferDsymbolSemantic(sc, cldec, scx);
}
cldec.baseok = Baseok.done;
@ -5446,7 +4918,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (tc.sym._scope)
Module.addDeferredSemantic(tc.sym);
//printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
return deferDsymbolSemantic(cldec, scx);
return deferDsymbolSemantic(sc, cldec, scx);
}
}
@ -5563,7 +5035,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sc2.pop();
//printf("\tdeferring %s\n", toChars());
return deferDsymbolSemantic(cldec, scx);
return deferDsymbolSemantic(sc, cldec, scx);
}
/* Look for special member functions.
@ -5905,7 +5377,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (idec.baseok == Baseok.none)
{
// Forward referencee of one or more bases, try again later
return deferDsymbolSemantic(idec, scx);
return deferDsymbolSemantic(sc, idec, scx);
}
idec.baseok = Baseok.done;
@ -5942,7 +5414,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Forward referencee of one or more bases, try again later
if (tc.sym._scope)
Module.addDeferredSemantic(tc.sym);
return deferDsymbolSemantic(idec, scx);
return deferDsymbolSemantic(sc, idec, scx);
}
}
@ -6281,7 +5753,7 @@ private extern(C++) class AddMemberVisitor : Visitor
}
else
{
if (findCondition(m.debugidsNot, ds.ident))
if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
{
.error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
ds.errors = true;
@ -6319,7 +5791,7 @@ private extern(C++) class AddMemberVisitor : Visitor
}
else
{
if (findCondition(m.versionidsNot, vs.ident))
if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
{
.error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
vs.errors = true;

File diff suppressed because it is too large Load diff

View file

@ -52,8 +52,6 @@ public:
bool isDeprecated() const override; // is Dsymbol deprecated?
Visibility visible() override;
bool isSpecial() const;
Expression *getDefaultValue(const Loc &loc);
Type *getMemtype(const Loc &loc);
EnumDeclaration *isEnumDeclaration() override { return this; }

714
gcc/d/dmd/enumsem.d Normal file
View file

@ -0,0 +1,714 @@
/**
* Does the semantic passes on enums.
*
* Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/enumsem.d, _enumsem.d)
* Documentation: https://dlang.org/phobos/dmd_enumsem.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/enumsem.d
*/
module dmd.enumsem;
import core.stdc.stdio;
import core.stdc.string;
import dmd.aggregate;
import dmd.aliasthis;
import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
import dmd.attrib;
import dmd.blockexit;
import dmd.clone;
import dmd.cond;
import dmd.compiler;
import dmd.dcast;
import dmd.dclass;
import dmd.declaration;
import dmd.denum;
import dmd.dimport;
import dmd.dinterpret;
import dmd.dmangle;
import dmd.dmodule;
import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.dversion;
import dmd.errors;
import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.importc;
import dmd.init;
import dmd.initsem;
import dmd.intrange;
import dmd.hdrgen;
import dmd.location;
import dmd.mtype;
import dmd.mustuse;
import dmd.nogc;
import dmd.nspace;
import dmd.objc;
import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.root.array;
import dmd.root.filename;
import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.rootobject;
import dmd.root.utf;
import dmd.semantic2;
import dmd.semantic3;
import dmd.sideeffect;
import dmd.statementsem;
import dmd.staticassert;
import dmd.tokens;
import dmd.utils;
import dmd.statement;
import dmd.target;
import dmd.templateparamsem;
import dmd.typesem;
import dmd.visitor;
/*********************************
* Perform semantic analysis on enum declaration `em`
*/
void enumSemantic(Scope* sc, EnumDeclaration ed)
{
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
//printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
if (ed.semanticRun >= PASS.semanticdone)
return; // semantic() already completed
if (ed.semanticRun == PASS.semantic)
{
assert(ed.memtype);
error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
ed.errors = true;
ed.semanticRun = PASS.semanticdone;
return;
}
Scope* scx = null;
if (ed._scope)
{
sc = ed._scope;
scx = ed._scope; // save so we don't make redundant copies
ed._scope = null;
}
if (!sc)
return;
ed.parent = sc.parent;
ed.type = ed.type.typeSemantic(ed.loc, sc);
ed.visibility = sc.visibility;
if (sc.stc & STC.deprecated_)
ed.isdeprecated = true;
ed.userAttribDecl = sc.userAttribDecl;
ed.cppnamespace = sc.namespace;
ed.semanticRun = PASS.semantic;
UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
checkMustUseReserved(ed);
if (!ed.members && !ed.memtype) // enum ident;
{
ed.semanticRun = PASS.semanticdone;
return;
}
if (!ed.symtab)
ed.symtab = new DsymbolTable();
/* The separate, and distinct, cases are:
* 1. enum { ... }
* 2. enum : memtype { ... }
* 3. enum ident { ... }
* 4. enum ident : memtype { ... }
* 5. enum ident : memtype;
* 6. enum ident;
*/
if (ed.memtype)
{
ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
/* Check to see if memtype is forward referenced
*/
if (auto te = ed.memtype.isTypeEnum())
{
auto sym = te.toDsymbol(sc).isEnumDeclaration();
// Special enums like __c_[u]long[long] are fine to forward reference
// see https://issues.dlang.org/show_bug.cgi?id=20599
if (!sym.isSpecial() && (!sym.memtype || !sym.members || !sym.symtab || sym._scope))
{
// memtype is forward referenced, so try again later
deferDsymbolSemantic(sc, ed, scx);
//printf("\tdeferring %s\n", toChars());
ed.semanticRun = PASS.initial;
return;
}
else
// Ensure that semantic is run to detect. e.g. invalid forward references
sym.dsymbolSemantic(sc);
}
if (ed.memtype.ty == Tvoid)
{
.error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
ed.memtype = Type.terror;
}
if (ed.memtype.ty == Terror)
{
ed.errors = true;
// poison all the members
ed.members.foreachDsymbol( (s) { s.errors = true; } );
ed.semanticRun = PASS.semanticdone;
return;
}
}
if (!ed.members) // enum ident : memtype;
{
ed.semanticRun = PASS.semanticdone;
return;
}
if (ed.members.length == 0)
{
.error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
ed.errors = true;
ed.semanticRun = PASS.semanticdone;
return;
}
if (!(sc.flags & SCOPE.Cfile)) // C enum remains incomplete until members are done
ed.semanticRun = PASS.semanticdone;
version (none)
{
// @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.100
// Make an error in 2.110
if (sc.stc & STC.scope_)
deprecation(ed.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
}
Scope* sce;
if (ed.isAnonymous())
sce = sc;
else
{
sce = sc.push(ed);
sce.parent = ed;
}
sce = sce.startCTFE();
sce.setNoFree(); // needed for getMaxMinValue()
/* Each enum member gets the sce scope
*/
ed.members.foreachDsymbol( (s)
{
EnumMember em = s.isEnumMember();
if (em)
em._scope = sce;
});
/* addMember() is not called when the EnumDeclaration appears as a function statement,
* so we have to do what addMember() does and install the enum members in the right symbol
* table
*/
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
if (sc.flags & SCOPE.Cfile)
{
/* C11 6.7.2.2
*/
Type commonType = ed.memtype;
if (!commonType)
commonType = Type.tint32;
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
// C11 6.7.2.2-2 value must be representable as an int.
// The sizemask represents all values that int will fit into,
// from 0..uint.max. We want to cover int.min..uint.max.
IntRange ir = IntRange.fromType(commonType);
void emSemantic(EnumMember em, ref ulong nextValue)
{
static void errorReturn(EnumMember em)
{
em.value = ErrorExp.get();
em.errors = true;
em.semanticRun = PASS.semanticdone;
}
em.semanticRun = PASS.semantic;
em.type = commonType;
em._linkage = LINK.c;
em.storage_class |= STC.manifest;
if (em.value)
{
Expression e = em.value;
assert(e.dyncast() == DYNCAST.expression);
/* To merge the type of e with commonType, add 0 of type commonType
*/
if (!ed.memtype)
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
e = e.expressionSemantic(sc);
e = resolveProperties(sc, e);
e = e.integralPromotions(sc);
e = e.ctfeInterpret();
if (e.op == EXP.error)
return errorReturn(em);
auto ie = e.isIntegerExp();
if (!ie)
{
// C11 6.7.2.2-2
.error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
return errorReturn(em);
}
if (ed.memtype && !ir.contains(getIntRange(ie)))
{
// C11 6.7.2.2-2
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
return errorReturn(em);
}
nextValue = ie.toInteger();
if (!ed.memtype)
commonType = e.type;
em.value = new IntegerExp(em.loc, nextValue, commonType);
}
else
{
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
bool first = (em == (*em.ed.members)[0]);
if (!first)
{
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
if (nextValue == max.toInteger())
{
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
return errorReturn(em);
}
nextValue += 1;
}
em.value = new IntegerExp(em.loc, nextValue, commonType);
}
em.type = commonType;
em.semanticRun = PASS.semanticdone;
}
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
emSemantic(em, nextValue);
});
if (!ed.memtype)
{
// cast all members to commonType
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
{
em.type = commonType;
em.value = em.value.castTo(sc, commonType);
}
});
}
ed.memtype = commonType;
ed.semanticRun = PASS.semanticdone;
return;
}
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
em.dsymbolSemantic(em._scope);
});
//printf("ed.defaultval = %lld\n", ed.defaultval);
//if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars());
//printf("members = %s\n", members.toChars());
}
Expression getDefaultValue(EnumDeclaration ed, const ref Loc loc)
{
Expression handleErrors(){
ed.defaultval = ErrorExp.get();
return ed.defaultval;
}
//printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
// https://issues.dlang.org/show_bug.cgi?id=23904
// Return ed.defaultval only if it is not ErrorExp.
// A speculative context may set ed.defaultval to ErrorExp;
// subsequent non-speculative contexts need to be able
// to print the error.
if (ed.defaultval && !ed.defaultval.isErrorExp())
return ed.defaultval;
if (ed.isCsymbol())
return ed.memtype.defaultInit(loc, true);
if (ed._scope)
dsymbolSemantic(ed, ed._scope);
if (ed.errors)
return handleErrors();
if (!ed.members)
{
if (ed.isSpecial())
{
/* Allow these special enums to not need a member list
*/
return ed.defaultval = ed.memtype.defaultInit(loc);
}
error(loc, "%s `%s` is opaque and has no default initializer", ed.kind, ed.toPrettyChars);
return handleErrors();
}
foreach (const i; 0 .. ed.members.length)
{
EnumMember em = (*ed.members)[i].isEnumMember();
if (em)
{
if (em.semanticRun < PASS.semanticdone)
{
error(loc, "%s `%s` forward reference of `%s.init`", ed.kind, ed.toPrettyChars, ed.toChars());
return handleErrors();
}
ed.defaultval = em.value;
return ed.defaultval;
}
}
return handleErrors();
}
Type getMemtype(EnumDeclaration ed, const ref Loc loc)
{
if (ed._scope)
{
/* Enum is forward referenced. We don't need to resolve the whole thing,
* just the base type
*/
if (ed.memtype)
{
Loc locx = loc.isValid() ? loc : ed.loc;
ed.memtype = ed.memtype.typeSemantic(locx, ed._scope);
}
else
{
// Run semantic to get the type from a possible first member value
dsymbolSemantic(ed, ed._scope);
}
}
if (!ed.memtype)
{
if (!ed.isAnonymous() && (ed.members || ed.semanticRun >= PASS.semanticdone))
ed.memtype = Type.tint32;
else
{
Loc locx = loc.isValid() ? loc : ed.loc;
error(locx, "is forward referenced looking for base type");
return Type.terror;
}
}
return ed.memtype;
}
/*********************************
* Perform semantic analysis on enum member `em`
*/
void enumMemberSemantic(Scope* sc, EnumMember em)
{
//printf("EnumMember::semantic() %s\n", em.toChars());
void errorReturn()
{
em.errors = true;
em.semanticRun = PASS.semanticdone;
}
if (em.errors || em.semanticRun >= PASS.semanticdone)
return;
if (em.semanticRun == PASS.semantic)
{
.error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
return errorReturn();
}
assert(em.ed);
em.ed.dsymbolSemantic(sc);
if (em.ed.errors)
return errorReturn();
if (em.errors || em.semanticRun >= PASS.semanticdone)
return;
if (em._scope)
sc = em._scope;
if (!sc)
return;
em.semanticRun = PASS.semantic;
em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
em._linkage = LINK.d;
em.storage_class |= STC.manifest;
// https://issues.dlang.org/show_bug.cgi?id=9701
if (em.ed.isAnonymous())
{
if (em.userAttribDecl)
em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
else
em.userAttribDecl = em.ed.userAttribDecl;
}
// Eval UDA in this same scope. Issues 19344, 20835, 21122
if (em.userAttribDecl)
{
// Set scope but avoid extra sc.uda attachment inside setScope()
auto inneruda = em.userAttribDecl.userAttribDecl;
em.userAttribDecl.setScope(sc);
em.userAttribDecl.userAttribDecl = inneruda;
em.userAttribDecl.dsymbolSemantic(sc);
}
// The first enum member is special
bool first = (em == (*em.ed.members)[0]);
if (em.origType)
{
em.origType = em.origType.typeSemantic(em.loc, sc);
em.type = em.origType;
assert(em.value); // "type id;" is not a valid enum member declaration
}
if (em.value)
{
Expression e = em.value;
assert(e.dyncast() == DYNCAST.expression);
e = e.expressionSemantic(sc);
e = resolveProperties(sc, e);
e = e.ctfeInterpret();
if (e.op == EXP.error)
return errorReturn();
if (first && !em.ed.memtype && !em.ed.isAnonymous())
{
em.ed.memtype = e.type;
if (em.ed.memtype.ty == Terror)
{
em.ed.errors = true;
return errorReturn();
}
if (em.ed.memtype.ty != Terror)
{
/* https://issues.dlang.org/show_bug.cgi?id=11746
* All of named enum members should have same type
* with the first member. If the following members were referenced
* during the first member semantic, their types should be unified.
*/
em.ed.members.foreachDsymbol( (s)
{
EnumMember enm = s.isEnumMember();
if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
return;
//printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
Expression ev = enm.value;
ev = ev.implicitCastTo(sc, em.ed.memtype);
ev = ev.ctfeInterpret();
ev = ev.castTo(sc, em.ed.type);
if (ev.op == EXP.error)
em.ed.errors = true;
enm.value = ev;
});
if (em.ed.errors)
{
em.ed.memtype = Type.terror;
return errorReturn();
}
}
}
if (em.ed.memtype && !em.origType)
{
e = e.implicitCastTo(sc, em.ed.memtype);
e = e.ctfeInterpret();
// save origValue for better json output
em.origValue = e;
if (!em.ed.isAnonymous())
{
e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
e = e.ctfeInterpret();
}
}
else if (em.origType)
{
e = e.implicitCastTo(sc, em.origType);
e = e.ctfeInterpret();
assert(em.ed.isAnonymous());
// save origValue for better json output
em.origValue = e;
}
em.value = e;
}
else if (first)
{
Type t;
if (em.ed.memtype)
t = em.ed.memtype;
else
{
t = Type.tint32;
if (!em.ed.isAnonymous())
em.ed.memtype = t;
}
const errors = global.startGagging();
Expression e = new IntegerExp(em.loc, 0, t);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
t.toChars(), em.toChars());
}
// save origValue for better json output
em.origValue = e;
if (!em.ed.isAnonymous())
{
e = e.castTo(sc, em.ed.type);
e = e.ctfeInterpret();
}
em.value = e;
}
else
{
/* Find the previous enum member,
* and set this to be the previous value + 1
*/
EnumMember emprev = null;
em.ed.members.foreachDsymbol( (s)
{
if (auto enm = s.isEnumMember())
{
if (enm == em)
return 1; // found
emprev = enm;
}
return 0; // continue
});
assert(emprev);
if (emprev.semanticRun < PASS.semanticdone) // if forward reference
emprev.dsymbolSemantic(emprev._scope); // resolve it
if (emprev.errors)
return errorReturn();
auto errors = global.startGagging();
Expression eprev = emprev.value;
assert(eprev);
// .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
? em.ed.memtype
: eprev.type;
/*
https://issues.dlang.org/show_bug.cgi?id=20777
Previously this used getProperty, which doesn't consider anything user defined,
this construct does do that and thus fixes the bug.
*/
Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
emax = emax.expressionSemantic(sc);
emax = emax.ctfeInterpret();
// check that (eprev != emax)
Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
e = e.expressionSemantic(sc);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
// display an introductory error before showing what actually failed
error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
// rerun to show errors
Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
e2 = e2.expressionSemantic(sc);
e2 = e2.ctfeInterpret();
e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
e2 = e2.expressionSemantic(sc);
e2 = e2.ctfeInterpret();
}
// now any errors are for generating a value
if (e.toInteger())
{
auto mt = em.ed.memtype;
if (!mt)
mt = eprev.type;
.error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
emprev.ed.toChars(), emprev.toChars(), mt.toChars());
return errorReturn();
}
errors = global.startGagging();
// Now set e to (eprev + 1)
e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
e = e.expressionSemantic(sc);
e = e.castTo(sc, eprev.type);
e = e.ctfeInterpret();
if (global.endGagging(errors))
{
error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
// rerun to show errors
Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
e2 = e2.expressionSemantic(sc);
e2 = e2.castTo(sc, eprev.type);
e2 = e2.ctfeInterpret();
}
// save origValue (without cast) for better json output
if (e.op != EXP.error) // avoid duplicate diagnostics
{
assert(emprev.origValue);
em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
em.origValue = em.origValue.expressionSemantic(sc);
em.origValue = em.origValue.ctfeInterpret();
}
if (e.op == EXP.error)
return errorReturn();
if (e.type.isfloating())
{
// Check that e != eprev (not always true for floats)
Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
etest = etest.expressionSemantic(sc);
etest = etest.ctfeInterpret();
if (etest.toInteger())
{
.error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
return errorReturn();
}
}
em.value = e;
}
if (!em.origType)
em.type = em.value.type;
assert(em.origValue);
em.semanticRun = PASS.semanticdone;
}

View file

@ -721,6 +721,7 @@ extern (C++) abstract class Expression : ASTNode
inout(SuperExp) isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
inout(NullExp) isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
inout(StringExp) isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
inout(InterpExp) isInterpExp() { return op == EXP.interpolated ? cast(typeof(return))this : null; }
inout(TupleExp) isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
@ -1499,6 +1500,7 @@ extern (C++) final class StringExp : Expression
char* string; // if sz == 1
wchar* wstring; // if sz == 2
dchar* dstring; // if sz == 4
ulong* lstring; // if sz == 8
} // (const if ownedByCtfe == OwnedBy.code)
size_t len; // number of code units
ubyte sz = 1; // 1: char, 2: wchar, 4: dchar
@ -1661,6 +1663,13 @@ extern (C++) final class StringExp : Expression
* code unit at index i
*/
dchar getCodeUnit(size_t i) const pure
{
assert(this.sz <= dchar.sizeof);
return cast(dchar) getIndex(i);
}
/// Returns: integer at index `i`
dinteger_t getIndex(size_t i) const pure
{
assert(i < len);
final switch (sz)
@ -1671,6 +1680,8 @@ extern (C++) final class StringExp : Expression
return wstring[i];
case 4:
return dstring[i];
case 8:
return lstring[i];
}
}
@ -1681,6 +1692,11 @@ extern (C++) final class StringExp : Expression
* c = code unit to set it to
*/
extern (D) void setCodeUnit(size_t i, dchar c)
{
return setIndex(i, c);
}
extern (D) void setIndex(size_t i, long c)
{
assert(i < len);
final switch (sz)
@ -1692,7 +1708,10 @@ extern (C++) final class StringExp : Expression
wstring[i] = cast(wchar)c;
break;
case 4:
dstring[i] = c;
dstring[i] = cast(dchar) c;
break;
case 8:
lstring[i] = c;
break;
}
}
@ -1847,6 +1866,28 @@ extern (C++) final class StringExp : Expression
}
}
extern (C++) final class InterpExp : Expression
{
char postfix = NoPostfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe = OwnedBy.code;
InterpolatedSet* interpolatedSet;
enum char NoPostfix = 0;
extern (D) this(const ref Loc loc, InterpolatedSet* set, char postfix = NoPostfix) scope
{
super(loc, EXP.interpolated);
this.interpolatedSet = set;
this.postfix = postfix;
}
override void accept(Visitor v)
{
v.visit(this);
}
}
/***********************************************************
* A sequence of expressions
*
@ -5494,6 +5535,7 @@ private immutable ubyte[EXP.max+1] expSize = [
EXP.preMinusMinus: __traits(classInstanceSize, PreExp),
EXP.identifier: __traits(classInstanceSize, IdentifierExp),
EXP.string_: __traits(classInstanceSize, StringExp),
EXP.interpolated: __traits(classInstanceSize, InterpExp),
EXP.this_: __traits(classInstanceSize, ThisExp),
EXP.super_: __traits(classInstanceSize, SuperExp),
EXP.halt: __traits(classInstanceSize, HaltExp),

View file

@ -38,6 +38,7 @@ class TemplateDeclaration;
class ClassDeclaration;
class OverloadSet;
class StringExp;
class InterpExp;
class LoweredAssignExp;
#ifdef IN_GCC
typedef union tree_node Symbol;
@ -129,6 +130,7 @@ public:
SuperExp* isSuperExp();
NullExp* isNullExp();
StringExp* isStringExp();
InterpExp* isInterpExp();
TupleExp* isTupleExp();
ArrayLiteralExp* isArrayLiteralExp();
AssocArrayLiteralExp* isAssocArrayLiteralExp();
@ -352,7 +354,7 @@ class StringExp final : public Expression
public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
void *string; // char, wchar, or dchar data
void *string; // char, wchar, dchar, or long data
size_t len; // number of chars, wchars, or dchars
unsigned char sz; // 1: char, 2: wchar, 4: dchar
d_bool committed; // if type is committed
@ -362,6 +364,7 @@ public:
static StringExp *create(const Loc &loc, const void *s, d_size_t len);
bool equals(const RootObject * const o) const override;
char32_t getCodeUnit(d_size_t i) const;
dinteger_t getIndex(d_size_t i) const;
StringExp *toStringExp() override;
Optional<bool> toBool() override;
bool isLvalue() override;
@ -370,6 +373,16 @@ public:
void writeTo(void* dest, bool zero, int tyto = 0) const;
};
class InterpExp final : public Expression
{
public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
void* interpolatedSet;
void accept(Visitor* v) override { v->visit(this); }
};
// Tuple
class TupleExp final : public Expression

View file

@ -42,10 +42,12 @@ import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.errorsink;
import dmd.enumsem;
import dmd.escape;
import dmd.expression;
import dmd.file_manager;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -1579,7 +1581,7 @@ Lagain:
if (auto f = s.isFuncDeclaration())
{
f = f.toAliasFunc();
if (!f.functionSemantic())
if (!functionSemantic(f))
return ErrorExp.get();
if (!hasOverloads && f.checkForwardRef(loc))
@ -2866,7 +2868,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
// If inferring return type, and semantic3() needs to be run if not already run
if (!tf.next && fd.inferRetType)
{
fd.functionSemantic();
functionSemantic(fd);
}
else if (fd && fd.parent)
{
@ -4145,6 +4147,84 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
}
override void visit(InterpExp e)
{
// the lexer breaks up into an odd/even array of literals and expression code
// we need to turn that into:
/+
tuple(
.object.imported!"core.interpolation".InterpolationHeader(),
...
.object.imported!"core.interpolation".InterpolationFooter()
)
There the ... loops through them all, making the even ones
.object.imported!"core.interpolation".InterpolatedLiteral!str()
and making the odd ones
.object.imported!"core.interpolation".InterpolatedExpression!str(),
the code represented by str
Empty string literals are skipped as they provide no additional information.
+/
if (e.postfix)
error(e.loc, "String postfixes on interpolated expression sequences are not allowed.");
Expression makeNonTemplateItem(Identifier which) {
Expression id = new IdentifierExp(e.loc, Id.empty);
id = new DotIdExp(e.loc, id, Id.object);
auto moduleNameArgs = new Objects();
moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
id = new DotIdExp(e.loc, id, which);
id = new CallExp(e.loc, id, new Expressions());
return id;
}
Expression makeTemplateItem(Identifier which, string arg) {
Expression id = new IdentifierExp(e.loc, Id.empty);
id = new DotIdExp(e.loc, id, Id.object);
auto moduleNameArgs = new Objects();
moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
auto tiargs = new Objects();
auto templateStringArg = new StringExp(e.loc, arg);
// banning those instead of forwarding them
// templateStringArg.postfix = e.postfix; // forward the postfix to these literals
tiargs.push(templateStringArg);
id = new DotTemplateInstanceExp(e.loc, id, which, tiargs);
id = new CallExp(e.loc, id, new Expressions());
return id;
}
auto arguments = new Expressions();
arguments.push(makeNonTemplateItem(Id.InterpolationHeader));
foreach (idx, str; e.interpolatedSet.parts)
{
if (idx % 2 == 0)
{
if (str.length > 0)
arguments.push(makeTemplateItem(Id.InterpolatedLiteral, str));
}
else
{
arguments.push(makeTemplateItem(Id.InterpolatedExpression, str));
Expressions* mix = new Expressions();
mix.push(new StringExp(e.loc, str));
// FIXME: i'd rather not use MixinExp but idk how to do it lol
arguments.push(new MixinExp(e.loc, mix));
}
}
arguments.push(makeNonTemplateItem(Id.InterpolationFooter));
auto loweredTo = new TupleExp(e.loc, arguments);
visit(loweredTo);
result = loweredTo;
}
override void visit(StringExp e)
{
static if (LOGSEMANTIC)
@ -5366,7 +5446,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (fd)
{
//printf("L%d fd = %s\n", __LINE__, f.toChars());
if (!fd.functionSemantic())
if (!functionSemantic(fd))
return setError();
}
@ -6564,10 +6644,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
.errorSupplemental(exp.loc, "the following error occured while looking for a UFCS match");
}
.error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
.error(exp.loc, "%s `%s` is not callable using argument types `%s`",
exp.f.kind(), exp.f.toChars(), buf.peekChars());
if (failMessage)
errorSupplemental(exp.loc, "%s", failMessage);
.errorSupplemental(exp.f.loc, "`%s%s` declared here", exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList));
exp.f = null;
}
@ -7549,7 +7630,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
se = se.toUTF8(sc);
auto namez = se.toStringz();
if (!global.filePath)
if (!global.filePath.length)
{
error(e.loc, "need `-J` switch to import text file `%s`", namez.ptr);
return setError();
@ -7580,12 +7661,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
auto resolvedNamez = FileName.searchPath(global.filePath[], namez, false);
if (!resolvedNamez)
{
error(e.loc, "file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
errorSupplemental(e.loc, "Path(s) searched (as provided by `-J`):");
foreach (idx, path; *global.filePath)
foreach (idx, path; global.filePath[])
{
const attr = FileName.exists(path);
const(char)* err = attr == 2 ? "" :
@ -8170,7 +8251,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (FuncDeclaration fd = exp.var.isFuncDeclaration())
{
// for functions, do checks after overload resolution
if (!fd.functionSemantic())
if (!functionSemantic(fd))
return setError();
/* https://issues.dlang.org/show_bug.cgi?id=13843
@ -8937,7 +9018,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
bool err = false;
if (cd.dtor)
{
err |= !cd.dtor.functionSemantic();
err |= !functionSemantic(cd.dtor);
err |= cd.dtor.checkPurity(exp.loc, sc);
err |= cd.dtor.checkSafety(exp.loc, sc);
err |= cd.dtor.checkNogc(exp.loc, sc);
@ -14356,7 +14437,7 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
if (auto f = s.isFuncDeclaration())
{
//printf("it's a function\n");
if (!f.functionSemantic())
if (!functionSemantic(f))
return ErrorExp.get();
Expression e;
if (f.needThis())

View file

@ -39,6 +39,7 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.escape;
import dmd.expression;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -466,103 +467,13 @@ extern (C++) class FuncDeclaration : Declaration
return f;
}
/****************************************************
* Resolve forward reference of function signature -
* parameter types, return type, and attributes.
* Returns:
* false if any errors exist in the signature.
*/
final bool functionSemantic()
{
//printf("functionSemantic() %p %s\n", this, toChars());
if (!_scope)
return !errors;
this.cppnamespace = _scope.namespace;
if (!originalType) // semantic not yet run
{
TemplateInstance spec = isSpeculative();
uint olderrs = global.errors;
uint oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
dsymbolSemantic(this, _scope);
global.gag = oldgag;
if (spec && global.errors != olderrs)
spec.errors = (global.errors - olderrs != 0);
if (olderrs != global.errors) // if errors compiling this function
return false;
}
// if inferring return type, sematic3 needs to be run
// - When the function body contains any errors, we cannot assume
// the inferred return type is valid.
// So, the body errors should become the function signature error.
if (inferRetType && type && !type.nextOf())
return functionSemantic3();
TemplateInstance ti;
if (isInstantiated() && !isVirtualMethod() &&
((ti = parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == ident))
{
AggregateDeclaration ad = isMemberLocal();
if (ad && ad.sizeok != Sizeok.done)
{
/* Currently dmd cannot resolve forward references per methods,
* then setting SIZOKfwd is too conservative and would break existing code.
* So, just stop method attributes inference until ad.dsymbolSemantic() done.
*/
//ad.sizeok = Sizeok.fwd;
}
else
return functionSemantic3() || !errors;
}
if (storage_class & STC.inference)
return functionSemantic3() || !errors;
return !errors;
}
/****************************************************
* Resolve forward reference of function body.
* Returns false if any errors exist in the body.
*/
final bool functionSemantic3()
{
if (semanticRun < PASS.semantic3 && _scope)
{
/* Forward reference - we need to run semantic3 on this function.
* If errors are gagged, and it's not part of a template instance,
* we need to temporarily ungag errors.
*/
TemplateInstance spec = isSpeculative();
uint olderrs = global.errors;
uint oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
semantic3(this, _scope);
global.gag = oldgag;
// If it is a speculatively-instantiated template, and errors occur,
// we need to mark the template as having errors.
if (spec && global.errors != olderrs)
spec.errors = (global.errors - olderrs != 0);
if (olderrs != global.errors) // if errors compiling this function
return false;
}
return !errors && !this.hasSemantic3Errors();
}
/****************************************************
* Check that this function type is properly resolved.
* If not, report "forward reference error" and return true.
*/
extern (D) final bool checkForwardRef(const ref Loc loc)
{
if (!functionSemantic())
if (!functionSemantic(this))
return true;
/* No deco means the functionSemantic() call could not resolve
@ -579,72 +490,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
// called from semantic3
/**
* Creates and returns the hidden parameters for this function declaration.
*
* Hidden parameters include the `this` parameter of a class, struct or
* nested function and the selector parameter for Objective-C methods.
*/
extern (D) final void declareThis(Scope* sc)
{
const bool dualCtx = (toParent2() != toParentLocal());
if (dualCtx)
this.hasDualContext = true;
auto ad = isThis();
if (!dualCtx && !ad && !isNested())
{
vthis = null;
objc.selectorParameter = null;
return;
}
Type addModStc(Type t)
{
return t.addMod(type.mod).addStorageClass(storage_class);
}
if (dualCtx || isNested())
{
/* The 'this' for a nested function is the link to the
* enclosing function's stack frame.
* Note that nested functions and member functions are disjoint.
*/
Type tthis = addModStc(dualCtx ?
Type.tvoidptr.sarrayOf(2).pointerTo() :
Type.tvoid.pointerTo());
vthis = new VarDeclaration(loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
vthis.storage_class |= STC.parameter | STC.nodtor;
}
else if (ad)
{
Type thandle = addModStc(ad.handleType());
vthis = new ThisDeclaration(loc, thandle);
vthis.storage_class |= STC.parameter;
if (thandle.ty == Tstruct)
{
vthis.storage_class |= STC.ref_;
}
}
if (auto tf = type.isTypeFunction())
{
if (tf.isreturn)
vthis.storage_class |= STC.return_;
if (tf.isScopeQual)
vthis.storage_class |= STC.scope_;
if (tf.isreturnscope)
vthis.storage_class |= STC.returnScope;
}
vthis.dsymbolSemantic(sc);
if (!sc.insert(vthis))
assert(0);
vthis.parent = this;
if (ad)
objc.selectorParameter = .objc.createSelectorParameter(this, sc);
}
override final bool equals(const RootObject o) const
{
if (this == o)
@ -1104,20 +949,24 @@ extern (C++) class FuncDeclaration : Declaration
}
/*************************************
* Determine partial specialization order of 'this' vs g.
* Determine partial specialization order of functions `f` vs `g`.
* This is very similar to TemplateDeclaration::leastAsSpecialized().
* Params:
* f = first function
* g = second function
* names = names of parameters
* Returns:
* match 'this' is at least as specialized as g
* 0 g is more specialized than 'this'
*/
final MATCH leastAsSpecialized(FuncDeclaration g, Identifiers* names)
static MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
{
enum LOG_LEASTAS = 0;
static if (LOG_LEASTAS)
{
import core.stdc.stdio : printf;
printf("%s.leastAsSpecialized(%s, %s)\n", toChars(), g.toChars(), names ? names.toChars() : "null");
printf("%s, %s\n", type.toChars(), g.type.toChars());
printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null");
printf("%s, %s\n", f.type.toChars(), g.type.toChars());
}
/* This works by calling g() with f()'s parameters, and
@ -1125,15 +974,15 @@ extern (C++) class FuncDeclaration : Declaration
* as g() is.
*/
TypeFunction tf = type.toTypeFunction();
TypeFunction tf = f.type.toTypeFunction();
TypeFunction tg = g.type.toTypeFunction();
/* If both functions have a 'this' pointer, and the mods are not
* the same and g's is not const, then this is less specialized.
*/
if (needThis() && g.needThis() && tf.mod != tg.mod)
if (f.needThis() && g.needThis() && tf.mod != tg.mod)
{
if (isCtorDeclaration())
if (f.isCtorDeclaration())
{
if (!MODimplicitConv(tg.mod, tf.mod))
return MATCH.nomatch;
@ -3037,7 +2886,7 @@ Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
// Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
// For the correct mangling,
// run attribute inference on inv if needed.
inv.functionSemantic();
functionSemantic(inv);
}
//e = new DsymbolExp(Loc.initial, inv);
@ -3316,7 +3165,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
if (m.count == 1) // exactly one match
{
if (!(flags & FuncResolveFlag.quiet))
m.lastf.functionSemantic();
functionSemantic(m.lastf);
return m.lastf;
}
if ((flags & FuncResolveFlag.overloadOnly) && !tthis && m.lastf.needThis())
@ -3386,12 +3235,18 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
// all of overloads are templates
if (td)
{
const(char)* msg = "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`";
if (!od && !td.overnext)
msg = "%s `%s.%s` is not callable using argument types `!(%s)%s`";
.error(loc, msg,
{
.error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
}
else
{
.error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
tiargsBuf.peekChars(), fargsBuf.peekChars());
}
if (!global.gag || global.params.v.showGaggedErrors)
printCandidates(loc, td, sc.isDeprecated());
@ -3574,7 +3429,11 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
if (!print)
return true;
const tmsg = td.toCharsNoConstraints();
OutBuffer buf;
HdrGenState hgs;
hgs.skipConstraints = true;
toCharsMaybeConstraints(td, buf, hgs);
const tmsg = buf.peekChars();
const cmsg = td.getConstraintEvalError(constraintsTip);
// add blank space if there are multiple candidates

219
gcc/d/dmd/funcsem.d Normal file
View file

@ -0,0 +1,219 @@
/**
* Does semantic analysis for functions.
*
* Specification: $(LINK2 https://dlang.org/spec/function.html, Functions)
*
* Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/funcsem.d, _funcsem.d)
* Documentation: https://dlang.org/phobos/dmd_funcsem.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/funcsem.d
*/
module dmd.funcsem;
import core.stdc.stdio;
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.blockexit;
import dmd.gluelayer;
import dmd.dcast;
import dmd.dclass;
import dmd.declaration;
import dmd.delegatize;
import dmd.dinterpret;
import dmd.dmodule;
import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.escape;
import dmd.expression;
import dmd.func;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.init;
import dmd.location;
import dmd.mtype;
import dmd.objc;
import dmd.root.aav;
import dmd.common.outbuffer;
import dmd.rootobject;
import dmd.root.string;
import dmd.root.stringtable;
import dmd.semantic2;
import dmd.semantic3;
import dmd.statement_rewrite_walker;
import dmd.statement;
import dmd.statementsem;
import dmd.tokens;
import dmd.visitor;
/****************************************************
* Resolve forward reference of function signature -
* parameter types, return type, and attributes.
* Params:
* fd = function declaration
* Returns:
* false if any errors exist in the signature.
*/
public
extern (C++)
bool functionSemantic(FuncDeclaration fd)
{
//printf("functionSemantic() %p %s\n", this, toChars());
if (!fd._scope)
return !fd.errors;
fd.cppnamespace = fd._scope.namespace;
if (!fd.originalType) // semantic not yet run
{
TemplateInstance spec = fd.isSpeculative();
uint olderrs = global.errors;
uint oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
dsymbolSemantic(fd, fd._scope);
global.gag = oldgag;
if (spec && global.errors != olderrs)
spec.errors = (global.errors - olderrs != 0);
if (olderrs != global.errors) // if errors compiling this function
return false;
}
// if inferring return type, sematic3 needs to be run
// - When the function body contains any errors, we cannot assume
// the inferred return type is valid.
// So, the body errors should become the function signature error.
if (fd.inferRetType && fd.type && !fd.type.nextOf())
return fd.functionSemantic3();
TemplateInstance ti;
if (fd.isInstantiated() && !fd.isVirtualMethod() &&
((ti = fd.parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == fd.ident))
{
AggregateDeclaration ad = fd.isMemberLocal();
if (ad && ad.sizeok != Sizeok.done)
{
/* Currently dmd cannot resolve forward references per methods,
* then setting SIZOKfwd is too conservative and would break existing code.
* So, just stop method attributes inference until ad.dsymbolSemantic() done.
*/
//ad.sizeok = Sizeok.fwd;
}
else
return fd.functionSemantic3() || !fd.errors;
}
if (fd.storage_class & STC.inference)
return fd.functionSemantic3() || !fd.errors;
return !fd.errors;
}
/****************************************************
* Resolve forward reference of function body.
* Returns false if any errors exist in the body.
*/
public
extern (C++)
bool functionSemantic3(FuncDeclaration fd)
{
if (fd.semanticRun < PASS.semantic3 && fd._scope)
{
/* Forward reference - we need to run semantic3 on this function.
* If errors are gagged, and it's not part of a template instance,
* we need to temporarily ungag errors.
*/
TemplateInstance spec = fd.isSpeculative();
uint olderrs = global.errors;
uint oldgag = global.gag;
if (global.gag && !spec)
global.gag = 0;
semantic3(fd, fd._scope);
global.gag = oldgag;
// If it is a speculatively-instantiated template, and errors occur,
// we need to mark the template as having errors.
if (spec && global.errors != olderrs)
spec.errors = (global.errors - olderrs != 0);
if (olderrs != global.errors) // if errors compiling this function
return false;
}
return !fd.errors && !fd.hasSemantic3Errors();
}
// called from semantic3
/**
* Creates and returns the hidden parameters for this function declaration.
*
* Hidden parameters include the `this` parameter of a class, struct or
* nested function and the selector parameter for Objective-C methods.
*/
extern (D) void declareThis(FuncDeclaration fd, Scope* sc)
{
const bool dualCtx = (fd.toParent2() != fd.toParentLocal());
if (dualCtx)
fd.hasDualContext = true;
auto ad = fd.isThis();
if (!dualCtx && !ad && !fd.isNested())
{
fd.vthis = null;
fd.objc.selectorParameter = null;
return;
}
Type addModStc(Type t)
{
return t.addMod(fd.type.mod).addStorageClass(fd.storage_class);
}
if (dualCtx || fd.isNested())
{
/* The 'this' for a nested function is the link to the
* enclosing function's stack frame.
* Note that nested functions and member functions are disjoint.
*/
Type tthis = addModStc(dualCtx ?
Type.tvoidptr.sarrayOf(2).pointerTo() :
Type.tvoid.pointerTo());
fd.vthis = new VarDeclaration(fd.loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
fd.vthis.storage_class |= STC.parameter | STC.nodtor;
}
else if (ad)
{
Type thandle = addModStc(ad.handleType());
fd.vthis = new ThisDeclaration(fd.loc, thandle);
fd.vthis.storage_class |= STC.parameter;
if (thandle.ty == Tstruct)
{
fd.vthis.storage_class |= STC.ref_;
}
}
if (auto tf = fd.type.isTypeFunction())
{
if (tf.isreturn)
fd.vthis.storage_class |= STC.return_;
if (tf.isScopeQual)
fd.vthis.storage_class |= STC.scope_;
if (tf.isreturnscope)
fd.vthis.storage_class |= STC.returnScope;
}
fd.vthis.dsymbolSemantic(sc);
if (!sc.insert(fd.vthis))
assert(0);
fd.vthis.parent = fd;
if (ad)
fd.objc.selectorParameter = .objc.createSelectorParameter(fd, sc);
}

View file

@ -219,8 +219,8 @@ extern (C++) struct Param
const(char)[] argv0; // program name
Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
Array!(const(char)*)* imppath; // array of char*'s of where to look for import modules
Array!(const(char)*)* fileImppath; // array of char*'s of where to look for file import modules
Array!(const(char)*) imppath; // array of char*'s of where to look for import modules
Array!(const(char)*) fileImppath; // array of char*'s of where to look for file import modules
const(char)[] objdir; // .obj/.lib file output directory
const(char)[] objname; // .obj file output name
const(char)[] libname; // .lib file output name
@ -280,8 +280,8 @@ extern (C++) struct Global
string copyright = "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved";
string written = "written by Walter Bright";
Array!(const(char)*)* path; /// Array of char*'s which form the import lookup path
Array!(const(char)*)* filePath; /// Array of char*'s which form the file import lookup path
Array!(const(char)*) path; /// Array of char*'s which form the import lookup path
Array!(const(char)*) filePath; /// Array of char*'s which form the file import lookup path
private enum string _version = import("VERSION");
char[26] datetime; /// string returned by ctime()
@ -296,8 +296,8 @@ extern (C++) struct Global
void* console; /// opaque pointer to console for controlling text attributes
Array!Identifier* versionids; /// command line versions and predefined versions
Array!Identifier* debugids; /// command line debug versions and predefined versions
Array!Identifier versionids; /// command line versions and predefined versions
Array!Identifier debugids; /// command line debug versions and predefined versions
bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
uint varSequenceNumber = 1; /// Relative lifetime of `VarDeclaration` within a function, used for `scope` checks

View file

@ -202,8 +202,8 @@ struct Param
DString argv0; // program name
Array<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
Array<const char *> *imppath; // array of char*'s of where to look for import modules
Array<const char *> *fileImppath; // array of char*'s of where to look for file import modules
Array<const char *> imppath; // array of char*'s of where to look for import modules
Array<const char *> fileImppath; // array of char*'s of where to look for file import modules
DString objdir; // .obj/.lib file output directory
DString objname; // .obj file output name
DString libname; // .lib file output name
@ -282,8 +282,8 @@ struct Global
const DString copyright;
const DString written;
Array<const char *> *path; // Array of char*'s which form the import lookup path
Array<const char *> *filePath; // Array of char*'s which form the file import lookup path
Array<const char *> path; // Array of char*'s which form the import lookup path
Array<const char *> filePath; // Array of char*'s which form the file import lookup path
char datetime[26]; /// string returned by ctime()
CompileEnv compileEnv;
@ -297,8 +297,8 @@ struct Global
void* console; // opaque pointer to console for controlling text attributes
Array<class Identifier*>* versionids; // command line versions and predefined versions
Array<class Identifier*>* debugids; // command line debug versions and predefined versions
Array<class Identifier*> versionids; // command line versions and predefined versions
Array<class Identifier*> debugids; // command line debug versions and predefined versions
d_bool hasMainFunction;
unsigned varSequenceNumber;

View file

@ -60,6 +60,7 @@ struct HdrGenState
bool importcHdr; /// true if generating a .di file from an ImportC file
bool doFuncBodies; /// include function bodies in output
bool vcg_ast; /// write out codegen-ast
bool skipConstraints; // skip constraints when doing templates
bool fullQual; /// fully qualify types when printing
int tpltMember;
@ -1957,6 +1958,47 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
s.accept(v);
}
// Note: this function is not actually `const`, because iterating the
// function parameter list may run dsymbolsemantic on enum types
public
void toCharsMaybeConstraints(const TemplateDeclaration td, ref OutBuffer buf, ref HdrGenState hgs)
{
buf.writestring(td.ident == Id.ctor ? "this" : td.ident.toString());
buf.writeByte('(');
foreach (i, const tp; *td.parameters)
{
if (i)
buf.writestring(", ");
toCBuffer(tp, buf, hgs);
}
buf.writeByte(')');
if (td.onemember)
{
if (const fd = td.onemember.isFuncDeclaration())
{
if (TypeFunction tf = cast(TypeFunction)fd.type.isTypeFunction())
{
// !! Casted away const
buf.writestring(parametersTypeToChars(tf.parameterList));
if (tf.mod)
{
buf.writeByte(' ');
buf.MODtoBuffer(tf.mod);
}
}
}
}
if (!hgs.skipConstraints &&
td.constraint)
{
buf.writestring(" if (");
toCBuffer(td.constraint, buf, hgs);
buf.writeByte(')');
}
}
/*****************************************
* Pretty-print a template parameter list to a buffer.
@ -2234,6 +2276,16 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
void visitString(StringExp e)
{
if (e.hexString || e.sz == 8)
{
buf.writeByte('x');
buf.writeByte('"');
buf.writeHexString(e.peekData, true);
buf.writeByte('"');
if (e.postfix)
buf.writeByte(e.postfix);
return;
}
buf.writeByte('"');
const o = buf.length;
foreach (i; 0 .. e.len)
@ -2247,6 +2299,37 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
buf.writeByte(e.postfix);
}
void visitInterpolation(InterpExp e)
{
buf.writeByte('i');
buf.writeByte('"');
const o = buf.length;
foreach (idx, str; e.interpolatedSet.parts)
{
if (idx % 2 == 0)
{
foreach(ch; str)
writeCharLiteral(buf, ch);
}
else
{
buf.writeByte('$');
buf.writeByte('(');
foreach(ch; str)
buf.writeByte(ch);
buf.writeByte(')');
}
}
if (hgs.ddoc)
escapeDdocString(buf, o);
buf.writeByte('"');
if (e.postfix)
buf.writeByte(e.postfix);
}
void visitArrayLiteral(ArrayLiteralExp e)
{
buf.writeByte('[');
@ -2827,6 +2910,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
case EXP.super_: return visitSuper(e.isSuperExp());
case EXP.null_: return visitNull(e.isNullExp());
case EXP.string_: return visitString(e.isStringExp());
case EXP.interpolated: return visitInterpolation(e.isInterpExp());
case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());

View file

@ -335,6 +335,12 @@ immutable Msgtable[] msgtable =
{ "_d_arrayassign_l" },
{ "_d_arrayassign_r" },
{ "imported" },
{ "InterpolationHeader" },
{ "InterpolationFooter" },
{ "InterpolatedLiteral" },
{ "InterpolatedExpression" },
// For pragma's
{ "Pinline", "inline" },
{ "lib" },

View file

@ -873,12 +873,9 @@ public:
propertyStart("predefinedVersions");
arrayStart();
if (global.versionids)
foreach (const versionid; global.versionids)
{
foreach (const versionid; *global.versionids)
{
item(versionid.toString());
}
item(versionid.toString());
}
arrayEnd();
@ -905,12 +902,9 @@ public:
propertyStart("importPaths");
arrayStart();
if (global.params.imppath)
foreach (importPath; global.params.imppath[])
{
foreach (importPath; *global.params.imppath)
{
item(importPath.toDString);
}
item(importPath.toDString);
}
arrayEnd();

View file

@ -506,6 +506,29 @@ class Lexer
}
else
goto case_ident;
case 'i':
if (Ccompile)
goto case_ident;
if (p[1] == '"')
{
p++; // skip the i
escapeStringConstant(t, true);
return;
}
else if (p[1] == '`')
{
p++; // skip the i
wysiwygStringConstant(t, true);
return;
}
else if (p[1] == 'q' && p[2] == '{')
{
p += 2; // skip the i and q
tokenStringConstant(t, true);
return;
}
else
goto case_ident;
case '"':
escapeStringConstant(t);
return;
@ -517,7 +540,7 @@ class Lexer
case 'f':
case 'g':
case 'h':
case 'i':
/*case 'i':*/
case 'j':
case 'k':
case 'l':
@ -1429,9 +1452,18 @@ class Lexer
Params:
result = pointer to the token that accepts the result
*/
private void wysiwygStringConstant(Token* result)
private void wysiwygStringConstant(Token* result, bool supportInterpolation = false)
{
result.value = TOK.string_;
if (supportInterpolation)
{
result.value = TOK.interpolated;
result.interpolatedSet = null;
}
else
{
result.value = TOK.string_;
}
Loc start = loc();
auto terminator = p[0];
p++;
@ -1451,6 +1483,14 @@ class Lexer
c = '\n'; // treat EndOfLine as \n character
endOfLine();
break;
case '$':
if (!supportInterpolation)
goto default;
if (!handleInterpolatedSegment(result, start))
goto default;
continue;
case 0:
case 0x1A:
error("unterminated string constant starting at %s", start.toChars());
@ -1461,7 +1501,11 @@ class Lexer
default:
if (c == terminator)
{
result.setString(stringbuffer);
if (supportInterpolation)
result.appendInterpolatedPart(stringbuffer);
else
result.setString(stringbuffer);
stringPostfix(result);
return;
}
@ -1736,13 +1780,21 @@ class Lexer
Params:
result = pointer to the token that accepts the result
*/
private void tokenStringConstant(Token* result)
private void tokenStringConstant(Token* result, bool supportInterpolation = false)
{
result.value = TOK.string_;
if (supportInterpolation)
{
result.value = TOK.interpolated;
result.interpolatedSet = null;
}
else
{
result.value = TOK.string_;
}
uint nest = 1;
const start = loc();
const pstart = ++p;
auto pstart = ++p;
inTokenStringConstant++;
scope(exit) inTokenStringConstant--;
while (1)
@ -1757,10 +1809,28 @@ class Lexer
case TOK.rightCurly:
if (--nest == 0)
{
result.setString(pstart, p - 1 - pstart);
if (supportInterpolation)
result.appendInterpolatedPart(pstart, p - 1 - pstart);
else
result.setString(pstart, p - 1 - pstart);
stringPostfix(result);
return;
}
continue;
case TOK.dollar:
if (!supportInterpolation)
goto default;
stringbuffer.setsize(0);
stringbuffer.write(pstart, p - 1 - pstart);
if (!handleInterpolatedSegment(result, start))
goto default;
stringbuffer.setsize(0);
pstart = p;
continue;
case TOK.endOfFile:
error("unterminated token string constant starting at %s", start.toChars());
@ -1772,6 +1842,52 @@ class Lexer
}
}
// returns true if it got special treatment as an interpolated segment
// otherwise returns false, indicating to treat it as just part of a normal string
private bool handleInterpolatedSegment(Token* token, Loc start)
{
switch(*p)
{
case '(':
// expression, at this level we need to scan until the closing ')'
// always put the string part in first
token.appendInterpolatedPart(stringbuffer);
stringbuffer.setsize(0);
int openParenCount = 1;
p++; // skip the first open paren
auto pstart = p;
while (openParenCount > 0)
{
// need to scan with the lexer to support embedded strings and other complex cases
Token tok;
scan(&tok);
if (tok.value == TOK.leftParenthesis)
openParenCount++;
if (tok.value == TOK.rightParenthesis)
openParenCount--;
if (tok.value == TOK.endOfFile)
{
// FIXME: make this error better, it spams a lot
error("unterminated interpolated string constant starting at %s", start.toChars());
return false;
}
}
// then put the interpolated string segment
token.appendInterpolatedPart(pstart[0 .. p - 1 - pstart]);
stringbuffer.setsize(0); // make sure this is reset from the last token scan
// otherwise something like i"$(func("thing")) stuff" can still include it
return true;
default:
// nothing special
return false;
}
}
/**
Scan a quoted string while building the processed string value by
handling escape sequences. The result is returned in the given `t` token.
@ -1783,9 +1899,17 @@ class Lexer
* D https://dlang.org/spec/lex.html#double_quoted_strings
* ImportC C11 6.4.5
*/
private void escapeStringConstant(Token* t)
private void escapeStringConstant(Token* t, bool supportInterpolation = false)
{
t.value = TOK.string_;
if (supportInterpolation)
{
t.value = TOK.interpolated;
t.interpolatedSet = null;
}
else
{
t.value = TOK.string_;
}
const start = loc();
const tc = *p++; // opening quote
@ -1813,11 +1937,28 @@ class Lexer
c = escapeSequence(c2);
stringbuffer.writeUTF8(c);
continue;
case '$':
if (supportInterpolation)
{
p++; // skip escaped $
stringbuffer.writeByte('$');
continue;
}
else
goto default;
default:
c = escapeSequence(c2);
break;
}
break;
case '$':
if (!supportInterpolation)
goto default;
if (!handleInterpolatedSegment(t, start))
goto default;
continue;
case '\n':
endOfLine();
if (Ccompile)
@ -1835,7 +1976,10 @@ class Lexer
case '"':
if (c != tc)
goto default;
t.setString(stringbuffer);
if (supportInterpolation)
t.appendInterpolatedPart(stringbuffer);
else
t.setString(stringbuffer);
if (!Ccompile)
stringPostfix(t);
return;

View file

@ -27,9 +27,11 @@ import dmd.denum;
import dmd.dstruct;
import dmd.dsymbol;
import dmd.dtemplate;
import dmd.enumsem;
import dmd.errors;
import dmd.expression;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -516,16 +518,39 @@ extern (C++) abstract class Type : ASTNode
Terror
];
static Type merge(Type t)
{
import dmd.basicmangle : tyToDecoBuffer;
OutBuffer buf;
buf.reserve(3);
if (t.ty == Tnoreturn)
buf.writestring("Nn");
else
tyToDecoBuffer(buf, t.ty);
auto sv = t.stringtable.update(buf[]);
if (sv.value)
return sv.value;
else
{
t.deco = cast(char*)sv.toDchars();
sv.value = t;
return t;
}
}
for (size_t i = 0; basetab[i] != Terror; i++)
{
Type t = new TypeBasic(basetab[i]);
t = t.merge();
t = merge(t);
basic[basetab[i]] = t;
}
basic[Terror] = new TypeError();
tnoreturn = new TypeNoreturn();
tnoreturn.deco = tnoreturn.merge().deco;
tnoreturn.deco = merge(tnoreturn).deco;
basic[Tnoreturn] = tnoreturn;
tvoid = basic[Tvoid];
@ -560,7 +585,7 @@ extern (C++) abstract class Type : ASTNode
terror = basic[Terror];
tnoreturn = basic[Tnoreturn];
tnull = new TypeNull();
tnull.deco = tnull.merge().deco;
tnull.deco = merge(tnull).deco;
tvoidptr = tvoid.pointerTo();
tstring = tchar.immutableOf().arrayOf();
@ -601,29 +626,6 @@ extern (C++) abstract class Type : ASTNode
return cast(uint)size(Loc.initial);
}
/*************************************
* This version does a merge even if the deco is already computed.
* Necessary for types that have a deco, but are not merged.
*/
final Type merge2()
{
//printf("merge2(%s)\n", toChars());
Type t = this;
assert(t);
if (!t.deco)
return t.merge();
auto sv = stringtable.lookup(t.deco, strlen(t.deco));
if (sv && sv.value)
{
t = sv.value;
assert(t.deco);
}
else
assert(0);
return t;
}
/*********************************
* Store this type's modifier name into buf.
*/
@ -1693,7 +1695,7 @@ extern (C++) abstract class Type : ASTNode
if (callable)
{
auto fd = resolveFuncCall(Loc.initial, null, callable, null, this, ArgumentList(), FuncResolveFlag.quiet);
if (!fd || fd.errors || !fd.functionSemantic())
if (!fd || fd.errors || !functionSemantic(fd))
return Type.terror;
auto t = fd.type.nextOf();

View file

@ -233,7 +233,6 @@ public:
uinteger_t size();
virtual uinteger_t size(const Loc &loc);
virtual unsigned alignsize();
Type *merge2();
void modToBuffer(OutBuffer& buf) const;
char *modToChars() const;
@ -909,3 +908,4 @@ Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
bool isBaseOf(Type *tthis, Type *t, int *poffset);
Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
void purityLevel(TypeFunction *type);
Type *merge2(Type *type);

View file

@ -2015,6 +2015,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.string_:
case TOK.interpolated:
case TOK.hexadecimalString:
case TOK.file:
case TOK.fileFullPath:
@ -5820,6 +5821,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.true_:
case TOK.false_:
case TOK.string_:
case TOK.interpolated:
case TOK.hexadecimalString:
case TOK.leftParenthesis:
case TOK.cast_:
@ -7313,6 +7315,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.string_:
case TOK.interpolated:
case TOK.hexadecimalString:
case TOK.file:
case TOK.fileFullPath:
@ -8177,6 +8180,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
break;
case TOK.interpolated:
e = new AST.InterpExp(loc, token.interpolatedSet, token.postfix);
nextToken();
break;
case TOK.string_:
case TOK.hexadecimalString:
const bool hexString = token.value == TOK.hexadecimalString;
@ -8810,6 +8818,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.string_:
case TOK.interpolated:
case TOK.function_:
case TOK.delegate_:
case TOK.typeof_:

View file

@ -183,6 +183,7 @@ public:
void visit(AST.TypeidExp e) { visit(cast(AST.Expression)e); }
void visit(AST.TraitsExp e) { visit(cast(AST.Expression)e); }
void visit(AST.StringExp e) { visit(cast(AST.Expression)e); }
void visit(AST.InterpExp e) { visit(cast(AST.Expression)e); }
void visit(AST.NewExp e) { visit(cast(AST.Expression)e); }
void visit(AST.AssocArrayLiteralExp e) { visit(cast(AST.Expression)e); }
void visit(AST.ArrayLiteralExp e) { visit(cast(AST.Expression)e); }

View file

@ -70,7 +70,7 @@ D_CODE =
<div class="code_sample">
<div class="dlang">
<ol class="code_lines">
<li><code class="code">$0</code></li>
<li><pre><code class="code">$0</code></pre></li>
</ol>
</div>
</div>
@ -81,7 +81,7 @@ OTHER_CODE =
<div class="code_sample">
<div class="dlang">
<ol class="code_lines">
<li><code class="code language-$1">$+</code></li>
<li><pre><code class="code language-$1">$+</code></pre></li>
</ol>
</div>
</div>
@ -517,6 +517,10 @@ DDOC =
white-space: pre-wrap;
}
.ddoc .code_lines pre {
display: contents;
}
.ddoc .code_lines li:only-of-type::before {
color: rgba(255, 255, 255, 1);
content: " ";

View file

@ -78,7 +78,7 @@ nothrow:
private const(char)[] str;
///
extern (D) this(const(char)[] str) pure
extern (D) this(const char[] str) pure
{
this.str = str.xarraydup;
}
@ -96,7 +96,7 @@ nothrow:
}
/// Ditto
extern (D) static bool equals(const(char)[] name1, const(char)[] name2) pure @nogc
extern (D) static bool equals(const char[] name1, const char[] name2) pure @nogc
{
if (name1.length != name2.length)
return false;
@ -125,7 +125,7 @@ nothrow:
}
/// Ditto
extern (D) static bool absolute(const(char)[] name) pure @nogc @safe
extern (D) static bool absolute(const char[] name) pure @nogc @safe
{
if (!name.length)
return false;
@ -189,7 +189,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] ext(const(char)[] str) nothrow pure @safe @nogc
extern (D) static const(char)[] ext(const char[] str) nothrow pure @safe @nogc
{
foreach_reverse (idx, char e; str)
{
@ -249,7 +249,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] removeExt(const(char)[] str)
extern (D) static const(char)[] removeExt(const char[] str)
{
auto e = ext(str);
if (e.length)
@ -278,7 +278,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] name(const(char)[] str) pure @nogc @safe
extern (D) static const(char)[] name(const char[] str) pure @nogc @safe
{
foreach_reverse (idx, char e; str)
{
@ -333,7 +333,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] path(const(char)[] str)
extern (D) static const(char)[] path(const char[] str)
{
const n = name(str);
bool hasTrailingSlash;
@ -358,7 +358,7 @@ nothrow:
/**************************************
* Replace filename portion of path.
*/
extern (D) static const(char)[] replaceName(const(char)[] path, const(char)[] name)
extern (D) static const(char)[] replaceName(const char[] path, const char[] name)
{
if (absolute(name))
return name;
@ -387,7 +387,7 @@ nothrow:
}
/// Ditto
extern(D) static const(char)[] combine(const(char)[] path, const(char)[] name)
extern(D) static const(char)[] combine(const char[] path, const char[] name)
{
return !path.length ? name : buildPath(path, name);
}
@ -401,7 +401,7 @@ nothrow:
assert(combine("foo/"[], "bar"[]) == "foo/bar");
}
static const(char)[] buildPath(const(char)[][] fragments...)
static const(char)[] buildPath(const char[][] fragments...)
{
size_t size;
foreach (f; fragments)
@ -563,7 +563,7 @@ nothrow:
* Returns:
* A newly allocated string (free with `FileName.free`)
*/
extern(D) static char[] addExt(const(char)[] name, const(char)[] ext) pure
extern(D) static char[] addExt(const char[] name, const char[] ext) pure
{
const len = name.length + ext.length + 2;
auto s = cast(char*)mem.xmalloc(len);
@ -584,7 +584,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] defaultExt(const(char)[] name, const(char)[] ext)
extern (D) static const(char)[] defaultExt(const char[] name, const char[] ext)
{
auto e = FileName.ext(name);
if (e.length) // it already has an extension
@ -608,7 +608,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] forceExt(const(char)[] name, const(char)[] ext)
extern (D) static const(char)[] forceExt(const char[] name, const char[] ext)
{
if (auto e = FileName.ext(name))
return addExt(name[0 .. $ - e.length - 1], ext);
@ -630,7 +630,7 @@ nothrow:
}
/// Ditto
extern (D) static bool equalsExt(const(char)[] name, const(char)[] ext) pure @nogc
extern (D) static bool equalsExt(const char[] name, const char[] ext) pure @nogc
{
auto e = FileName.ext(name);
if (!e.length && !ext.length)
@ -665,12 +665,12 @@ nothrow:
* Returns:
* if found, filename combined with path, otherwise null
*/
extern (C++) static const(char)* searchPath(Strings* path, const(char)* name, bool cwd)
extern (C++) static const(char)* searchPath(const ref Strings path, const char* name, bool cwd)
{
return searchPath(path, name.toDString, cwd).ptr;
return searchPath(path[], name.toDString, cwd).ptr;
}
extern (D) static const(char)[] searchPath(Strings* path, const(char)[] name, bool cwd)
extern (D) static const(char)[] searchPath(const char*[] path, const char[] name, bool cwd)
{
if (absolute(name))
{
@ -681,24 +681,21 @@ nothrow:
if (exists(name))
return name;
}
if (path)
foreach (p; path)
{
foreach (p; *path)
auto n = combine(p.toDString, name);
if (exists(n))
return n;
//combine might return name
if (n.ptr != name.ptr)
{
auto n = combine(p.toDString, name);
if (exists(n))
return n;
//combine might return name
if (n.ptr != name.ptr)
{
mem.xfree(cast(void*)n.ptr);
}
mem.xfree(cast(void*)n.ptr);
}
}
return null;
}
extern (D) static const(char)[] searchPath(const(char)* path, const(char)[] name, bool cwd)
extern (D) static const(char)[] searchPath(const char* path, const char[] name, bool cwd)
{
if (absolute(name))
{
@ -738,7 +735,7 @@ nothrow:
* Returns:
* index of the first reserved character in path if found, size_t.max otherwise
*/
extern (D) static size_t findReservedChar(const(char)[] name) pure @nogc @safe
extern (D) static size_t findReservedChar(const char[] name) pure @nogc @safe
{
version (Windows)
{
@ -787,7 +784,7 @@ nothrow:
* Returns:
* true if path contains '..' reference to parent directory
*/
extern (D) static bool refersToParentDir(const(char)[] name) pure @nogc @safe
extern (D) static bool refersToParentDir(const char[] name) pure @nogc @safe
{
size_t s = 0;
foreach (i; 0 .. name.length)
@ -845,7 +842,7 @@ nothrow:
}
/// Ditto
extern (D) static int exists(const(char)[] name)
extern (D) static int exists(const char[] name)
{
if (!name.length)
return 0;
@ -892,7 +889,7 @@ nothrow:
Returns:
`true` if the directory exists or was successfully created
*/
extern (D) static bool ensurePathExists(const(char)[] path)
extern (D) static bool ensurePathExists(const char[] path)
{
//printf("FileName::ensurePathExists(%s)\n", path ? path : "");
if (!path.length)
@ -967,7 +964,7 @@ nothrow:
}
/// Ditto
extern (D) static const(char)[] canonicalName(const(char)[] name)
extern (D) static const(char)[] canonicalName(const char[] name)
{
version (Posix)
{
@ -1127,7 +1124,7 @@ version(Windows)
* References:
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx
*/
private int _mkdir(const(char)[] path) nothrow
private int _mkdir(const char[] path) nothrow
{
const createRet = path.extendedPathThen!(
p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
@ -1175,7 +1172,7 @@ version(Windows)
* Returns:
* The result of calling F on the UTF16 version of str.
*/
private auto toWStringzThen(alias F)(const(char)[] str) nothrow
private auto toWStringzThen(alias F)(const char[] str) nothrow
{
import dmd.common.smallbuffer : SmallBuffer, toWStringz;

View file

@ -38,7 +38,7 @@ public:
bool equalsExt(const char *ext);
static const char *searchPath(Strings *path, const char *name, bool cwd);
static const char *searchPath(Strings& path, const char *name, bool cwd);
static int exists(const char *name);
static bool ensurePathExists(const char *path);
static const char *canonicalName(const char *name);

View file

@ -41,6 +41,7 @@ import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@ -384,7 +385,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
}
funcdecl.declareThis(sc2);
declareThis(funcdecl, sc2);
// Reverts: https://issues.dlang.org/show_bug.cgi?id=5710
// No compiler supports this, and there was never any spec for it.

View file

@ -43,6 +43,7 @@ import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.gluelayer;
import dmd.hdrgen;
@ -1284,7 +1285,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
Type tfront;
if (auto fd = sfront.isFuncDeclaration())
{
if (!fd.functionSemantic())
if (!functionSemantic(fd))
return rangeError();
tfront = fd.type;
}

1497
gcc/d/dmd/templatesem.d Normal file

File diff suppressed because it is too large Load diff

View file

@ -124,6 +124,7 @@ enum TOK : ubyte
// Leaf operators
identifier,
string_,
interpolated,
hexadecimalString,
this_,
super_,
@ -380,6 +381,7 @@ enum EXP : ubyte
// Leaf operators
identifier,
string_,
interpolated,
this_,
super_,
halt,
@ -623,6 +625,10 @@ static immutable TOK[TOK.max + 1] Ckeywords =
}
} ();
struct InterpolatedSet {
// all strings in the parts are zero terminated at length+1
string[] parts;
}
/***********************************************************
*/
@ -645,7 +651,11 @@ extern (C++) struct Token
struct
{
const(char)* ustring; // UTF8 string
union
{
const(char)* ustring; // UTF8 string
InterpolatedSet* interpolatedSet;
}
uint len;
ubyte postfix; // 'c', 'w', 'd'
}
@ -833,6 +843,7 @@ extern (C++) struct Token
// For debugging
TOK.error: "error",
TOK.string_: "string",
TOK.interpolated: "interpolated string",
TOK.onScopeExit: "scope(exit)",
TOK.onScopeSuccess: "scope(success)",
TOK.onScopeFailure: "scope(failure)",
@ -910,6 +921,24 @@ nothrow:
return 0;
}
extern(D) void appendInterpolatedPart(const ref OutBuffer buf) {
appendInterpolatedPart(cast(const(char)*)buf[].ptr, buf.length);
}
extern(D) void appendInterpolatedPart(const(char)[] str) {
appendInterpolatedPart(str.ptr, str.length);
}
extern(D) void appendInterpolatedPart(const(char)* ptr, size_t length) {
assert(value == TOK.interpolated);
if (interpolatedSet is null)
interpolatedSet = new InterpolatedSet;
auto s = cast(char*)mem.xmalloc_noscan(length + 1);
memcpy(s, ptr, length);
s[length] = 0;
interpolatedSet.parts ~= cast(string) s[0 .. length];
}
/****
* Set to contents of ptr[0..length]
* Params:
@ -918,6 +947,7 @@ nothrow:
*/
void setString(const(char)* ptr, size_t length)
{
value = TOK.string_;
auto s = cast(char*)mem.xmalloc_noscan(length + 1);
memcpy(s, ptr, length);
s[length] = 0;
@ -941,6 +971,7 @@ nothrow:
*/
void setString()
{
value = TOK.string_;
ustring = "";
len = 0;
postfix = 0;

View file

@ -133,6 +133,7 @@ enum class TOK : unsigned char
// Leaf operators
identifier,
string_,
interpolated,
hexadecimalString,
this_,
super_,
@ -390,6 +391,7 @@ enum class EXP : unsigned char
// Leaf operators
identifier,
string_,
interpolated,
this_,
super_,
halt,
@ -461,7 +463,12 @@ struct Token
real_t floatvalue;
struct
{ utf8_t *ustring; // UTF8 string
{
union
{
utf8_t *ustring; // UTF8 string
void *interpolatedSet;
};
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};

View file

@ -36,6 +36,7 @@ import dmd.errorsink;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -1306,7 +1307,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
// attribute inference.
if (fd && fd.parent && fd.parent.isTemplateInstance)
{
fd.functionSemantic3();
functionSemantic3(fd);
tf = fd.type.isTypeFunction();
}

View file

@ -35,6 +35,7 @@ import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.enumsem;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
@ -2919,6 +2920,29 @@ extern (C++) Type merge(Type type)
return type;
}
/*************************************
* This version does a merge even if the deco is already computed.
* Necessary for types that have a deco, but are not merged.
*/
extern(C++) Type merge2(Type type)
{
//printf("merge2(%s)\n", toChars());
Type t = type;
assert(t);
if (!t.deco)
return t.merge();
auto sv = Type.stringtable.lookup(t.deco, strlen(t.deco));
if (sv && sv.value)
{
t = sv.value;
assert(t.deco);
}
else
assert(0);
return t;
}
/***************************************
* Calculate built-in properties which just the type is necessary.
*
@ -5697,7 +5721,7 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty)
* Returns:
* An enum value of either `Covariant.yes` or a reason it's not covariant.
*/
extern (C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
extern(C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
{
version (none)
{

View file

@ -65,6 +65,7 @@ extern (C++) bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope
fatal();
}
import dmd.typesem : merge2;
Type t = torig.merge2(); // do this since not all Type's are merge'd
bool needsCodegen = false;
if (!t.vtinfo)

View file

@ -195,6 +195,7 @@ class ThisExp;
class SuperExp;
class NullExp;
class StringExp;
class InterpExp;
class TupleExp;
class ArrayLiteralExp;
class AssocArrayLiteralExp;
@ -480,6 +481,7 @@ public:
virtual void visit(TypeidExp *e) { visit((Expression *)e); }
virtual void visit(TraitsExp *e) { visit((Expression *)e); }
virtual void visit(StringExp *e) { visit((Expression *)e); }
virtual void visit(InterpExp *e) { visit((Expression *)e); }
virtual void visit(NewExp *e) { visit((Expression *)e); }
virtual void visit(AssocArrayLiteralExp *e) { visit((Expression *)e); }
virtual void visit(ArrayLiteralExp *e) { visit((Expression *)e); }

View file

@ -2495,17 +2495,18 @@ public:
for (size_t i = 0; i < e->len; i++)
{
tree value = build_integer_cst (e->getCodeUnit (i), etype);
tree value = build_integer_cst (e->getIndex (i), etype);
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
tree ctor = build_constructor (type, elms);
TREE_CONSTANT (ctor) = 1;
this->result_ = ctor;
return;
}
else
{
/* Copy the string contents to a null terminated string. */
/* Copy the string contents to a null terminated STRING_CST. */
dinteger_t length = (e->len * e->sz);
char *string = XALLOCAVEC (char, length + e->sz);
memset (string, 0, length + e->sz);
@ -2514,7 +2515,18 @@ public:
/* String value and type includes the null terminator. */
tree value = build_string (length + e->sz, string);
TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
if (e->sz <= 4)
TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
else
{
/* Hexadecimal literal strings with an 8-byte character type are
just an alternative way to store an array of `ulong'.
Treat it as if it were a `uint[]' array instead. */
dinteger_t resize = e->sz / 4;
TREE_TYPE (value) = make_array_type (Type::tuns32,
(length * resize) + resize);
}
value = build_address (value);
if (tb->ty == TY::Tarray)

View file

@ -259,8 +259,9 @@ create_tinfo_types (Module *mod)
array_type_node, array_type_node, array_type_node,
array_type_node, ptr_type_node, ptr_type_node,
ptr_type_node, d_uint_type, ptr_type_node,
array_type_node, ptr_type_node, d_ulong_type,
d_ulong_type, ptr_type_node, NULL);
array_type_node, ptr_type_node, ptr_type_node,
d_uint_type, d_uint_type, d_uint_type, d_uint_type,
NULL);
object_module = mod;
}
@ -577,7 +578,7 @@ public:
void visit (TypeInfoConstDeclaration *d) final override
{
Type *tm = d->tinfo->mutableOf ();
tm = tm->merge2 ();
tm = merge2 (tm);
/* The vtable for TypeInfo_Const. */
this->layout_base (Type::typeinfoconst);
@ -594,7 +595,7 @@ public:
void visit (TypeInfoInvariantDeclaration *d) final override
{
Type *tm = d->tinfo->mutableOf ();
tm = tm->merge2 ();
tm = merge2 (tm);
/* The vtable for TypeInfo_Invariant. */
this->layout_base (Type::typeinfoinvariant);
@ -611,7 +612,7 @@ public:
void visit (TypeInfoSharedDeclaration *d) final override
{
Type *tm = d->tinfo->unSharedOf ();
tm = tm->merge2 ();
tm = merge2 (tm);
/* The vtable for TypeInfo_Shared. */
this->layout_base (Type::typeinfoshared);
@ -628,7 +629,7 @@ public:
void visit (TypeInfoWildDeclaration *d) final override
{
Type *tm = d->tinfo->mutableOf ();
tm = tm->merge2 ();
tm = merge2 (tm);
/* The vtable for TypeInfo_Inout. */
this->layout_base (Type::typeinfowild);
@ -934,10 +935,6 @@ public:
else
this->layout_field (null_pointer_node);
/* ulong[2] nameSig; */
this->layout_field (build_zero_cst (d_ulong_type));
this->layout_field (build_zero_cst (d_ulong_type));
/* immutable(void)* m_RTInfo; */
if (cd->getRTInfo)
this->layout_field (build_expr (cd->getRTInfo, true));
@ -945,6 +942,12 @@ public:
this->layout_field (size_one_node);
else
this->layout_field (null_pointer_node);
/* uint[4] nameSig; */
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
}
else
{
@ -985,15 +988,17 @@ public:
this->layout_field (null_array_node);
this->layout_field (null_pointer_node);
/* ulong[2] nameSig; */
this->layout_field (build_zero_cst (d_ulong_type));
this->layout_field (build_zero_cst (d_ulong_type));
/* immutable(void)* m_RTInfo; */
if (cd->getRTInfo)
this->layout_field (build_expr (cd->getRTInfo, true));
else
this->layout_field (null_pointer_node);
/* uint[4] nameSig; */
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
this->layout_field (build_zero_cst (d_uint_type));
}
/* Put out array of Interfaces. */
@ -1546,7 +1551,7 @@ create_typeinfo (Type *type, Module *mod, bool generate)
create_frontend_tinfo_types ();
/* Do this since not all Type's are merged. */
Type *t = type->merge2 ();
Type *t = merge2 (type);
Identifier *ident;
if (!t->vtinfo)

View file

@ -36,12 +36,27 @@ static assert((123 ).stringof == "123");
static assert((123u ).stringof == "123u");
static assert((123L ).stringof == "123L");
static assert((123uL).stringof == "123LU");
static assert((123.5 ).stringof == "1.235e+2");
static assert((123.5f ).stringof == "1.235e+2F");
static assert((123.5L ).stringof == "1.235e+2L");
static assert((123.5i ).stringof == "1.235e+2i");
static assert((123.5fi).stringof == "1.235e+2Fi");
static assert((123.5Li).stringof == "1.235e+2Li");
static assert((123.5 +5.5i ).stringof == "1.235e+2 + 5.5e+0i");
static assert((123.5f+5.5fi).stringof == "1.235e+2F + 5.5e+0Fi");
static assert((123.5L+5.5Li).stringof == "1.235e+2L + 5.5e+0Li");
version (GNU)
{
static assert((123.5 ).stringof == "1.235e+2");
static assert((123.5f ).stringof == "1.235e+2F");
static assert((123.5L ).stringof == "1.235e+2L");
static assert((123.5i ).stringof == "1.235e+2i");
static assert((123.5fi).stringof == "1.235e+2Fi");
static assert((123.5Li).stringof == "1.235e+2Li");
static assert((123.5 +5.5i ).stringof == "1.235e+2 + 5.5e+0i");
static assert((123.5f+5.5fi).stringof == "1.235e+2F + 5.5e+0Fi");
static assert((123.5L+5.5Li).stringof == "1.235e+2L + 5.5e+0Li");
}
else
{
static assert((123.5 ).stringof == "123.5");
static assert((123.5f ).stringof == "123.5F");
static assert((123.5L ).stringof == "123.5L");
static assert((123.5i ).stringof == "123.5i");
static assert((123.5fi).stringof == "123.5Fi");
static assert((123.5Li).stringof == "123.5Li");
static assert((123.5 +5.5i ).stringof == "123.5 + 5.5i");
static assert((123.5f+5.5fi).stringof == "123.5F + 5.5Fi");
static assert((123.5L+5.5Li).stringof == "123.5L + 5.5Li");
}

View file

@ -1,10 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/b19523.d(12): Error: undefined identifier `SomeStruct`
fail_compilation/b19523.d(13): Error: function `b19523.foo(int delegate() arg)` is not callable using argument types `(_error_)`
fail_compilation/b19523.d(13): cannot pass argument `__lambda2` of type `_error_` to parameter `int delegate() arg`
---
----
fail_compilation/b19523.d(13): Error: undefined identifier `SomeStruct`
fail_compilation/b19523.d(14): Error: function `foo` is not callable using argument types `(_error_)`
fail_compilation/b19523.d(14): cannot pass argument `__lambda2` of type `_error_` to parameter `int delegate() arg`
fail_compilation/b19523.d(19): `b19523.foo(int delegate() arg)` declared here
----
*/
module b19523;

View file

@ -1,16 +1,19 @@
/*
TEST_OUTPUT:
---
fail_compilation/b20011.d(25): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
fail_compilation/b20011.d(28): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(29): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(32): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
fail_compilation/b20011.d(37): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(37): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
fail_compilation/b20011.d(38): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(38): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
fail_compilation/b20011.d(39): Error: function `b20011.main.assignableByConstRef(ref const(ubyte) p)` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(39): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref const(ubyte) p`
fail_compilation/b20011.d(28): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
fail_compilation/b20011.d(31): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(32): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(35): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
fail_compilation/b20011.d(40): Error: function `assignableByRef` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(40): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
fail_compilation/b20011.d(37): `b20011.main.assignableByRef(ref ubyte p)` declared here
fail_compilation/b20011.d(41): Error: function `assignableByOut` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(41): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
fail_compilation/b20011.d(38): `b20011.main.assignableByOut(out ubyte p)` declared here
fail_compilation/b20011.d(42): Error: function `assignableByConstRef` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(42): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref const(ubyte) p`
fail_compilation/b20011.d(39): `b20011.main.assignableByConstRef(ref const(ubyte) p)` declared here
---
*/
module b20011;

View file

@ -1,10 +1,12 @@
/*
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`
fail_compilation/bug15613.d(18): Error: function `f` is not callable using argument types `(typeof(null))`
fail_compilation/bug15613.d(18): cannot pass argument `null` of type `typeof(null)` to parameter `int...`
fail_compilation/bug15613.d(13): `bug15613.f(int...)` declared here
fail_compilation/bug15613.d(19): Error: function `g` is not callable using argument types `(int)`
fail_compilation/bug15613.d(19): cannot pass argument `8` of type `int` to parameter `Object`
fail_compilation/bug15613.d(14): `bug15613.g(Object, ...)` declared here
---
*/
@ -20,8 +22,9 @@ void main()
/*
TEST_OUTPUT:
---
fail_compilation/bug15613.d(32): Error: function `bug15613.h(int[]...)` is not callable using argument types `(int, void function(int[]...))`
fail_compilation/bug15613.d(32): cannot pass argument `& h` of type `void function(int[]...)` to parameter `int[]...`
fail_compilation/bug15613.d(35): Error: function `h` is not callable using argument types `(int, void function(int[]...))`
fail_compilation/bug15613.d(35): cannot pass argument `& h` of type `void function(int[]...)` to parameter `int[]...`
fail_compilation/bug15613.d(31): `bug15613.h(int[]...)` declared here
---
*/

View file

@ -10,9 +10,11 @@ void g()
/*
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): Error: function `f` 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(1): `bug16165.f(int x, Object y)` declared here
fail_compilation/bug16165.d(7): Error: function `f` 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`
fail_compilation/bug16165.d(1): `bug16165.f(int x, Object y)` declared here
---
*/

View file

@ -62,12 +62,13 @@ void test3()
/*
TEST_OUTPUT:
---
fail_compilation/bug9631.d(79): Error: function `bug9631.arg.f(int i, S s)` is not callable using argument types `(int, S)`
fail_compilation/bug9631.d(79): cannot pass argument `y` of type `bug9631.tem!().S` to parameter `bug9631.S s`
fail_compilation/bug9631.d(80): Error: function literal `__lambda4(S s)` is not callable using argument types `(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 parameter `bug9631.S __param_0`
fail_compilation/bug9631.d(80): Error: function `f` is not callable using argument types `(int, S)`
fail_compilation/bug9631.d(80): cannot pass argument `y` of type `bug9631.tem!().S` to parameter `bug9631.S s`
fail_compilation/bug9631.d(79): `bug9631.arg.f(int i, S s)` declared here
fail_compilation/bug9631.d(81): Error: function literal `__lambda4(S s)` is not callable using argument types `(S)`
fail_compilation/bug9631.d(81): cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S s`
fail_compilation/bug9631.d(87): Error: constructor `bug9631.arg.A.this(S __param_0)` is not callable using argument types `(S)`
fail_compilation/bug9631.d(87): cannot pass argument `S(0)` of type `bug9631.tem!().S` to parameter `bug9631.S __param_0`
---
*/
void arg()
@ -89,12 +90,13 @@ void arg()
/*
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` is not callable using argument types `!()(S)`
fail_compilation/bug9631.d(105): Candidate is: `ft()(tem!().S)`
fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` is not callable using argument types `!()(S, int)`
fail_compilation/bug9631.d(108): Candidate is: `ft2(T)(S, T)`
fail_compilation/bug9631.d(108): Error: function `ft` is not callable using argument types `(S)`
fail_compilation/bug9631.d(108): cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S __param_0`
fail_compilation/bug9631.d(107): `bug9631.targ.ft!().ft(S __param_0)` declared here
fail_compilation/bug9631.d(109): Error: template `ft` is not callable using argument types `!()(S)`
fail_compilation/bug9631.d(107): Candidate is: `ft()(tem!().S)`
fail_compilation/bug9631.d(111): Error: template `ft2` is not callable using argument types `!()(S, int)`
fail_compilation/bug9631.d(110): Candidate is: `ft2(T)(S, T)`
---
*/
void targ()

View file

@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/callconst.d(13): Error: function `callconst.func(ref X)` is not callable using argument types `(const(X))`
fail_compilation/callconst.d(13): cannot pass argument `x` of type `const(X)` to parameter `ref X`
fail_compilation/callconst.d(14): Error: function `func` is not callable using argument types `(const(X))`
fail_compilation/callconst.d(14): cannot pass argument `x` of type `const(X)` to parameter `ref X`
fail_compilation/callconst.d(17): `callconst.func(ref X)` declared here
---
*/
struct X {}

View file

@ -2,12 +2,12 @@
EXTRA_FILES: imports/constraints.d
TEST_OUTPUT:
---
fail_compilation/constraints_aggr.d(32): Error: template `imports.constraints.C.f` is not callable using argument types `!()(int)`
fail_compilation/constraints_aggr.d(32): Error: template `f` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(60): Candidate is: `f(T)(T v)`
with `T = int`
must satisfy the following constraint:
` !P!T`
fail_compilation/constraints_aggr.d(33): Error: template `imports.constraints.C.g` is not callable using argument types `!()()`
fail_compilation/constraints_aggr.d(33): Error: template `g` is not callable using argument types `!()()`
fail_compilation/imports/constraints.d(63): Candidate is: `g(this T)()`
with `T = imports.constraints.C`
must satisfy the following constraint:

View file

@ -2,72 +2,72 @@
EXTRA_FILES: imports/constraints.d
TEST_OUTPUT:
---
fail_compilation/constraints_func1.d(79): Error: template `imports.constraints.test1` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(79): Error: template `test1` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(9): Candidate is: `test1(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func1.d(80): Error: template `imports.constraints.test2` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(80): Error: template `test2` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(10): Candidate is: `test2(T)(T v)`
with `T = int`
must satisfy the following constraint:
` !P!T`
fail_compilation/constraints_func1.d(81): Error: template `imports.constraints.test3` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(81): Error: template `test3` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(11): Candidate is: `test3(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func1.d(82): Error: template `imports.constraints.test4` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(82): Error: template `test4` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(12): Candidate is: `test4(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func1.d(83): Error: template `imports.constraints.test5` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(83): Error: template `test5` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(13): Candidate is: `test5(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T`
fail_compilation/constraints_func1.d(84): Error: template `imports.constraints.test6` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(84): Error: template `test6` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(14): Candidate is: `test6(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T
!P!T`
fail_compilation/constraints_func1.d(85): Error: template `imports.constraints.test7` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(85): Error: template `test7` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(15): Candidate is: `test7(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T`
fail_compilation/constraints_func1.d(86): Error: template `imports.constraints.test8` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(86): Error: template `test8` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(16): Candidate is: `test8(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func1.d(87): Error: template `imports.constraints.test9` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(87): Error: template `test9` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(17): Candidate is: `test9(T)(T v)`
with `T = int`
must satisfy the following constraint:
` !P!T`
fail_compilation/constraints_func1.d(88): Error: template `imports.constraints.test10` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(88): Error: template `test10` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(18): Candidate is: `test10(T)(T v)`
with `T = int`
must satisfy the following constraint:
` !P!T`
fail_compilation/constraints_func1.d(89): Error: template `imports.constraints.test11` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(89): Error: template `test11` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(19): Candidate is: `test11(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
!P!T`
fail_compilation/constraints_func1.d(90): Error: template `imports.constraints.test12` is not callable using argument types `!()(int)`
fail_compilation/constraints_func1.d(90): Error: template `test12` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(20): Candidate is: `test12(T)(T v)`
with `T = int`
must satisfy the following constraint:
` !P!T`
fail_compilation/constraints_func1.d(92): Error: template `imports.constraints.test1` is not callable using argument types `!()(int, int)`
fail_compilation/constraints_func1.d(92): Error: template `test1` is not callable using argument types `!()(int, int)`
fail_compilation/imports/constraints.d(9): Candidate is: `test1(T)(T v)`
---
*/

View file

@ -2,83 +2,83 @@
EXTRA_FILES: imports/constraints.d
TEST_OUTPUT:
---
fail_compilation/constraints_func2.d(94): Error: template `imports.constraints.test13` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(94): Error: template `test13` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(23): Candidate is: `test13(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
!P!T`
fail_compilation/constraints_func2.d(95): Error: template `imports.constraints.test14` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(95): Error: template `test14` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(24): Candidate is: `test14(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` !P!T
N!T`
fail_compilation/constraints_func2.d(96): Error: template `imports.constraints.test15` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(96): Error: template `test15` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(25): Candidate is: `test15(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` !P!T
!P!T`
fail_compilation/constraints_func2.d(97): Error: template `imports.constraints.test16` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(97): Error: template `test16` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(26): Candidate is: `test16(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T`
fail_compilation/constraints_func2.d(98): Error: template `imports.constraints.test17` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(98): Error: template `test17` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(27): Candidate is: `test17(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func2.d(99): Error: template `imports.constraints.test18` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(99): Error: template `test18` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(28): Candidate is: `test18(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T`
fail_compilation/constraints_func2.d(100): Error: template `imports.constraints.test19` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(100): Error: template `test19` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(29): Candidate is: `test19(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
!P!T
N!T`
fail_compilation/constraints_func2.d(101): Error: template `imports.constraints.test20` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(101): Error: template `test20` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(30): Candidate is: `test20(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func2.d(102): Error: template `imports.constraints.test21` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(102): Error: template `test21` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(31): Candidate is: `test21(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` N!T
N!T`
fail_compilation/constraints_func2.d(103): Error: template `imports.constraints.test22` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(103): Error: template `test22` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(32): Candidate is: `test22(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` !P!T
!P!T`
fail_compilation/constraints_func2.d(104): Error: template `imports.constraints.test23` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(104): Error: template `test23` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(33): Candidate is: `test23(T)(T v)`
with `T = int`
must satisfy one of the following constraints:
` !P!T
N!T
!P!T`
fail_compilation/constraints_func2.d(105): Error: template `imports.constraints.test24` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(105): Error: template `test24` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(34): Candidate is: `test24(R)(R r)`
with `R = int`
must satisfy the following constraint:
` __traits(hasMember, R, "stuff")`
fail_compilation/constraints_func2.d(106): Error: template `imports.constraints.test25` is not callable using argument types `!()(int)`
fail_compilation/constraints_func2.d(106): Error: template `test25` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(35): Candidate is: `test25(T)(T v)`
with `T = int`
must satisfy the following constraint:
` N!T`
fail_compilation/constraints_func2.d(107): Error: template `imports.constraints.test26` is not callable using argument types `!(float)(int)`
fail_compilation/constraints_func2.d(107): Error: template `test26` is not callable using argument types `!(float)(int)`
fail_compilation/imports/constraints.d(36): Candidate is: `test26(T, U)(U u)`
with `T = float,
U = int`

View file

@ -1,7 +1,7 @@
/*
EXTRA_FILES: imports/constraints.d
TEST_OUTPUT:
---
----
fail_compilation/constraints_func3.d(53): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(39): Candidates are: `overload(T)(T v)`
with `T = int`
@ -23,27 +23,27 @@ fail_compilation/imports/constraints.d(42): `overload(T,
must satisfy one of the following constraints:
` N!T
N!V`
fail_compilation/constraints_func3.d(56): Error: template `imports.constraints.variadic` is not callable using argument types `!()()`
fail_compilation/constraints_func3.d(56): Error: template `variadic` is not callable using argument types `!()()`
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
fail_compilation/constraints_func3.d(57): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int)`
fail_compilation/constraints_func3.d(57): Error: template `variadic` is not callable using argument types `!()(int)`
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
with `A = int,
T = ()`
must satisfy the following constraint:
` N!int`
fail_compilation/constraints_func3.d(58): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int)`
fail_compilation/constraints_func3.d(58): Error: template `variadic` is not callable using argument types `!()(int, int)`
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
with `A = int,
T = (int)`
must satisfy the following constraint:
` N!int`
fail_compilation/constraints_func3.d(59): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int, int)`
fail_compilation/constraints_func3.d(59): Error: template `variadic` is not callable using argument types `!()(int, int, int)`
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
with `A = int,
T = (int, int)`
must satisfy the following constraint:
` N!int`
---
----
*/
void main()

View file

@ -2,7 +2,7 @@
EXTRA_FILES: imports/constraints.d
REQUIRED_ARGS: -verrors=context
TEST_OUTPUT:
---
----
fail_compilation/constraints_func4.d(90): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
overload(0);
^
@ -44,13 +44,13 @@ fail_compilation/imports/constraints.d(42): `overload(T,
N!V`
void overload(T, V)(T v1, V v2) if (N!T || N!V);
^
fail_compilation/constraints_func4.d(93): Error: template `imports.constraints.variadic` is not callable using argument types `!()()`
fail_compilation/constraints_func4.d(93): Error: template `variadic` is not callable using argument types `!()()`
variadic();
^
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
void variadic(A, T...)(A a, T v) if (N!int);
^
fail_compilation/constraints_func4.d(94): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int)`
fail_compilation/constraints_func4.d(94): Error: template `variadic` is not callable using argument types `!()(int)`
variadic(0);
^
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
@ -60,7 +60,7 @@ fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T.
` N!int`
void variadic(A, T...)(A a, T v) if (N!int);
^
fail_compilation/constraints_func4.d(95): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int)`
fail_compilation/constraints_func4.d(95): Error: template `variadic` is not callable using argument types `!()(int, int)`
variadic(0, 1);
^
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
@ -70,7 +70,7 @@ fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T.
` N!int`
void variadic(A, T...)(A a, T v) if (N!int);
^
fail_compilation/constraints_func4.d(96): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int, int)`
fail_compilation/constraints_func4.d(96): Error: template `variadic` is not callable using argument types `!()(int, int, int)`
variadic(0, 1, 2);
^
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
@ -80,7 +80,7 @@ fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T.
` N!int`
void variadic(A, T...)(A a, T v) if (N!int);
^
---
----
*/
void main()

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/diag13942.d(18): Error: template instance `isRawStaticArray!()` does not match template declaration `isRawStaticArray(T, A...)`
fail_compilation/diag13942.d(26): Error: template `diag13942.to!double.to` is not callable using argument types `!()()`
fail_compilation/diag13942.d(26): Error: template `to` is not callable using argument types `!()()`
fail_compilation/diag13942.d(17): Candidate is: `to(A...)(A args)`
---
*/

View file

@ -3,7 +3,7 @@ TEST_OUTPUT:
---
fail_compilation/diag16977.d(25): Error: undefined identifier `undefined`, did you mean function `undefinedId`?
fail_compilation/diag16977.d(26): Error: cannot implicitly convert expression `"\x01string"` of type `string` to `int`
fail_compilation/diag16977.d(27): Error: template `diag16977.templ` is not callable using argument types `!()(int)`
fail_compilation/diag16977.d(27): Error: template `templ` is not callable using argument types `!()(int)`
fail_compilation/diag16977.d(20): Candidate is: `templ(S)(S s)`
with `S = int`
must satisfy the following constraint:

View file

@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag20268.d(12): Error: template `diag20268.__lambda4` is not callable using argument types `!()(int)`
fail_compilation/diag20268.d(12): Error: template `__lambda4` is not callable using argument types `!()(int)`
fail_compilation/diag20268.d(11): Candidate is: `__lambda4(__T1, __T2)(x, y)`
---
*/

View file

@ -2,10 +2,10 @@
TEST_OUTPUT:
---
fail_compilation/diag23355.d(1): Error: undefined identifier `n`
fail_compilation/diag23355.d(4): Error: template `diag23355.ffi1` is not callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(4): Error: template `ffi1` is not callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(1): Candidate is: `ffi1(T)(T[n] s)`
fail_compilation/diag23355.d(2): Error: undefined identifier `n`
fail_compilation/diag23355.d(4): Error: template `diag23355.ffi2` is not callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(4): Error: template `ffi2` is not callable using argument types `!()(int[4])`
fail_compilation/diag23355.d(2): Candidate is: `ffi2()(T[n] s)`
---
*/

View file

@ -1,32 +1,33 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag8101.d(61): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
fail_compilation/diag8101.d(61): too few arguments, expected 1, got 0
fail_compilation/diag8101.d(62): Error: none of the overloads of `f_1` are callable using argument types `()`
fail_compilation/diag8101.d(35): Candidates are: `diag8101.f_1(int)`
fail_compilation/diag8101.d(36): `diag8101.f_1(int, int)`
fail_compilation/diag8101.d(63): Error: none of the overloads of `f_2` are callable using argument types `()`
fail_compilation/diag8101.d(38): Candidates are: `diag8101.f_2(int)`
fail_compilation/diag8101.d(39): `diag8101.f_2(int, int)`
fail_compilation/diag8101.d(40): `diag8101.f_2(int, int, int)`
fail_compilation/diag8101.d(41): `diag8101.f_2(int, int, int, int)`
fail_compilation/diag8101.d(42): `diag8101.f_2(int, int, int, int, int)`
fail_compilation/diag8101.d(43): `diag8101.f_2(int, int, int, int, int, int)`
fail_compilation/diag8101.d(63): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(65): Error: template `diag8101.t_0` is not callable using argument types `!()()`
fail_compilation/diag8101.d(46): Candidate is: `t_0(T1)()`
fail_compilation/diag8101.d(66): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()`
fail_compilation/diag8101.d(48): Candidates are: `t_1(T1)()`
fail_compilation/diag8101.d(49): `t_1(T1, T2)()`
fail_compilation/diag8101.d(67): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()`
fail_compilation/diag8101.d(51): Candidates are: `t_2(T1)()`
fail_compilation/diag8101.d(52): `t_2(T1, T2)()`
fail_compilation/diag8101.d(53): `t_2(T1, T2, T3)()`
fail_compilation/diag8101.d(54): `t_2(T1, T2, T3, T4)()`
fail_compilation/diag8101.d(55): `t_2(T1, T2, T3, T4, T5)()`
fail_compilation/diag8101.d(56): `t_2(T1, T2, T3, T4, T5, T6)()`
fail_compilation/diag8101.d(67): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(62): Error: function `f_0` is not callable using argument types `()`
fail_compilation/diag8101.d(62): too few arguments, expected 1, got 0
fail_compilation/diag8101.d(34): `diag8101.f_0(int)` declared here
fail_compilation/diag8101.d(63): Error: none of the overloads of `f_1` are callable using argument types `()`
fail_compilation/diag8101.d(36): Candidates are: `diag8101.f_1(int)`
fail_compilation/diag8101.d(37): `diag8101.f_1(int, int)`
fail_compilation/diag8101.d(64): Error: none of the overloads of `f_2` are callable using argument types `()`
fail_compilation/diag8101.d(39): Candidates are: `diag8101.f_2(int)`
fail_compilation/diag8101.d(40): `diag8101.f_2(int, int)`
fail_compilation/diag8101.d(41): `diag8101.f_2(int, int, int)`
fail_compilation/diag8101.d(42): `diag8101.f_2(int, int, int, int)`
fail_compilation/diag8101.d(43): `diag8101.f_2(int, int, int, int, int)`
fail_compilation/diag8101.d(44): `diag8101.f_2(int, int, int, int, int, int)`
fail_compilation/diag8101.d(64): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(66): Error: template `t_0` is not callable using argument types `!()()`
fail_compilation/diag8101.d(47): Candidate is: `t_0(T1)()`
fail_compilation/diag8101.d(67): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()`
fail_compilation/diag8101.d(49): Candidates are: `t_1(T1)()`
fail_compilation/diag8101.d(50): `t_1(T1, T2)()`
fail_compilation/diag8101.d(68): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()`
fail_compilation/diag8101.d(52): Candidates are: `t_2(T1)()`
fail_compilation/diag8101.d(53): `t_2(T1, T2)()`
fail_compilation/diag8101.d(54): `t_2(T1, T2, T3)()`
fail_compilation/diag8101.d(55): `t_2(T1, T2, T3, T4)()`
fail_compilation/diag8101.d(56): `t_2(T1, T2, T3, T4, T5)()`
fail_compilation/diag8101.d(57): `t_2(T1, T2, T3, T4, T5, T6)()`
fail_compilation/diag8101.d(68): ... (1 more, -v to show) ...
---
*/

View file

@ -2,13 +2,13 @@
TEST_OUTPUT:
---
fail_compilation/diag8648.d(18): Error: undefined identifier `X`
fail_compilation/diag8648.d(29): Error: template `diag8648.foo` is not callable using argument types `!()(Foo!(int, 1))`
fail_compilation/diag8648.d(29): Error: template `foo` is not callable using argument types `!()(Foo!(int, 1))`
fail_compilation/diag8648.d(18): Candidate is: `foo(T, n)(X!(T, n))`
fail_compilation/diag8648.d(20): Error: undefined identifier `a`
fail_compilation/diag8648.d(31): Error: template `diag8648.bar` is not callable using argument types `!()(Foo!(int, 1))`
fail_compilation/diag8648.d(31): Error: template `bar` is not callable using argument types `!()(Foo!(int, 1))`
fail_compilation/diag8648.d(20): Candidate is: `bar(T)(Foo!(T, a))`
fail_compilation/diag8648.d(20): Error: undefined identifier `a`
fail_compilation/diag8648.d(32): Error: template `diag8648.bar` is not callable using argument types `!()(Foo!(int, f))`
fail_compilation/diag8648.d(32): Error: template `bar` is not callable using argument types `!()(Foo!(int, f))`
fail_compilation/diag8648.d(20): Candidate is: `bar(T)(Foo!(T, a))`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag9004.d(21): Error: template `diag9004.bar` is not callable using argument types `!()(Foo!int, int)`
fail_compilation/diag9004.d(21): Error: template `bar` is not callable using argument types `!()(Foo!int, int)`
fail_compilation/diag9004.d(14): Candidate is: `bar(FooT)(FooT foo, FooT.T x)`
---
*/

View file

@ -2,10 +2,11 @@
REQUIRED_ARGS: -preview=in
TEST_OUTPUT:
---
fail_compilation/diagin.d(14): Error: function `diagin.foo(in int)` is not callable using argument types `()`
fail_compilation/diagin.d(14): too few arguments, expected 1, got 0
fail_compilation/diagin.d(16): Error: template `diagin.foo1` is not callable using argument types `!()(bool[])`
fail_compilation/diagin.d(20): Candidate is: `foo1(T)(in T v, string)`
fail_compilation/diagin.d(15): Error: function `foo` is not callable using argument types `()`
fail_compilation/diagin.d(15): too few arguments, expected 1, got 0
fail_compilation/diagin.d(20): `diagin.foo(in int)` declared here
fail_compilation/diagin.d(17): Error: template `foo1` is not callable using argument types `!()(bool[])`
fail_compilation/diagin.d(21): Candidate is: `foo1(T)(in T v, string)`
---
*/

View file

@ -14,10 +14,10 @@ fail_compilation/fail12744.d(61): Error: template instance `fail12744.bar12744L!
fail_compilation/fail12744.d(40): Error: incompatible parameter storage classes `lazy` and `out`
fail_compilation/fail12744.d(62): Error: template instance `fail12744.bar12744L!(foo12744O)` error instantiating
fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `out`
fail_compilation/fail12744.d(67): Error: template `fail12744.bar12744A` is not callable using argument types `!(foo12744O)(int)`
fail_compilation/fail12744.d(67): Error: template `bar12744A` is not callable using argument types `!(foo12744O)(int)`
fail_compilation/fail12744.d(41): Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `lazy`
fail_compilation/fail12744.d(68): Error: template `fail12744.bar12744A` is not callable using argument types `!(foo12744L)(int)`
fail_compilation/fail12744.d(68): Error: template `bar12744A` is not callable using argument types `!(foo12744L)(int)`
fail_compilation/fail12744.d(41): Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation\fail136.d(10): Error: `"\xef\xbb\xbf"` has no effect
fail_compilation/fail136.d(10): Error: `x"EFBBBF"` has no effect
---
*/

View file

@ -4,7 +4,7 @@ TEST_OUTPUT:
fail_compilation/fail14669.d(11): Error: `auto` can only be used as part of `auto ref` for template function parameters
fail_compilation/fail14669.d(16): Error: template instance `fail14669.foo1!()` error instantiating
fail_compilation/fail14669.d(12): Error: `auto` can only be used as part of `auto ref` for template function parameters
fail_compilation/fail14669.d(17): Error: template `fail14669.foo2` is not callable using argument types `!()(int)`
fail_compilation/fail14669.d(17): Error: template `foo2` is not callable using argument types `!()(int)`
fail_compilation/fail14669.d(12): Candidate is: `foo2()(auto int a)`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail162.d(25): Error: template `fail162.testHelper` is not callable using argument types `!()(string, string)`
fail_compilation/fail162.d(25): Error: template `testHelper` is not callable using argument types `!()(string, string)`
fail_compilation/fail162.d(10): Candidate is: `testHelper(A...)()`
fail_compilation/fail162.d(30): Error: template instance `fail162.test!("hello", "world")` error instantiating
---

View file

@ -3,8 +3,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail19948.d(15): Error: function `fail19948.func(const(X))` is not callable using argument types `(X)`
fail_compilation/fail19948.d(15): cannot pass argument `X()` of type `fail19948.main.X` to parameter `const(fail19948.X)`
fail_compilation/fail19948.d(16): Error: function `func` is not callable using argument types `(X)`
fail_compilation/fail19948.d(16): cannot pass argument `X()` of type `fail19948.main.X` to parameter `const(fail19948.X)`
fail_compilation/fail19948.d(19): `fail19948.func(const(X))` declared here
---
*/
// DISABLED: win32

View file

@ -1,8 +1,9 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/fail20183.d(1016): Error: function `fail20183.addr(return ref int b)` is not callable using argument types `(int)`
fail_compilation/fail20183.d(1016): Error: function `addr` is not callable using argument types `(int)`
fail_compilation/fail20183.d(1016): cannot pass rvalue argument `S(0).i` of type `int` to parameter `return ref int b`
fail_compilation/fail20183.d(1005): `fail20183.addr(return ref int b)` declared here
fail_compilation/fail20183.d(1017): Error: address of struct temporary returned by `s()` assigned to longer lived variable `q`
---
*/

View file

@ -3,7 +3,7 @@ REQUIRED_ARGS: -verrors=spec -o-
TEST_OUTPUT:
---
(spec:1) fail_compilation/fail20730b.d-mixin-43(43): Error: C style cast illegal, use `cast(int)mod`
fail_compilation/fail20730b.d(26): Error: template `fail20730b.atomicOp` is not callable using argument types `!("+=")(shared(uint), int)`
fail_compilation/fail20730b.d(26): Error: template `atomicOp` is not callable using argument types `!("+=")(shared(uint), int)`
fail_compilation/fail20730b.d(41): Candidate is: `atomicOp(string op, T, V1)(shared ref T val, V1 mod)`
with `op = "+=",
T = uint,

View file

@ -2,10 +2,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail20800.d(22): Error: function `fail20800.fun(int a)` is not callable using argument types `(string)`
fail_compilation/fail20800.d(22): cannot pass argument `(m()).index()` of type `string` to parameter `int a`
---
----
fail_compilation/fail20800.d(23): Error: function `fun` is not callable using argument types `(string)`
fail_compilation/fail20800.d(23): cannot pass argument `(m()).index()` of type `string` to parameter `int a`
fail_compilation/fail20800.d(19): `fail20800.fun(int a)` declared here
----
*/
struct RegexMatch

View file

@ -3,8 +3,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail22202.d(21): Error: function `fail22202.fun(SystemCopy __param_0)` is not callable using argument types `(SystemCopy)`
fail_compilation/fail22202.d(21): `inout ref inout(SystemCopy)(ref inout(SystemCopy) other)` copy constructor cannot be called from a `pure @safe nogc` context
fail_compilation/fail22202.d(22): Error: function `fun` is not callable using argument types `(SystemCopy)`
fail_compilation/fail22202.d(22): `inout ref inout(SystemCopy)(ref inout(SystemCopy) other)` copy constructor cannot be called from a `pure @safe nogc` context
fail_compilation/fail22202.d(17): `fail22202.fun(SystemCopy __param_0)` declared here
---
*/

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail236.d(14): Error: undefined identifier `x`
fail_compilation/fail236.d(22): Error: template `fail236.Templ2` is not callable using argument types `!()(int)`
fail_compilation/fail236.d(22): Error: template `Templ2` is not callable using argument types `!()(int)`
fail_compilation/fail236.d(12): Candidate is: `Templ2(alias a)(x)`
---
*/

View file

@ -1,8 +1,9 @@
/+
TEST_OUTPUT:
---
fail_compilation/fail24301.d(18): Error: function `fail24301.fun(S __param_0)` is not callable using argument types `(S)`
fail_compilation/fail24301.d(18): `ref S(ref S)` copy constructor cannot be used because it is annotated with `@disable`
fail_compilation/fail24301.d(19): Error: function `fun` is not callable using argument types `(S)`
fail_compilation/fail24301.d(19): `ref S(ref S)` copy constructor cannot be used because it is annotated with `@disable`
fail_compilation/fail24301.d(14): `fail24301.fun(S __param_0)` declared here
---
+/
struct S

View file

@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
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`
---
----
fail_compilation/fail263.d(20): Error: function `f` is not callable using argument types `(const(byte)*)`
fail_compilation/fail263.d(20): cannot pass argument `cast(const(byte)*)A` of type `const(byte)*` to parameter `byte* p`
fail_compilation/fail263.d(14): `fail263.f(byte* p)` declared here
----
*/
// https://issues.dlang.org/show_bug.cgi?id=2766

View file

@ -1,11 +1,13 @@
/*
TEST_OUTPUT:
---
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`
---
----
fail_compilation/fail322.d(15): Error: function `digestToString2` is not callable using argument types `(string)`
fail_compilation/fail322.d(15): cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] digest`
fail_compilation/fail322.d(20): `fail322.digestToString2(ref char[16] digest)` declared here
fail_compilation/fail322.d(17): Error: function `digestToString2` is not callable using argument types `(const(char[16]))`
fail_compilation/fail322.d(17): cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] digest`
fail_compilation/fail322.d(20): `fail322.digestToString2(ref char[16] digest)` declared here
----
*/
void main()

View file

@ -1,14 +1,18 @@
/*
TEST_OUTPUT:
---
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...`
fail_compilation/fail332.d(26): Error: function `foo` is not callable using argument types `()`
fail_compilation/fail332.d(26): missing argument for parameter #1: `int __param_0`
fail_compilation/fail332.d(21): `fail332.foo(int __param_0, ...)` declared here
fail_compilation/fail332.d(27): Error: function `foo` is not callable using argument types `(typeof(null))`
fail_compilation/fail332.d(27): cannot pass argument `null` of type `typeof(null)` to parameter `int __param_0`
fail_compilation/fail332.d(21): `fail332.foo(int __param_0, ...)` declared here
fail_compilation/fail332.d(29): Error: function `baz` is not callable using argument types `(string)`
fail_compilation/fail332.d(29): cannot pass argument `""` of type `string` to parameter `int[] __param_0...`
fail_compilation/fail332.d(22): `fail332.baz(int[] __param_0...)` declared here
fail_compilation/fail332.d(30): Error: function `baz` is not callable using argument types `(int, typeof(null))`
fail_compilation/fail332.d(30): cannot pass argument `null` of type `typeof(null)` to parameter `int[] __param_0...`
fail_compilation/fail332.d(22): `fail332.baz(int[] __param_0...)` declared here
---
*/
@ -29,18 +33,24 @@ void test()
/*
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
fail_compilation/fail332.d(60): Error: function `bar` is not callable using argument types `()`
fail_compilation/fail332.d(60): missing argument for parameter #1: `Object`
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
fail_compilation/fail332.d(61): Error: function `bar` is not callable using argument types `(int)`
fail_compilation/fail332.d(61): cannot pass argument `4` of type `int` to parameter `Object`
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
fail_compilation/fail332.d(62): Error: function `bar` is not callable using argument types `(typeof(null))`
fail_compilation/fail332.d(62): expected 2 variadic argument(s), not 0
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
fail_compilation/fail332.d(63): Error: function `bar` is not callable using argument types `(typeof(null), int)`
fail_compilation/fail332.d(63): expected 2 variadic argument(s), not 1
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
fail_compilation/fail332.d(64): Error: function `bar` is not callable using argument types `(typeof(null), int, string)`
fail_compilation/fail332.d(64): cannot pass argument `""` of type `string` to parameter `int[2]...`
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
fail_compilation/fail332.d(65): Error: function `bar` is not callable using argument types `(typeof(null), int, int, int)`
fail_compilation/fail332.d(65): expected 2 variadic argument(s), not 3
fail_compilation/fail332.d(56): `fail332.bar(Object, int[2]...)` declared here
---
*/
void bar(Object, int[2]...);

View file

@ -1,11 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail58.d(26): Error: function `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` is not callable using argument types `(string, int)`
fail_compilation/fail58.d(26): cannot pass argument `"123"` of type `string` to parameter `dchar[] pText`
fail_compilation/fail58.d(30): Error: function `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` is not callable using argument types `(string, int)`
fail_compilation/fail58.d(30): cannot pass argument `""` of type `string` to parameter `dchar[] pText`
---
----
fail_compilation/fail58.d(28): Error: function `SomeFunc` is not callable using argument types `(string, int)`
fail_compilation/fail58.d(28): cannot pass argument `"123"` of type `string` to parameter `dchar[] pText`
fail_compilation/fail58.d(14): `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` declared here
fail_compilation/fail58.d(32): Error: function `SomeFunc` is not callable using argument types `(string, int)`
fail_compilation/fail58.d(32): cannot pass argument `""` of type `string` to parameter `dchar[] pText`
fail_compilation/fail58.d(14): `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` declared here
----
*/
debug import std.stdio;
const int anything = -1000; // Line #2

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail8009.d(9): Error: template `fail8009.filter` is not callable using argument types `!()(void)`
fail_compilation/fail8009.d(9): Error: template `filter` is not callable using argument types `!()(void)`
fail_compilation/fail8009.d(8): Candidate is: `filter(R)(scope bool delegate(ref BAD!R) func)`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail95.d(19): Error: template `fail95.A` is not callable using argument types `!()(int)`
fail_compilation/fail95.d(19): Error: template `A` is not callable using argument types `!()(int)`
fail_compilation/fail95.d(11): Candidate is: `A(alias T)(T)`
---
*/

View file

@ -1,18 +1,39 @@
/**
TEST_OUTPUT:
---
fail_compilation\hexstring.d(16): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
fail_compilation\hexstring.d(17): Error: cannot implicitly convert expression `"\x12?"c` of type `string` to `immutable(ubyte[])`
fail_compilation\hexstring.d(18): Error: cannot implicitly convert expression `"\x12?"` of type `string` to `immutable(ubyte[])`
fail_compilation\hexstring.d(15): Error: cannot implicitly convert expression `"\x12?"` of type `string` to `ubyte[]`
---
*/
immutable ubyte[] s0 = x"123F";
static assert(s0[0] == 0x12);
static assert(s0[1] == 0x3F);
immutable byte[] s1 = x"123F";
ubyte[] f1 = x"123F";
immutable ubyte[] f2 = "123F";
immutable ubyte[] f3 = x"123F"c;
immutable ubyte[] f4 = cast(string) x"123F";
/**
TEST_OUTPUT:
---
fail_compilation/hexstring.d(29): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
fail_compilation/hexstring.d(30): Error: cannot implicitly convert expression `x"123F"c` of type `string` to `immutable(ubyte[])`
fail_compilation/hexstring.d(31): Error: cannot implicitly convert expression `x"123F"` of type `string` to `immutable(ubyte[])`
fail_compilation/hexstring.d(33): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])`
fail_compilation/hexstring.d(34): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])`
fail_compilation/hexstring.d(35): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])`
fail_compilation/hexstring.d(36): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time
fail_compilation/hexstring.d(36): perhaps remove postfix `w` from hex string
fail_compilation/hexstring.d(37): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
fail_compilation/hexstring.d(38): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time
fail_compilation/hexstring.d(39): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
fail_compilation/hexstring.d(39): perhaps remove postfix `c` from hex string
fail_compilation/hexstring.d(28): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]`
---
*/
immutable ubyte[] s0 = x"123F";
static assert(s0[0] == 0x12);
static assert(s0[1] == 0x3F);
immutable byte[] s1 = x"123F";
enum E(X) = cast(X[]) x"AABBCCDD";
static assert(E!int[0] == 0xAABBCCDD);
ubyte[] f1 = x"123F";
immutable ubyte[] f2 = "123F";
immutable ubyte[] f3 = x"123F"c;
immutable ubyte[] f4 = cast(string) x"123F";
immutable ushort[] f5 = cast(immutable ushort[]) x"11";
immutable uint[] f6 = cast(immutable uint[]) x"112233";
immutable ulong[] f7 = cast(immutable ulong[]) x"1122334455";
immutable ulong[] f8 = cast(immutable ulong[]) x"1122334455"w;
immutable uint[] f9 = cast(immutable uint[]) "ABCD";
immutable ushort[] f10 = cast(immutable ushort[]) (x"1122" ~ "");
immutable uint[] f11 = cast(immutable uint[]) x"AABBCCDD"c;

View file

@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(in uint n)` is not callable using argument types `()`
fail_compilation/ice10922.d(10): too few arguments, expected 1, got 0
fail_compilation/ice10922.d(11): Error: function `__lambda4` is not callable using argument types `()`
fail_compilation/ice10922.d(11): too few arguments, expected 1, got 0
fail_compilation/ice10922.d(10): `ice10922.__lambda4(in uint n)` declared here
---
*/

View file

@ -1,14 +1,14 @@
/*
TEST_OUTPUT:
---
----
fail_compilation/ice11856_1.d(18): Error: no property `g` for `A()` of type `A`
fail_compilation/ice11856_1.d(18): the following error occured while looking for a UFCS match
fail_compilation/ice11856_1.d(18): Error: template `ice11856_1.g` is not callable using argument types `!()(A)`
fail_compilation/ice11856_1.d(18): Error: template `g` is not callable using argument types `!()(A)`
fail_compilation/ice11856_1.d(16): Candidate is: `g(T)(T x)`
with `T = A`
must satisfy the following constraint:
` is(typeof(x.f()))`
---
----
*/
struct A {}

View file

@ -1,12 +1,14 @@
/*
TEST_OUTPUT:
---
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
---
----
fail_compilation/ice12501.d(33): Error: function `foo` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(33): expected 1 argument(s), not 2
fail_compilation/ice12501.d(40): `ice12501.foo(int value)` declared here
fail_compilation/ice12501.d(33): Error: function `foo` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(33): expected 1 argument(s), not 2
fail_compilation/ice12501.d(40): `ice12501.foo(int value)` declared here
fail_compilation/ice12501.d(47): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
----
*/
struct Tuple(T...)

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/ice14130.d(10): Error: undefined identifier `Undef`
fail_compilation/ice14130.d(14): Error: template `ice14130.foo` is not callable using argument types `!()(int)`
fail_compilation/ice14130.d(14): Error: template `foo` is not callable using argument types `!()(int)`
fail_compilation/ice14130.d(10): Candidate is: `foo(R, F = Undef)(R r, F s = 0)`
---
*/

View file

@ -1,14 +1,14 @@
/*
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` is not callable using argument types `!()()`
fail_compilation/ice14907.d(21): Error: template `f` is not callable using argument types `!()()`
fail_compilation/ice14907.d(15): Candidate is: `f(int v = f)()`
---
----
*/
struct S(int v = S) {}

View file

@ -1,10 +1,11 @@
/*
TEST_OUTPUT:
---
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))`
---
----
fail_compilation/ice14923.d(23): Error: function `parse` is not callable using argument types `(A)`
fail_compilation/ice14923.d(23): cannot pass argument `b` of type `ice14923.A` to parameter `C a`
fail_compilation/ice14923.d(21): `ice14923.parse(C a)` declared here
fail_compilation/ice14923.d(23): instantiated from here: `bar!((b) => parse(b))`
----
*/
auto bar(alias fun)()

Some files were not shown because too many files have changed in this diff Show more