d: Merge upstream dmd 02a3fafc6, druntime 26b58167, phobos 16cb085b5.

D front-end changes:

    - Import dmd v2.099.0.
    - The deprecation period for D1-style operators has ended, any use
      of the D1 overload operators will now result in a compiler error.
    - `scope' as a type constraint on class, struct, union, and enum
      declarations has been deprecated.
    - Fix segmentation fault when emplacing a new front-end Expression
      node during CTFE (PR104835).

D runtime changes:

    - Import druntime v2.099.0.
    - Fix C bindings for stdint types (PR104738).
    - Fix bus error when allocating new array on the GC (PR104742).
    - Fix bus error when allocating new pointer on the GC (PR104745).

Phobos changes:

    - Import phobos v2.099.0.
    - New function `bind' in `std.functional'.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 02a3fafc6.
	* dmd/VERSION: Update version to v2.099.0.
	* imports.cc (ImportVisitor::visit (EnumDeclaration *)): Don't cache
	decl in front-end AST node.
	(ImportVisitor::visit (AggregateDeclaration *)): Likewise.
	(ImportVisitor::visit (ClassDeclaration *)): Likewise.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 26b58167.
	* src/MERGE: Merge upstream phobos 16cb085b5.
This commit is contained in:
Iain Buclaw 2022-03-13 12:28:05 +01:00
parent 1b85638aff
commit 7e28750395
75 changed files with 1787 additions and 970 deletions

View File

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

View File

@ -1 +1 @@
v2.099.0-rc.1 v2.099.0

View File

@ -662,6 +662,8 @@ struct OutBuffer
return cast(char)data[i]; return cast(char)data[i];
} }
alias opDollar = length;
/*********************************** /***********************************
* Extract the data as a slice and take ownership of it. * Extract the data as a slice and take ownership of it.
* *
@ -879,3 +881,36 @@ unittest
s = unsignedToTempString(29, buf[], 16); s = unsignedToTempString(29, buf[], 16);
assert(s == "1d"); assert(s == "1d");
} }
unittest
{
OutBuffer buf;
buf.writeUTF8(0x0000_0011);
buf.writeUTF8(0x0000_0111);
buf.writeUTF8(0x0000_1111);
buf.writeUTF8(0x0001_1111);
buf.writeUTF8(0x0010_0000);
assert(buf[] == "\x11\U00000111\U00001111\U00011111\U00100000");
buf.reset();
buf.writeUTF16(0x0000_0011);
buf.writeUTF16(0x0010_FFFF);
assert(buf[] == cast(string) "\u0011\U0010FFFF"w);
}
unittest
{
OutBuffer buf;
buf.doindent = true;
const(char)[] s = "abc";
buf.writestring(s);
buf.level += 1;
buf.indent();
buf.writestring("abs");
assert(buf[] == "abc\tabs");
buf.setsize(4);
assert(buf.length == 4);
}

View File

@ -1230,7 +1230,7 @@ UnionExp ArrayLength(Type type, Expression e1)
/* Also return EXP.cantExpression if this fails /* Also return EXP.cantExpression if this fails
*/ */
UnionExp Index(Type type, Expression e1, Expression e2) UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
{ {
UnionExp ue = void; UnionExp ue = void;
Loc loc = e1.loc; Loc loc = e1.loc;
@ -1255,8 +1255,9 @@ UnionExp Index(Type type, Expression e1, Expression e2)
TypeSArray tsa = cast(TypeSArray)e1.type.toBasetype(); TypeSArray tsa = cast(TypeSArray)e1.type.toBasetype();
uinteger_t length = tsa.dim.toInteger(); uinteger_t length = tsa.dim.toInteger();
uinteger_t i = e2.toInteger(); uinteger_t i = e2.toInteger();
if (i >= length) if (i >= length && (e1.op == EXP.arrayLiteral || !indexIsInBounds))
{ {
// C code only checks bounds if an ArrayLiteralExp
e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length); e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length);
emplaceExp!(ErrorExp)(&ue); emplaceExp!(ErrorExp)(&ue);
} }

View File

@ -22,6 +22,7 @@ import dmd.identifier;
import dmd.lexer; import dmd.lexer;
import dmd.parse; import dmd.parse;
import dmd.errors; import dmd.errors;
import dmd.root.array;
import dmd.root.filename; import dmd.root.filename;
import dmd.common.outbuffer; import dmd.common.outbuffer;
import dmd.root.rmem; import dmd.root.rmem;
@ -38,6 +39,24 @@ final class CParser(AST) : Parser!AST
bool addFuncName; /// add declaration of __func__ to function symbol table bool addFuncName; /// add declaration of __func__ to function symbol table
bool importBuiltins; /// seen use of C compiler builtins, so import __builtins; bool importBuiltins; /// seen use of C compiler builtins, so import __builtins;
private
{
structalign_t packalign; // current state of #pragma pack alignment
// #pragma pack stack
Array!Identifier* records; // identifers (or null)
Array!structalign_t* packs; // parallel alignment values
}
/** C allows declaring a function with a typedef:
* typedef int (myfunc)(); myfunc fun;
* but we need to distinguish `fun` being a function as opposed to a variable in the
* parse pass. This is accomplished by having a simple symbol table of typedefs
* where we know, by syntax, if they are function types or non-function types.
* funcTypeIds is the symbol table, of the identifiers of typedefs of function types.
*/
AST.Identifiers funcTypeIds; /// Identifiers in this are typedefs of function types
extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment, extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
const ref TARGET target) const ref TARGET target)
{ {
@ -47,6 +66,7 @@ final class CParser(AST) : Parser!AST
mod = _module; mod = _module;
linkage = LINK.c; linkage = LINK.c;
Ccompile = true; Ccompile = true;
this.packalign.setDefault();
// Configure sizes for C `long`, `long double`, `wchar_t`, ... // Configure sizes for C `long`, `long double`, `wchar_t`, ...
this.boolsize = target.boolsize; this.boolsize = target.boolsize;
@ -130,6 +150,7 @@ final class CParser(AST) : Parser!AST
//printf("cparseStatement()\n"); //printf("cparseStatement()\n");
const funcTypeIdsLengthSave = funcTypeIds.length;
auto symbolsSave = symbols; auto symbolsSave = symbols;
if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope))) if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)))
symbols = new AST.Dsymbols(); symbols = new AST.Dsymbols();
@ -572,6 +593,7 @@ final class CParser(AST) : Parser!AST
if (pEndloc) if (pEndloc)
*pEndloc = prevloc; *pEndloc = prevloc;
symbols = symbolsSave; symbols = symbolsSave;
funcTypeIds.setDim(funcTypeIdsLengthSave);
return s; return s;
} }
@ -1551,6 +1573,7 @@ final class CParser(AST) : Parser!AST
return; return;
} }
const funcTypeIdsLengthSave = funcTypeIds.length;
auto symbolsSave = symbols; auto symbolsSave = symbols;
Specifier specifier; Specifier specifier;
specifier.packalign = this.packalign; specifier.packalign = this.packalign;
@ -1660,11 +1683,13 @@ final class CParser(AST) : Parser!AST
t.value == TOK.leftCurly) // start of compound-statement t.value == TOK.leftCurly) // start of compound-statement
{ {
auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier); auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
funcTypeIds.setDim(funcTypeIdsLengthSave);
symbols = symbolsSave; symbols = symbolsSave;
symbols.push(s); symbols.push(s);
return; return;
} }
AST.Dsymbol s = null; AST.Dsymbol s = null;
funcTypeIds.setDim(funcTypeIdsLengthSave);
symbols = symbolsSave; symbols = symbolsSave;
if (!symbols) if (!symbols)
symbols = new AST.Dsymbols; // lazilly create it symbols = new AST.Dsymbols; // lazilly create it
@ -1722,6 +1747,10 @@ final class CParser(AST) : Parser!AST
} }
} }
} }
else if (isFunctionTypedef(dt))
{
funcTypeIds.push(id); // remember function typedefs
}
if (isalias) if (isalias)
s = new AST.AliasDeclaration(token.loc, id, dt); s = new AST.AliasDeclaration(token.loc, id, dt);
} }
@ -1743,7 +1772,8 @@ final class CParser(AST) : Parser!AST
} }
// declare the symbol // declare the symbol
assert(id); assert(id);
if (dt.isTypeFunction())
if (isFunctionTypedef(dt))
{ {
if (hasInitializer) if (hasInitializer)
error("no initializer for function declaration"); error("no initializer for function declaration");
@ -4546,5 +4576,238 @@ final class CParser(AST) : Parser!AST
return s; return s;
} }
/********************************
* Determines if type t is a function type.
* Make this work without needing semantic analysis.
* Params:
* t = type to test
* Returns:
* true if it represents a function
*/
bool isFunctionTypedef(AST.Type t)
{
//printf("isFunctionTypedef() %s\n", t.toChars());
if (t.isTypeFunction())
return true;
if (auto tid = t.isTypeIdentifier())
{
/* Scan array of typedef identifiers that are an alias for
* a function type
*/
foreach (ftid; funcTypeIds[])
{
if (tid.ident == ftid)
{
return true;
}
}
}
return false;
}
//}
/******************************************************************************/
/********************************* Directive Parser ***************************/
//{
override bool parseSpecialTokenSequence()
{
Token n;
scan(&n);
if (n.value == TOK.int32Literal)
{
poundLine(n, true);
return true;
}
if (n.value == TOK.identifier)
{
if (n.ident == Id.line)
{
poundLine(n, false);
return true;
}
else if (n.ident == Id.__pragma)
{
pragmaDirective(scanloc);
return true;
}
}
error("C preprocessor directive `#%s` is not supported", n.toChars());
return false;
}
/*********************************************
* C11 6.10.6 Pragma directive
* # pragma pp-tokens(opt) new-line
* The C preprocessor sometimes leaves pragma directives in
* the preprocessed output. Ignore them.
* Upon return, p is at start of next line.
*/
private void pragmaDirective(const ref Loc loc)
{
Token n;
scan(&n);
if (n.value == TOK.identifier && n.ident == Id.pack)
return pragmaPack(loc);
skipToNextLine();
}
/*********
* # pragma pack
* https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
* https://docs.microsoft.com/en-us/cpp/preprocessor/pack
* Scanner is on the `pack`
* Params:
* startloc = location to use for error messages
*/
private void pragmaPack(const ref Loc startloc)
{
const loc = startloc;
Token n;
scan(&n);
if (n.value != TOK.leftParenthesis)
{
error(loc, "left parenthesis expected to follow `#pragma pack`");
skipToNextLine();
return;
}
void closingParen()
{
if (n.value != TOK.rightParenthesis)
{
error(loc, "right parenthesis expected to close `#pragma pack(`");
}
skipToNextLine();
}
void setPackAlign(ref const Token t)
{
const n = t.unsvalue;
if (n < 1 || n & (n - 1) || ushort.max < n)
error(loc, "pack must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
packalign.set(cast(uint)n);
packalign.setPack(true);
}
scan(&n);
if (!records)
{
records = new Array!Identifier;
packs = new Array!structalign_t;
}
/* # pragma pack ( show )
*/
if (n.value == TOK.identifier && n.ident == Id.show)
{
if (packalign.isDefault())
warning(startloc, "current pack attribute is default");
else
warning(startloc, "current pack attribute is %d", packalign.get());
scan(&n);
return closingParen();
}
/* # pragma pack ( push )
* # pragma pack ( push , identifier )
* # pragma pack ( push , integer )
* # pragma pack ( push , identifier , integer )
*/
if (n.value == TOK.identifier && n.ident == Id.push)
{
scan(&n);
Identifier record = null;
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
record = n.ident;
scan(&n);
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
this.records.push(record);
this.packs.push(packalign);
return closingParen();
}
/* # pragma pack ( pop )
* # pragma pack ( pop PopList )
* PopList :
* , IdentifierOrInteger
* , IdentifierOrInteger PopList
* IdentifierOrInteger:
* identifier
* integer
*/
if (n.value == TOK.identifier && n.ident == Id.pop)
{
scan(&n);
while (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
for (size_t len = this.records.length; len; --len)
{
if ((*this.records)[len - 1] == n.ident)
{
packalign = (*this.packs)[len - 1];
this.records.setDim(len - 1);
this.packs.setDim(len - 1);
break;
}
}
scan(&n);
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
this.records.push(null);
this.packs.push(packalign);
scan(&n);
}
}
return closingParen();
}
/* # pragma pack ( integer )
*/
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
return closingParen();
}
/* # pragma pack ( )
*/
if (n.value == TOK.rightParenthesis)
{
packalign.setDefault();
return closingParen();
}
error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
skipToNextLine();
}
//} //}
} }

View File

@ -2443,7 +2443,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{ {
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
} }
__gshared const(char)* msg = "cannot form delegate due to covariant return type"; static immutable msg = "cannot form delegate due to covariant return type";
Type tb = t.toBasetype(); Type tb = t.toBasetype();
Type typeb = e.type.toBasetype(); Type typeb = e.type.toBasetype();
@ -2453,7 +2453,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
int offset; int offset;
e.func.tookAddressOf++; e.func.tookAddressOf++;
if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset) if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
e.error("%s", msg); e.error("%s", msg.ptr);
auto result = e.copy(); auto result = e.copy();
result.type = t; result.type = t;
return result; return result;
@ -2469,7 +2469,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{ {
int offset; int offset;
if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset) if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
e.error("%s", msg); e.error("%s", msg.ptr);
if (f != e.func) // if address not already marked as taken if (f != e.func) // if address not already marked as taken
f.tookAddressOf++; f.tookAddressOf++;
auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2); auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
@ -2477,7 +2477,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
return result; return result;
} }
if (e.func.tintro) if (e.func.tintro)
e.error("%s", msg); e.error("%s", msg.ptr);
} }
} }

View File

@ -205,7 +205,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
super(loc, id); super(loc, id);
__gshared const(char)* msg = "only object.d can define this reserved class name"; static immutable msg = "only object.d can define this reserved class name";
if (baseclasses) if (baseclasses)
{ {
@ -232,37 +232,37 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.TypeInfo) if (id == Id.TypeInfo)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.dtypeinfo = this; Type.dtypeinfo = this;
} }
if (id == Id.TypeInfo_Class) if (id == Id.TypeInfo_Class)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoclass = this; Type.typeinfoclass = this;
} }
if (id == Id.TypeInfo_Interface) if (id == Id.TypeInfo_Interface)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfointerface = this; Type.typeinfointerface = this;
} }
if (id == Id.TypeInfo_Struct) if (id == Id.TypeInfo_Struct)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfostruct = this; Type.typeinfostruct = this;
} }
if (id == Id.TypeInfo_Pointer) if (id == Id.TypeInfo_Pointer)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfopointer = this; Type.typeinfopointer = this;
} }
if (id == Id.TypeInfo_Array) if (id == Id.TypeInfo_Array)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoarray = this; Type.typeinfoarray = this;
} }
if (id == Id.TypeInfo_StaticArray) if (id == Id.TypeInfo_StaticArray)
@ -274,61 +274,61 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.TypeInfo_AssociativeArray) if (id == Id.TypeInfo_AssociativeArray)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoassociativearray = this; Type.typeinfoassociativearray = this;
} }
if (id == Id.TypeInfo_Enum) if (id == Id.TypeInfo_Enum)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoenum = this; Type.typeinfoenum = this;
} }
if (id == Id.TypeInfo_Function) if (id == Id.TypeInfo_Function)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfofunction = this; Type.typeinfofunction = this;
} }
if (id == Id.TypeInfo_Delegate) if (id == Id.TypeInfo_Delegate)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfodelegate = this; Type.typeinfodelegate = this;
} }
if (id == Id.TypeInfo_Tuple) if (id == Id.TypeInfo_Tuple)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfotypelist = this; Type.typeinfotypelist = this;
} }
if (id == Id.TypeInfo_Const) if (id == Id.TypeInfo_Const)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoconst = this; Type.typeinfoconst = this;
} }
if (id == Id.TypeInfo_Invariant) if (id == Id.TypeInfo_Invariant)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoinvariant = this; Type.typeinfoinvariant = this;
} }
if (id == Id.TypeInfo_Shared) if (id == Id.TypeInfo_Shared)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfoshared = this; Type.typeinfoshared = this;
} }
if (id == Id.TypeInfo_Wild) if (id == Id.TypeInfo_Wild)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfowild = this; Type.typeinfowild = this;
} }
if (id == Id.TypeInfo_Vector) if (id == Id.TypeInfo_Vector)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
Type.typeinfovector = this; Type.typeinfovector = this;
} }
} }
@ -336,32 +336,32 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.Object) if (id == Id.Object)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
object = this; object = this;
} }
if (id == Id.Throwable) if (id == Id.Throwable)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
throwable = this; throwable = this;
} }
if (id == Id.Exception) if (id == Id.Exception)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
exception = this; exception = this;
} }
if (id == Id.Error) if (id == Id.Error)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
errorException = this; errorException = this;
} }
if (id == Id.cpp_type_info_ptr) if (id == Id.cpp_type_info_ptr)
{ {
if (!inObject) if (!inObject)
error("%s", msg); error("%s", msg.ptr);
cpp_type_info_ptr = this; cpp_type_info_ptr = this;
} }

View File

@ -29,6 +29,7 @@ import dmd.errors;
import dmd.expression; import dmd.expression;
import dmd.func; import dmd.func;
import dmd.globals; import dmd.globals;
import dmd.gluelayer;
import dmd.id; import dmd.id;
import dmd.identifier; import dmd.identifier;
import dmd.init; import dmd.init;
@ -227,6 +228,8 @@ extern (C++) abstract class Declaration : Dsymbol
enum wasRead = 1; // set if AliasDeclaration was read enum wasRead = 1; // set if AliasDeclaration was read
enum ignoreRead = 2; // ignore any reads of AliasDeclaration enum ignoreRead = 2; // ignore any reads of AliasDeclaration
Symbol* isym; // import version of csym
// overridden symbol with pragma(mangle, "...") // overridden symbol with pragma(mangle, "...")
const(char)[] mangleOverride; const(char)[] mangleOverride;
@ -679,10 +682,12 @@ extern (C++) final class TupleDeclaration : Declaration
} }
/*********************************************************** /***********************************************************
* https://dlang.org/spec/declaration.html#AliasDeclaration
*/ */
extern (C++) final class AliasDeclaration : Declaration extern (C++) final class AliasDeclaration : Declaration
{ {
Dsymbol aliassym; Dsymbol aliassym; // alias ident = aliassym;
Dsymbol overnext; // next in overload list Dsymbol overnext; // next in overload list
Dsymbol _import; // !=null if unresolved internal alias for selective import Dsymbol _import; // !=null if unresolved internal alias for selective import

View File

@ -119,6 +119,7 @@ public:
LINK linkage; LINK linkage;
short inuse; // used to detect cycles short inuse; // used to detect cycles
uint8_t adFlags; uint8_t adFlags;
Symbol* isym; // import version of csym
DString mangleOverride; // overridden symbol with pragma(mangle, "...") DString mangleOverride; // overridden symbol with pragma(mangle, "...")
const char *kind() const; const char *kind() const;

View File

@ -675,24 +675,28 @@ extern (C++) final class Module : Package
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars()); //printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
if (global.params.emitMakeDeps)
{
global.params.makeDeps.push(srcfile.toChars());
}
bool success;
if (auto readResult = FileManager.fileManager.lookup(srcfile)) if (auto readResult = FileManager.fileManager.lookup(srcfile))
{ {
srcBuffer = readResult; srcBuffer = readResult;
return true; success = true;
} }
else
auto readResult = File.read(srcfile.toChars());
if (loadSourceBuffer(loc, readResult))
{ {
FileManager.fileManager.add(srcfile, srcBuffer); auto readResult = File.read(srcfile.toChars());
return true; if (loadSourceBuffer(loc, readResult))
{
FileManager.fileManager.add(srcfile, srcBuffer);
success = true;
}
} }
return false; if (success && global.params.emitMakeDeps)
{
global.params.makeDeps.push(srcfile.toChars());
}
return success;
} }
/// syntactic parse /// syntactic parse

View File

@ -245,8 +245,6 @@ extern (C++) class Dsymbol : ASTNode
/// C++ namespace this symbol belongs to /// C++ namespace this symbol belongs to
CPPNamespaceDeclaration cppnamespace; CPPNamespaceDeclaration cppnamespace;
Symbol* csym; // symbol for code generator Symbol* csym; // symbol for code generator
Symbol* isym; // import version of csym
const(char)* comment; // documentation comment for this Dsymbol
const Loc loc; // where defined const Loc loc; // where defined
Scope* _scope; // !=null means context to use for semantic() Scope* _scope; // !=null means context to use for semantic()
const(char)* prettystring; // cached value of toPrettyChars() const(char)* prettystring; // cached value of toPrettyChars()
@ -257,10 +255,6 @@ extern (C++) class Dsymbol : ASTNode
DeprecatedDeclaration depdecl; // customized deprecation message DeprecatedDeclaration depdecl; // customized deprecation message
UserAttributeDeclaration userAttribDecl; // user defined attributes UserAttributeDeclaration userAttribDecl; // user defined attributes
// !=null means there's a ddoc unittest associated with this symbol
// (only use this with ddoc)
UnitTestDeclaration ddocUnittest;
final extern (D) this() final extern (D) this()
{ {
//printf("Dsymbol::Dsymbol(%p)\n", this); //printf("Dsymbol::Dsymbol(%p)\n", this);
@ -811,7 +805,7 @@ extern (C++) class Dsymbol : ASTNode
Dsymbol s2 = sds.symtabLookup(this,ident); Dsymbol s2 = sds.symtabLookup(this,ident);
// If using C tag/prototype/forward declaration rules // If using C tag/prototype/forward declaration rules
if (sc.flags & SCOPE.Cfile) if (sc.flags & SCOPE.Cfile && !this.isImport())
{ {
if (handleTagSymbols(*sc, this, s2, sds)) if (handleTagSymbols(*sc, this, s2, sds))
return; return;
@ -1214,17 +1208,65 @@ extern (C++) class Dsymbol : ASTNode
*/ */
void addComment(const(char)* comment) void addComment(const(char)* comment)
{ {
//if (comment) if (!comment || !*comment)
// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); return;
if (!this.comment)
this.comment = comment; //printf("addComment '%s' to Dsymbol %p '%s'\n", comment, this, toChars());
else if (comment && strcmp(cast(char*)comment, cast(char*)this.comment) != 0) void* h = cast(void*)this; // just the pointer is the key
auto p = h in commentHashTable;
if (!p)
{
commentHashTable[h] = comment;
return;
}
if (strcmp(*p, comment) != 0)
{ {
// Concatenate the two // Concatenate the two
this.comment = Lexer.combineComments(this.comment.toDString(), comment.toDString(), true); *p = Lexer.combineComments((*p).toDString(), comment.toDString(), true);
} }
} }
/// get documentation comment for this Dsymbol
final const(char)* comment()
{
//printf("getcomment: %p '%s'\n", this, this.toChars());
if (auto p = cast(void*)this in commentHashTable)
{
//printf("comment: '%s'\n", *p);
return *p;
}
return null;
}
/* Shell around addComment() to avoid disruption for the moment */
final void comment(const(char)* comment) { addComment(comment); }
private extern (D) __gshared const(char)*[void*] commentHashTable;
/**********************************
* Get ddoc unittest associated with this symbol.
* (only use this with ddoc)
* Returns: ddoc unittest, null if none
*/
final UnitTestDeclaration ddocUnittest()
{
if (auto p = cast(void*)this in ddocUnittestHashTable)
return *p;
return null;
}
/**********************************
* Set ddoc unittest associated with this symbol.
*/
final void ddocUnittest(UnitTestDeclaration utd)
{
ddocUnittestHashTable[cast(void*)this] = utd;
}
private extern (D) __gshared UnitTestDeclaration[void*] ddocUnittestHashTable;
/**************************************** /****************************************
* Returns true if this symbol is defined in a non-root module without instantiation. * Returns true if this symbol is defined in a non-root module without instantiation.
*/ */
@ -1247,6 +1289,18 @@ extern (C++) class Dsymbol : ASTNode
return false; return false;
} }
/**
* Deinitializes the global state of the compiler.
*
* This can be used to restore the state set by `_init` to its original
* state.
*/
static void deinitialize()
{
commentHashTable = commentHashTable.init;
ddocUnittestHashTable = ddocUnittestHashTable.init;
}
/************ /************
*/ */
override void accept(Visitor v) override void accept(Visitor v)

View File

@ -175,8 +175,6 @@ public:
/// C++ namespace this symbol belongs to /// C++ namespace this symbol belongs to
CPPNamespaceDeclaration *namespace_; CPPNamespaceDeclaration *namespace_;
Symbol *csym; // symbol for code generator Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
const utf8_t *comment; // documentation comment for this Dsymbol
Loc loc; // where defined Loc loc; // where defined
Scope *_scope; // !=NULL means context to use for semantic() Scope *_scope; // !=NULL means context to use for semantic()
const utf8_t *prettystring; const utf8_t *prettystring;
@ -185,7 +183,6 @@ public:
unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
DeprecatedDeclaration *depdecl; // customized deprecation message DeprecatedDeclaration *depdecl; // customized deprecation message
UserAttributeDeclaration *userAttribDecl; // user defined attributes UserAttributeDeclaration *userAttribDecl; // user defined attributes
UnitTestDeclaration *ddocUnittest; // !=NULL means there's a ddoc unittest associated with this symbol (only use this with ddoc)
static Dsymbol *create(Identifier *); static Dsymbol *create(Identifier *);
const char *toChars() const; const char *toChars() const;
@ -252,6 +249,10 @@ public:
virtual void checkCtorConstInit() { } virtual void checkCtorConstInit() { }
virtual void addComment(const utf8_t *comment); virtual void addComment(const utf8_t *comment);
const utf8_t *comment(); // current value of comment
UnitTestDeclaration *ddocUnittest();
void ddocUnittest(UnitTestDeclaration *);
bool inNonRoot(); bool inNonRoot();

View File

@ -2140,6 +2140,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Module.dprogress++; Module.dprogress++;
// @@@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; Scope* sce;
if (ed.isAnonymous()) if (ed.isAnonymous())
sce = sc; sce = sc;
@ -3085,6 +3091,25 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
return null; return null;
} }
if (sc.flags & SCOPE.Cfile)
{
/* C11 allows a function to be declared with a typedef, D does not.
*/
if (auto ti = funcdecl.type.isTypeIdentifier())
{
auto tj = ti.typeSemantic(funcdecl.loc, sc);
if (auto tjf = tj.isTypeFunction())
{
/* Copy the type instead of just pointing to it,
* as we don't merge function types
*/
auto tjf2 = new TypeFunction(tjf.parameterList, tjf.next, tjf.linkage);
funcdecl.type = tjf2;
funcdecl.originalType = tjf2;
}
}
}
if (!getFunctionType(funcdecl)) if (!getFunctionType(funcdecl))
return; return;
@ -3550,6 +3575,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
default: default:
{ {
if (vi >= cd.vtbl.length)
{
/* the derived class cd doesn't have its vtbl[] allocated yet.
* https://issues.dlang.org/show_bug.cgi?id=21008
*/
funcdecl.error("circular reference to class `%s`", cd.toChars());
funcdecl.errors = true;
return;
}
FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration(); FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration(); FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
// This function is covariant with fdv // This function is covariant with fdv
@ -4625,6 +4659,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sd.deferred.semantic2(sc); sd.deferred.semantic2(sc);
sd.deferred.semantic3(sc); sd.deferred.semantic3(sc);
} }
// @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.100
// Make an error in 2.110
if (sd.storage_class & STC.scope_)
deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
} }
void interfaceSemantic(ClassDeclaration cd) void interfaceSemantic(ClassDeclaration cd)
@ -5283,12 +5323,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
} }
//printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
// @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.087 // Deprecated in 2.100
// Make an error in 2.091 // Make an error in 2.110
// Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036 // Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
if (0 && // deprecation disabled for now to accommodate existing extensive use if (cldec.storage_class & STC.scope_)
cldec.storage_class & STC.scope_)
deprecation(cldec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site."); deprecation(cldec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
} }

View File

@ -7806,10 +7806,10 @@ struct TemplateInstanceBox
/* Used when a proposed instance is used to see if there's /* Used when a proposed instance is used to see if there's
* an existing instance. * an existing instance.
*/ */
static if (__VERSION__ >= 2099) static if (__VERSION__ < 2099) // https://issues.dlang.org/show_bug.cgi?id=22717
res = (cast()ti).equalsx(cast()s.ti);
else // https://issues.dlang.org/show_bug.cgi?id=22717
res = (cast()s.ti).equalsx(cast()ti); res = (cast()s.ti).equalsx(cast()ti);
else
res = (cast()ti).equalsx(cast()s.ti);
} }
debug (FindExistingInstance) ++(res ? nHits : nCollisions); debug (FindExistingInstance) ++(res ? nHits : nCollisions);

View File

@ -180,6 +180,15 @@ struct _d_dynamicArray final
`); `);
} }
// prevent trailing newlines
version (Windows)
while (buf.length >= 4 && buf[$-4..$] == "\r\n\r\n")
buf.remove(buf.length - 2, 2);
else
while (buf.length >= 2 && buf[$-2..$] == "\n\n")
buf.remove(buf.length - 1, 1);
if (global.params.cxxhdrname is null) if (global.params.cxxhdrname is null)
{ {
// Write to stdout; assume it succeeds // Write to stdout; assume it succeeds

View File

@ -497,7 +497,7 @@ bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag)
{ {
Expression arg = (*ce.arguments)[i]; Expression arg = (*ce.arguments)[i];
if (!arg.type.hasPointers()) if (!arg.type.hasPointers())
return false; continue;
//printf("\targ[%d]: %s\n", i, arg.toChars()); //printf("\targ[%d]: %s\n", i, arg.toChars());
@ -620,7 +620,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
return false; return false;
if (va == fd.vthis) // `this` of a non-static member function is considered to be the first parameter if (va == fd.vthis) // `this` of a non-static member function is considered to be the first parameter
return true; return true;
if (fd.parameters && fd.parameters.length && (*fd.parameters)[0] == va) // va is first parameter if (!fd.vthis && fd.parameters && fd.parameters.length && (*fd.parameters)[0] == va) // va is first parameter
return true; return true;
} }
return false; return false;
@ -1029,7 +1029,6 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
*/ */
!(p.parent == sc.func)) !(p.parent == sc.func))
{ {
// Only look for errors if in module listed on command line
if (global.params.useDIP1000 == FeatureState.enabled // https://issues.dlang.org/show_bug.cgi?id=17029 if (global.params.useDIP1000 == FeatureState.enabled // https://issues.dlang.org/show_bug.cgi?id=17029
&& sc.func.setUnsafe()) // https://issues.dlang.org/show_bug.cgi?id=20868 && sc.func.setUnsafe()) // https://issues.dlang.org/show_bug.cgi?id=20868
{ {
@ -1095,7 +1094,6 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
continue; continue;
// https://dlang.org/spec/function.html#return-ref-parameters // https://dlang.org/spec/function.html#return-ref-parameters
// Only look for errors if in module listed on command line
if (p == sc.func) if (p == sc.func)
{ {
//printf("escaping reference to local ref variable %s\n", v.toChars()); //printf("escaping reference to local ref variable %s\n", v.toChars());
@ -1246,7 +1244,6 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
!(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0) !(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0)
) )
{ {
// Only look for errors if in module listed on command line
// https://issues.dlang.org/show_bug.cgi?id=17029 // https://issues.dlang.org/show_bug.cgi?id=17029
if (global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe()) if (global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe())
{ {
@ -1278,11 +1275,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{ {
if (log) if (log)
{ {
printf("byref `%s`\n", v.toChars()); printf("byref `%s` %s\n", v.toChars(), toChars(buildScopeRef(v.storage_class)));
if (v.storage_class & STC.return_) printf(" return");
if (v.storage_class & STC.ref_) printf(" ref");
if (v.storage_class & STC.scope_) printf(" scope");
printf("\n");
} }
// 'featureState' tells us whether to emit an error or a deprecation, // 'featureState' tells us whether to emit an error or a deprecation,
@ -1714,9 +1707,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
{ {
Parameter p = tf.parameterList[i - j]; Parameter p = tf.parameterList[i - j];
const stc = tf.parameterStorageClass(null, p); const stc = tf.parameterStorageClass(null, p);
if ((stc & (STC.scope_)) && (stc & STC.return_)) ScopeRef psr = buildScopeRef(stc);
if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
arg.accept(this); arg.accept(this);
else if ((stc & (STC.ref_)) && (stc & STC.return_)) else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
{ {
if (tf.isref) if (tf.isref)
{ {
@ -1974,9 +1968,10 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
{ {
Parameter p = tf.parameterList[i - j]; Parameter p = tf.parameterList[i - j];
const stc = tf.parameterStorageClass(null, p); const stc = tf.parameterStorageClass(null, p);
if ((stc & (STC.out_ | STC.ref_)) && (stc & STC.return_)) ScopeRef psr = buildScopeRef(stc);
if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
arg.accept(this); arg.accept(this);
else if ((stc & STC.scope_) && (stc & STC.return_)) else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
{ {
if (auto de = arg.isDelegateExp()) if (auto de = arg.isDelegateExp())
{ {

View File

@ -72,10 +72,15 @@ import dmd.typesem;
import dmd.visitor; import dmd.visitor;
enum LOGSEMANTIC = false; enum LOGSEMANTIC = false;
void emplaceExp(T : Expression, Args...)(void* p, Args args) void emplaceExp(T : Expression, Args...)(void* p, Args args)
{ {
scope tmp = new T(args); static if (__VERSION__ < 2099)
memcpy(p, cast(void*)tmp, __traits(classInstanceSize, T)); const init = typeid(T).initializer;
else
const init = __traits(initSymbol, T);
p[0 .. __traits(classInstanceSize, T)] = init[];
(cast(T)p).__ctor(args);
} }
void emplaceExp(T : UnionExp)(T* p, Expression e) void emplaceExp(T : UnionExp)(T* p, Expression e)
@ -5831,6 +5836,13 @@ extern (C++) final class IndexExp : BinExp
//printf("IndexExp::IndexExp('%s')\n", toChars()); //printf("IndexExp::IndexExp('%s')\n", toChars());
} }
extern (D) this(const ref Loc loc, Expression e1, Expression e2, bool indexIsInBounds)
{
super(loc, EXP.index, __traits(classInstanceSize, IndexExp), e1, e2);
this.indexIsInBounds = indexIsInBounds;
//printf("IndexExp::IndexExp('%s')\n", toChars());
}
override IndexExp syntaxCopy() override IndexExp syntaxCopy()
{ {
auto ie = new IndexExp(loc, e1.syntaxCopy(), e2.syntaxCopy()); auto ie = new IndexExp(loc, e1.syntaxCopy(), e2.syntaxCopy());

View File

@ -5279,6 +5279,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// The mangling change only works for D mangling // The mangling change only works for D mangling
} }
if (!(sc.flags & SCOPE.Cfile))
{ {
/* https://issues.dlang.org/show_bug.cgi?id=21272 /* https://issues.dlang.org/show_bug.cgi?id=21272
* If we are in a foreach body we need to extract the * If we are in a foreach body we need to extract the
@ -7057,19 +7058,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError(); return setError();
} }
} }
else if (exp.e1.op == EXP.call) else if (auto ce = exp.e1.isCallExp())
{ {
CallExp ce = cast(CallExp)exp.e1; if (!checkAddressCall(sc, ce, "take address of"))
if (ce.e1.type.ty == Tfunction) return setError();
{
TypeFunction tf = cast(TypeFunction)ce.e1.type;
if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
&& tf.next.hasPointers() && sc.func.setUnsafe())
{
exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
ce.e1.toChars(), sc.func.toChars());
}
}
} }
else if (exp.e1.op == EXP.index) else if (exp.e1.op == EXP.index)
{ {
@ -7800,7 +7792,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError(); return setError();
Type t1b = exp.e1.type.toBasetype(); Type t1b = exp.e1.type.toBasetype();
if (t1b.ty == Tpointer) if (auto tp = t1b.isTypePointer())
{ {
if (t1b.isPtrToFunction()) if (t1b.isPtrToFunction())
{ {
@ -7809,7 +7801,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
} }
if (!exp.lwr || !exp.upr) if (!exp.lwr || !exp.upr)
{ {
exp.error("need upper and lower bound to slice pointer"); exp.error("upper and lower bounds are needed to slice a pointer");
if (auto ad = isAggregate(tp.next.toBasetype()))
{
auto s = search_function(ad, Id.index);
if (!s) s = search_function(ad, Id.slice);
if (s)
{
auto fd = s.isFuncDeclaration();
if ((fd && !fd.getParameterList().length) || s.isTemplateDeclaration())
{
exp.errorSupplemental(
"pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`",
exp.e1.toChars(),
s.ident.toChars(),
exp.e1.toChars()
);
}
}
}
return setError(); return setError();
} }
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
@ -7844,6 +7856,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (v && !checkAddressVar(sc, exp.e1, v)) if (v && !checkAddressVar(sc, exp.e1, v))
return setError(); return setError();
} }
// https://issues.dlang.org/show_bug.cgi?id=22539
if (auto ce = exp.e1.isCallExp())
{
if (!checkAddressCall(sc, ce, "slice static array of"))
return setError();
}
} }
} }
else if (t1b.ty == Ttuple) else if (t1b.ty == Ttuple)
@ -8446,7 +8464,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (length) if (length)
{ {
auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1)); auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2)); // OR it in, because it might already be set for C array indexing
exp.indexIsInBounds |= bounds.contains(getIntRange(exp.e2));
} }
} }
} }
@ -12943,6 +12962,38 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
return true; return true;
} }
/****************************************************
* Determine if the address of a `ref return` value of
* a function call with type `tf` can be taken safely.
*
* This is currently stricter than necessary: it can be safe to take the
* address of a `ref` with pointer type when the pointer isn't `scope`, but
* that involves inspecting the function arguments and parameter types, which
* is left as a future enhancement.
*
* Params:
* sc = context
* ce = function call in question
* action = for the error message, how the pointer is taken, e.g. "slice static array of"
* Returns:
* `true` if ok, `false` for error
*/
private bool checkAddressCall(Scope* sc, CallExp ce, const(char)* action)
{
if (auto tf = ce.e1.type.isTypeFunction())
{
if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
&& tf.next.hasPointers() && sc.func.setUnsafe())
{
ce.error("cannot %s `ref return` of `%s()` in `@safe` function `%s`",
action, ce.e1.toChars(), sc.func.toChars());
ce.errorSupplemental("return type `%s` has pointers that may be `scope`", tf.next.toChars());
return false;
}
}
return true;
}
/******************************* /*******************************
* Checks the attributes of a function. * Checks the attributes of a function.
* Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`) * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)

View File

@ -159,7 +159,8 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
if (t1.isTypeDArray() || t1.isTypeSArray()) if (t1.isTypeDArray() || t1.isTypeSArray())
{ {
e2 = e2.expressionSemantic(sc).arrayFuncConv(sc); e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
return new IndexExp(ae.loc, e1, e2).expressionSemantic(sc); // C doesn't do array bounds checking, so `true` turns it off
return new IndexExp(ae.loc, e1, e2, true).expressionSemantic(sc);
} }
e1 = e1.arrayFuncConv(sc); // e1 might still be a function call e1 = e1.arrayFuncConv(sc); // e1 might still be a function call
@ -167,7 +168,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
auto t2 = e2.type.toBasetype(); auto t2 = e2.type.toBasetype();
if (t2.isTypeDArray() || t2.isTypeSArray()) if (t2.isTypeDArray() || t2.isTypeSArray())
{ {
return new IndexExp(ae.loc, e2, e1).expressionSemantic(sc); // swap operands return new IndexExp(ae.loc, e2, e1, true).expressionSemantic(sc); // swap operands
} }
e2 = e2.arrayFuncConv(sc); e2 = e2.arrayFuncConv(sc);

View File

@ -68,8 +68,6 @@ class Lexer
ubyte long_doublesize; /// size of C long double, 8 or D real.sizeof ubyte long_doublesize; /// size of C long double, 8 or D real.sizeof
ubyte wchar_tsize; /// size of C wchar_t, 2 or 4 ubyte wchar_tsize; /// size of C wchar_t, 2 or 4
structalign_t packalign; /// current state of #pragma pack alignment (ImportC)
private private
{ {
const(char)* base; // pointer to start of buffer const(char)* base; // pointer to start of buffer
@ -89,10 +87,6 @@ class Lexer
int lastDocLine; // last line of previous doc comment int lastDocLine; // last line of previous doc comment
Token* tokenFreelist; Token* tokenFreelist;
// ImportC #pragma pack stack
Array!Identifier* records; // identifers (or null)
Array!structalign_t* packs; // parallel alignment values
} }
nothrow: nothrow:
@ -124,7 +118,6 @@ class Lexer
this.commentToken = commentToken; this.commentToken = commentToken;
this.inTokenStringConstant = 0; this.inTokenStringConstant = 0;
this.lastDocLine = 0; this.lastDocLine = 0;
this.packalign.setDefault();
//initKeywords(); //initKeywords();
/* If first line starts with '#!', ignore the line /* If first line starts with '#!', ignore the line
*/ */
@ -381,24 +374,18 @@ class Lexer
goto case_ident; goto case_ident;
case 'r': case 'r':
if (p[1] != '"') if (Ccompile || p[1] != '"')
goto case_ident; goto case_ident;
p++; p++;
goto case '`'; goto case '`';
case '`': case '`':
if (Ccompile)
goto default;
wysiwygStringConstant(t); wysiwygStringConstant(t);
return; return;
case 'x':
if (p[1] != '"')
goto case_ident;
p++;
auto start = p;
OutBuffer hexString;
t.value = hexStringConstant(t);
hexString.write(start[0 .. p - start]);
error("Built-in hex string literals are obsolete, use `std.conv.hexString!%s` instead.", hexString.extractChars());
return;
case 'q': case 'q':
if (Ccompile)
goto case_ident;
if (p[1] == '"') if (p[1] == '"')
{ {
p++; p++;
@ -438,7 +425,7 @@ class Lexer
//case 'u': //case 'u':
case 'v': case 'v':
case 'w': case 'w':
/*case 'x':*/ case 'x':
case 'y': case 'y':
case 'z': case 'z':
case 'A': case 'A':
@ -676,6 +663,7 @@ class Lexer
endOfLine(); endOfLine();
continue; continue;
case '+': case '+':
if (!Ccompile)
{ {
int nest; int nest;
startLoc = loc(); startLoc = loc();
@ -745,6 +733,7 @@ class Lexer
} }
continue; continue;
} }
break;
default: default:
break; break;
} }
@ -1051,35 +1040,8 @@ class Lexer
case '#': case '#':
{ {
p++; p++;
Token n; if (parseSpecialTokenSequence())
scan(&n);
if (Ccompile && n.value == TOK.int32Literal)
{
poundLine(n, true);
continue; continue;
}
if (n.value == TOK.identifier)
{
if (n.ident == Id.line)
{
poundLine(n, false);
continue;
}
else if (n.ident == Id.__pragma && Ccompile)
{
pragmaDirective(scanloc);
continue;
}
else
{
const locx = loc();
warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars());
}
}
else if (n.value == TOK.if_)
{
error("C preprocessor directive `#if` is not supported, use `version` or `static if`");
}
t.value = TOK.pound; t.value = TOK.pound;
return; return;
} }
@ -1388,84 +1350,6 @@ class Lexer
} }
} }
/**************************************
* Lex hex strings:
* x"0A ae 34FE BD"
*/
private TOK hexStringConstant(Token* t)
{
Loc start = loc();
uint n = 0;
uint v = ~0; // dead assignment, needed to suppress warning
p++;
stringbuffer.setsize(0);
while (1)
{
dchar c = *p++;
switch (c)
{
case ' ':
case '\t':
case '\v':
case '\f':
continue; // skip white space
case '\r':
if (*p == '\n')
continue; // ignore '\r' if followed by '\n'
// Treat isolated '\r' as if it were a '\n'
goto case '\n';
case '\n':
endOfLine();
continue;
case 0:
case 0x1A:
error("unterminated string constant starting at %s", start.toChars());
t.setString();
// decrement `p`, because it needs to point to the next token (the 0 or 0x1A character is the TOK.endOfFile token).
p--;
return TOK.hexadecimalString;
case '"':
if (n & 1)
{
error("odd number (%d) of hex characters in hex string", n);
stringbuffer.writeByte(v);
}
t.setString(stringbuffer);
stringPostfix(t);
return TOK.hexadecimalString;
default:
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'a' && c <= 'f')
c -= 'a' - 10;
else if (c >= 'A' && c <= 'F')
c -= 'A' - 10;
else if (c & 0x80)
{
p--;
const u = decodeUTF();
p++;
if (u == PS || u == LS)
endOfLine();
else
error("non-hex character \\u%04x in hex string", u);
}
else
error("non-hex character '%c' in hex string", c);
if (n & 1)
{
v = (v << 4) | c;
stringbuffer.writeByte(v);
}
else
v = c;
n++;
break;
}
}
assert(0); // see bug 15731
}
/** /**
Lex a delimited string. Some examples of delimited strings are: Lex a delimited string. Some examples of delimited strings are:
--- ---
@ -2666,6 +2550,37 @@ class Lexer
va_end(args); va_end(args);
} }
/***************************************
* Parse special token sequence:
* Returns:
* true if the special token sequence was handled
* References:
* https://dlang.org/spec/lex.html#special-token-sequence
*/
bool parseSpecialTokenSequence()
{
Token n;
scan(&n);
if (n.value == TOK.identifier)
{
if (n.ident == Id.line)
{
poundLine(n, false);
return true;
}
else
{
const locx = loc();
warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars());
}
}
else if (n.value == TOK.if_)
{
error("C preprocessor directive `#if` is not supported, use `version` or `static if`");
}
return false;
}
/********************************************* /*********************************************
* Parse line/file preprocessor directive: * Parse line/file preprocessor directive:
* #line linnum [filespec] * #line linnum [filespec]
@ -2680,7 +2595,7 @@ class Lexer
* References: * References:
* linemarker https://gcc.gnu.org/onlinedocs/gcc-11.1.0/cpp/Preprocessor-Output.html * linemarker https://gcc.gnu.org/onlinedocs/gcc-11.1.0/cpp/Preprocessor-Output.html
*/ */
private void poundLine(ref Token tok, bool linemarker) final void poundLine(ref Token tok, bool linemarker)
{ {
auto linnum = this.scanloc.linnum; auto linnum = this.scanloc.linnum;
const(char)* filespec = null; const(char)* filespec = null;
@ -2806,183 +2721,10 @@ class Lexer
error(loc, "#line integer [\"filespec\"]\\n expected"); error(loc, "#line integer [\"filespec\"]\\n expected");
} }
/*********************************************
* C11 6.10.6 Pragma directive
* # pragma pp-tokens(opt) new-line
* The C preprocessor sometimes leaves pragma directives in
* the preprocessed output. Ignore them.
* Upon return, p is at start of next line.
*/
private void pragmaDirective(const ref Loc loc)
{
Token n;
scan(&n);
if (n.value == TOK.identifier && n.ident == Id.pack)
return pragmaPack(loc);
skipToNextLine();
}
/*********
* ImportC
* # pragma pack
* https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
* https://docs.microsoft.com/en-us/cpp/preprocessor/pack
* Scanner is on the `pack`
* Params:
* startloc = location to use for error messages
*/
private void pragmaPack(const ref Loc startloc)
{
const loc = startloc;
Token n;
scan(&n);
if (n.value != TOK.leftParenthesis)
{
error(loc, "left parenthesis expected to follow `#pragma pack`");
skipToNextLine();
return;
}
void closingParen()
{
if (n.value != TOK.rightParenthesis)
{
error(loc, "right parenthesis expected to close `#pragma pack(`");
}
skipToNextLine();
}
void setPackAlign(ref const Token t)
{
const n = t.unsvalue;
if (n < 1 || n & (n - 1) || ushort.max < n)
error(loc, "pack must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
packalign.set(cast(uint)n);
packalign.setPack(true);
}
scan(&n);
if (!records)
{
records = new Array!Identifier;
packs = new Array!structalign_t;
}
/* # pragma pack ( show )
*/
if (n.value == TOK.identifier && n.ident == Id.show)
{
if (packalign.isDefault())
warning(startloc, "current pack attribute is default");
else
warning(startloc, "current pack attribute is %d", packalign.get());
scan(&n);
return closingParen();
}
/* # pragma pack ( push )
* # pragma pack ( push , identifier )
* # pragma pack ( push , integer )
* # pragma pack ( push , identifier , integer )
*/
if (n.value == TOK.identifier && n.ident == Id.push)
{
scan(&n);
Identifier record = null;
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
record = n.ident;
scan(&n);
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
this.records.push(record);
this.packs.push(packalign);
return closingParen();
}
/* # pragma pack ( pop )
* # pragma pack ( pop PopList )
* PopList :
* , IdentifierOrInteger
* , IdentifierOrInteger PopList
* IdentifierOrInteger:
* identifier
* integer
*/
if (n.value == TOK.identifier && n.ident == Id.pop)
{
scan(&n);
while (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
for (size_t len = this.records.length; len; --len)
{
if ((*this.records)[len - 1] == n.ident)
{
packalign = (*this.packs)[len - 1];
this.records.setDim(len - 1);
this.packs.setDim(len - 1);
break;
}
}
scan(&n);
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
this.records.push(null);
this.packs.push(packalign);
scan(&n);
}
}
return closingParen();
}
/* # pragma pack ( integer )
*/
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
return closingParen();
}
/* # pragma pack ( )
*/
if (n.value == TOK.rightParenthesis)
{
packalign.setDefault();
return closingParen();
}
error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
skipToNextLine();
}
/*************************************** /***************************************
* Scan forward to start of next line. * Scan forward to start of next line.
*/ */
private void skipToNextLine() final void skipToNextLine()
{ {
while (1) while (1)
{ {
@ -3557,5 +3299,3 @@ unittest
assert(tok == TOK.endOfFile); assert(tok == TOK.endOfFile);
} }
} }

View File

@ -4214,6 +4214,7 @@ extern (C++) final class TypeFunction : TypeNext
inoutParam = 0x0400, // inout on the parameters inoutParam = 0x0400, // inout on the parameters
inoutQual = 0x0800, // inout on the qualifier inoutQual = 0x0800, // inout on the qualifier
isctor = 0x1000, // the function is a constructor isctor = 0x1000, // the function is a constructor
isreturnscope = 0x2000, // `this` is returned by value
} }
LINK linkage; // calling convention LINK linkage; // calling convention
@ -4247,6 +4248,8 @@ extern (C++) final class TypeFunction : TypeNext
this.isref = true; this.isref = true;
if (stc & STC.return_) if (stc & STC.return_)
this.isreturn = true; this.isreturn = true;
if (stc & STC.returnScope)
this.isreturnscope = true;
if (stc & STC.returninferred) if (stc & STC.returninferred)
this.isreturninferred = true; this.isreturninferred = true;
if (stc & STC.scope_) if (stc & STC.scope_)
@ -4285,6 +4288,7 @@ extern (C++) final class TypeFunction : TypeNext
t.isproperty = isproperty; t.isproperty = isproperty;
t.isref = isref; t.isref = isref;
t.isreturn = isreturn; t.isreturn = isreturn;
t.isreturnscope = isreturnscope;
t.isScopeQual = isScopeQual; t.isScopeQual = isScopeQual;
t.isreturninferred = isreturninferred; t.isreturninferred = isreturninferred;
t.isscopeinferred = isscopeinferred; t.isscopeinferred = isscopeinferred;
@ -4507,6 +4511,7 @@ extern (C++) final class TypeFunction : TypeNext
tf.isproperty = t.isproperty; tf.isproperty = t.isproperty;
tf.isref = t.isref; tf.isref = t.isref;
tf.isreturn = t.isreturn; tf.isreturn = t.isreturn;
tf.isreturnscope = t.isreturnscope;
tf.isScopeQual = t.isScopeQual; tf.isScopeQual = t.isScopeQual;
tf.isreturninferred = t.isreturninferred; tf.isreturninferred = t.isreturninferred;
tf.isscopeinferred = t.isscopeinferred; tf.isscopeinferred = t.isscopeinferred;
@ -4573,6 +4578,7 @@ extern (C++) final class TypeFunction : TypeNext
t.isproperty = isproperty; t.isproperty = isproperty;
t.isref = isref; t.isref = isref;
t.isreturn = isreturn; t.isreturn = isreturn;
t.isreturnscope = isreturnscope;
t.isScopeQual = isScopeQual; t.isScopeQual = isScopeQual;
t.isreturninferred = isreturninferred; t.isreturninferred = isreturninferred;
t.isscopeinferred = isscopeinferred; t.isscopeinferred = isscopeinferred;
@ -5136,6 +5142,18 @@ extern (C++) final class TypeFunction : TypeNext
else funcFlags &= ~FunctionFlag.isreturn; else funcFlags &= ~FunctionFlag.isreturn;
} }
/// set or get if the function has the `returnscope` attribute
bool isreturnscope() const pure nothrow @safe @nogc
{
return (funcFlags & FunctionFlag.isreturnscope) != 0;
}
/// ditto
void isreturnscope(bool v) pure nothrow @safe @nogc
{
if (v) funcFlags |= FunctionFlag.isreturnscope;
else funcFlags &= ~FunctionFlag.isreturnscope;
}
/// set or get if the function has the `scope` attribute /// set or get if the function has the `scope` attribute
bool isScopeQual() const pure nothrow @safe @nogc bool isScopeQual() const pure nothrow @safe @nogc
{ {
@ -6384,7 +6402,7 @@ extern (C++) final class TypeClass : Type
/* Conversion derived to const(base) /* Conversion derived to const(base)
*/ */
int offset = 0; int offset = 0;
if (to.isBaseOf(this, &offset) && MODimplicitConv(mod, to.mod)) if (to.isBaseOf(this, &offset) && offset == 0 && MODimplicitConv(mod, to.mod))
{ {
// Disallow: // Disallow:
// derived to base // derived to base

View File

@ -625,6 +625,8 @@ public:
void isref(bool v); void isref(bool v);
bool isreturn() const; bool isreturn() const;
void isreturn(bool v); void isreturn(bool v);
bool isreturnscope() const;
void isreturnscope(bool v);
bool isScopeQual() const; bool isScopeQual() const;
void isScopeQual(bool v); void isScopeQual(bool v);
bool isreturninferred() const; bool isreturninferred() const;

View File

@ -396,13 +396,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
fd = search_function(ad, id); fd = search_function(ad, id);
if (fd) if (fd)
{ {
// @@@DEPRECATED_2.098@@@. // @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088 // Deprecated in 2.088, made an error in 2.100
// Make an error in 2.098 e.error("`%s` is obsolete. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
e.deprecation("`%s` is deprecated. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); return ErrorExp.get();
// Rewrite +e1 as e1.add()
result = build_overload(e.loc, sc, e.e1, null, fd);
return result;
} }
} }
// Didn't find it. Forward to aliasthis // Didn't find it. Forward to aliasthis
@ -670,13 +667,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
s = search_function(ad1, id); s = search_function(ad1, id);
if (s && id != Id.assign) if (s && id != Id.assign)
{ {
// @@@DEPRECATED_2.098@@@. // @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088 // Deprecated in 2.088, made an error in 2.100
// Make an error in 2.098
if (id == Id.postinc || id == Id.postdec) if (id == Id.postinc || id == Id.postdec)
e.deprecation("`%s` is deprecated. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); e.error("`%s` is obsolete. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
else else
e.deprecation("`%s` is deprecated. Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); e.error("`%s` is obsolete. Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
return ErrorExp.get();
} }
} }
if (ad2 && id_r) if (ad2 && id_r)
@ -689,10 +686,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
s_r = null; s_r = null;
if (s_r) if (s_r)
{ {
// @@@DEPRECATED_2.098@@@. // @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088 // Deprecated in 2.088, made an error in 2.100
// Make an error in 2.098 e.error("`%s` is obsolete. Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr);
e.deprecation("`%s` is deprecated. Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr); return ErrorExp.get();
} }
} }
} }
@ -1232,12 +1229,12 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
s = search_function(ad1, id); s = search_function(ad1, id);
if (s) if (s)
{ {
// @@@DEPRECATED_2.098@@@. // @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088 // Deprecated in 2.088, made an error in 2.100
// Make an error in 2.098
scope char[] op = EXPtoString(e.op).dup; scope char[] op = EXPtoString(e.op).dup;
op[$-1] = '\0'; // remove trailing `=` op[$-1] = '\0'; // remove trailing `=`
e.deprecation("`%s` is deprecated. Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr); e.error("`%s` is obsolete. Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr);
return ErrorExp.get();
} }
} }
@ -1552,7 +1549,8 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
* Params: * Params:
* fes = the foreach statement * fes = the foreach statement
* sc = context * sc = context
* sapply = null or opApply or delegate * sapply = null or opApply or delegate, overload resolution has not been done.
* Do overload resolution on sapply.
* Returns: * Returns:
* false for errors * false for errors
*/ */
@ -1588,8 +1586,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
*/ */
if (FuncDeclaration fd = sapply.isFuncDeclaration()) if (FuncDeclaration fd = sapply.isFuncDeclaration())
{ {
auto fdapply = findBestOpApplyMatch(ethis, fd, fes.parameters); if (auto fdapply = findBestOpApplyMatch(ethis, fd, fes.parameters))
if (fdapply)
{ {
// Fill in any missing types on foreach parameters[] // Fill in any missing types on foreach parameters[]
matchParamsToOpApply(fdapply.type.isTypeFunction(), fes.parameters, true); matchParamsToOpApply(fdapply.type.isTypeFunction(), fes.parameters, true);
@ -1598,7 +1595,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
} }
return false; return false;
} }
return sapply !is null; return true; // shouldn't this be false?
} }
Parameter p = (*fes.parameters)[0]; Parameter p = (*fes.parameters)[0];

View File

@ -338,9 +338,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
void visitTuple(TupleExp e) void visitTuple(TupleExp e)
{ {
expOptimize(e.e0, WANTvalue); expOptimize(e.e0, WANTvalue);
for (size_t i = 0; i < e.exps.dim; i++) foreach (ref ex; (*e.exps)[])
{ {
expOptimize((*e.exps)[i], WANTvalue); expOptimize(ex, WANTvalue);
} }
} }
@ -349,9 +349,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.elements) if (e.elements)
{ {
expOptimize(e.basis, result & WANTexpand); expOptimize(e.basis, result & WANTexpand);
for (size_t i = 0; i < e.elements.dim; i++) foreach (ref ex; (*e.elements)[])
{ {
expOptimize((*e.elements)[i], result & WANTexpand); expOptimize(ex, result & WANTexpand);
} }
} }
} }
@ -359,9 +359,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
void visitAssocArrayLiteral(AssocArrayLiteralExp e) void visitAssocArrayLiteral(AssocArrayLiteralExp e)
{ {
assert(e.keys.dim == e.values.dim); assert(e.keys.dim == e.values.dim);
for (size_t i = 0; i < e.keys.dim; i++) foreach (i, ref ekey; (*e.keys)[])
{ {
expOptimize((*e.keys)[i], result & WANTexpand); expOptimize(ekey, result & WANTexpand);
expOptimize((*e.values)[i], result & WANTexpand); expOptimize((*e.values)[i], result & WANTexpand);
} }
} }
@ -374,9 +374,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
e.stageflags |= stageOptimize; e.stageflags |= stageOptimize;
if (e.elements) if (e.elements)
{ {
for (size_t i = 0; i < e.elements.dim; i++) foreach (ref ex; (*e.elements)[])
{ {
expOptimize((*e.elements)[i], result & WANTexpand); expOptimize(ex, result & WANTexpand);
} }
} }
e.stageflags = old; e.stageflags = old;
@ -647,9 +647,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// Optimize parameters // Optimize parameters
if (e.arguments) if (e.arguments)
{ {
for (size_t i = 0; i < e.arguments.dim; i++) foreach (ref arg; (*e.arguments)[])
{ {
expOptimize((*e.arguments)[i], WANTvalue); expOptimize(arg, WANTvalue);
} }
} }
} }
@ -663,16 +663,16 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.arguments) if (e.arguments)
{ {
Type t1 = e.e1.type.toBasetype(); Type t1 = e.e1.type.toBasetype();
if (t1.ty == Tdelegate) if (auto td = t1.isTypeDelegate())
t1 = t1.nextOf(); t1 = td.next;
// t1 can apparently be void for __ArrayDtor(T) calls // t1 can apparently be void for __ArrayDtor(T) calls
if (auto tf = t1.isTypeFunction()) if (auto tf = t1.isTypeFunction())
{ {
for (size_t i = 0; i < e.arguments.dim; i++) foreach (i, ref arg; (*e.arguments)[])
{ {
Parameter p = tf.parameterList[i]; Parameter p = tf.parameterList[i];
bool keep = p && p.isReference(); bool keep = p && p.isReference();
expOptimize((*e.arguments)[i], WANTvalue, keep); expOptimize(arg, WANTvalue, keep);
} }
} }
} }
@ -719,14 +719,17 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
} }
} }
// Returning e.e1 with changing its type
void returnE_e1()
{
ret = (e1old == e.e1 ? e.e1.copy() : e.e1);
ret.type = e.type;
}
if (e.e1.op == EXP.structLiteral && e.e1.type.implicitConvTo(e.type) >= MATCH.constant) if (e.e1.op == EXP.structLiteral && e.e1.type.implicitConvTo(e.type) >= MATCH.constant)
{ {
//printf(" returning2 %s\n", e.e1.toChars()); //printf(" returning2 %s\n", e.e1.toChars());
L1: return returnE_e1();
// Returning e1 with changing its type
ret = (e1old == e.e1 ? e.e1.copy() : e.e1);
ret.type = e.type;
return;
} }
/* The first test here is to prevent infinite loops /* The first test here is to prevent infinite loops
*/ */
@ -738,7 +741,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.e1.op == EXP.null_ && (e.type.ty == Tpointer || e.type.ty == Tclass || e.type.ty == Tarray)) if (e.e1.op == EXP.null_ && (e.type.ty == Tpointer || e.type.ty == Tclass || e.type.ty == Tarray))
{ {
//printf(" returning3 %s\n", e.e1.toChars()); //printf(" returning3 %s\n", e.e1.toChars());
goto L1; return returnE_e1();
} }
if (e.type.ty == Tclass && e.e1.type.ty == Tclass) if (e.type.ty == Tclass && e.e1.type.ty == Tclass)
{ {
@ -750,7 +753,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (cdfrom.errors || cdto.errors) if (cdfrom.errors || cdto.errors)
return error(); return error();
if (cdto == ClassDeclaration.object && !cdfrom.isInterfaceDeclaration()) if (cdto == ClassDeclaration.object && !cdfrom.isInterfaceDeclaration())
goto L1; // can always convert a class to Object return returnE_e1(); // can always convert a class to Object
// Need to determine correct offset before optimizing away the cast. // Need to determine correct offset before optimizing away the cast.
// https://issues.dlang.org/show_bug.cgi?id=16980 // https://issues.dlang.org/show_bug.cgi?id=16980
cdfrom.size(e.loc); cdfrom.size(e.loc);
@ -760,13 +763,13 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (cdto.isBaseOf(cdfrom, &offset) && offset == 0) if (cdto.isBaseOf(cdfrom, &offset) && offset == 0)
{ {
//printf(" returning4 %s\n", e.e1.toChars()); //printf(" returning4 %s\n", e.e1.toChars());
goto L1; return returnE_e1();
} }
} }
if (e.e1.type.mutableOf().unSharedOf().equals(e.to.mutableOf().unSharedOf())) if (e.e1.type.mutableOf().unSharedOf().equals(e.to.mutableOf().unSharedOf()))
{ {
//printf(" returning5 %s\n", e.e1.toChars()); //printf(" returning5 %s\n", e.e1.toChars());
goto L1; return returnE_e1();
} }
if (e.e1.isConst()) if (e.e1.isConst())
{ {
@ -781,7 +784,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return error(); return error();
if (esz == e1sz) if (esz == e1sz)
goto L1; return returnE_e1();
} }
return; return;
} }
@ -1065,7 +1068,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// Don't optimize to an array literal element directly in case an lvalue is requested // Don't optimize to an array literal element directly in case an lvalue is requested
if (keepLvalue && ex.op == EXP.arrayLiteral) if (keepLvalue && ex.op == EXP.arrayLiteral)
return; return;
ret = Index(e.type, ex, e.e2).copy(); ret = Index(e.type, ex, e.e2, e.indexIsInBounds).copy();
if (CTFEExp.isCantExp(ret) || (!ret.isErrorExp() && keepLvalue && !ret.isLvalue())) if (CTFEExp.isCantExp(ret) || (!ret.isErrorExp() && keepLvalue && !ret.isLvalue()))
ret = e; ret = e;
} }

View File

@ -1971,7 +1971,6 @@ class Parser(AST) : Lexer
case TOK.wcharLiteral: case TOK.wcharLiteral:
case TOK.dcharLiteral: case TOK.dcharLiteral:
case TOK.string_: case TOK.string_:
case TOK.hexadecimalString:
case TOK.file: case TOK.file:
case TOK.fileFullPath: case TOK.fileFullPath:
case TOK.line: case TOK.line:
@ -5623,7 +5622,6 @@ LagainStc:
case TOK.true_: case TOK.true_:
case TOK.false_: case TOK.false_:
case TOK.string_: case TOK.string_:
case TOK.hexadecimalString:
case TOK.leftParenthesis: case TOK.leftParenthesis:
case TOK.cast_: case TOK.cast_:
case TOK.mul: case TOK.mul:
@ -7106,7 +7104,6 @@ LagainStc:
case TOK.wcharLiteral: case TOK.wcharLiteral:
case TOK.dcharLiteral: case TOK.dcharLiteral:
case TOK.string_: case TOK.string_:
case TOK.hexadecimalString:
case TOK.file: case TOK.file:
case TOK.fileFullPath: case TOK.fileFullPath:
case TOK.line: case TOK.line:
@ -7987,7 +7984,6 @@ LagainStc:
break; break;
case TOK.string_: case TOK.string_:
case TOK.hexadecimalString:
{ {
// cat adjacent strings // cat adjacent strings
auto s = token.ustring; auto s = token.ustring;
@ -7997,7 +7993,7 @@ LagainStc:
{ {
const prev = token; const prev = token;
nextToken(); nextToken();
if (token.value == TOK.string_ || token.value == TOK.hexadecimalString) if (token.value == TOK.string_)
{ {
if (token.postfix) if (token.postfix)
{ {

View File

@ -866,7 +866,6 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
assert(t.ty == Tdelegate); assert(t.ty == Tdelegate);
tfld = cast(TypeFunction)t.nextOf(); tfld = cast(TypeFunction)t.nextOf();
} }
//printf("tfld = %s\n", tfld.toChars());
} }
} }
} }
@ -1442,12 +1441,12 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
/* Call: /* Call:
* _aApply(aggr, flde) * _aApply(aggr, flde)
*/ */
__gshared const(char)** fntab = static immutable fntab =
[ [
"cc", "cw", "cd", "cc", "cw", "cd",
"wc", "cc", "wd", "wc", "cc", "wd",
"dc", "dw", "dd" "dc", "dw", "dd"
]; ];
const(size_t) BUFFER_LEN = 7 + 1 + 2 + dim.sizeof * 3 + 1; const(size_t) BUFFER_LEN = 7 + 1 + 2 + dim.sizeof * 3 + 1;
char[BUFFER_LEN] fdname; char[BUFFER_LEN] fdname;
@ -1470,7 +1469,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
assert(0); assert(0);
} }
const(char)* r = (fs.op == TOK.foreach_reverse_) ? "R" : ""; const(char)* r = (fs.op == TOK.foreach_reverse_) ? "R" : "";
int j = sprintf(fdname.ptr, "_aApply%s%.*s%llu", r, 2, fntab[flag], cast(ulong)dim); int j = sprintf(fdname.ptr, "_aApply%s%.*s%llu", r, 2, fntab[flag].ptr, cast(ulong)dim);
assert(j < BUFFER_LEN); assert(j < BUFFER_LEN);
FuncDeclaration fdapply; FuncDeclaration fdapply;
@ -2475,68 +2474,66 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
Expression initialExp = cs.exp; Expression initialExp = cs.exp;
// The switch'ed value has errors and doesn't provide the actual type // The switch'ed value has errors and doesn't provide the actual type
// Don't touch the case to not replace it with an `ErrorExp` even if it is valid // Omit the cast to enable further semantic (exluding the check for matching types)
if (sw.condition.type && !sw.condition.type.isTypeError()) if (sw.condition.type && !sw.condition.type.isTypeError())
{
cs.exp = cs.exp.implicitCastTo(sc, sw.condition.type); cs.exp = cs.exp.implicitCastTo(sc, sw.condition.type);
cs.exp = cs.exp.optimize(WANTvalue | WANTexpand); cs.exp = cs.exp.optimize(WANTvalue | WANTexpand);
Expression e = cs.exp; Expression e = cs.exp;
// Remove all the casts the user and/or implicitCastTo may introduce // Remove all the casts the user and/or implicitCastTo may introduce
// otherwise we'd sometimes fail the check below. // otherwise we'd sometimes fail the check below.
while (e.op == EXP.cast_) while (e.op == EXP.cast_)
e = (cast(CastExp)e).e1; e = (cast(CastExp)e).e1;
/* This is where variables are allowed as case expressions. /* This is where variables are allowed as case expressions.
*/ */
if (e.op == EXP.variable) if (e.op == EXP.variable)
{
VarExp ve = cast(VarExp)e;
VarDeclaration v = ve.var.isVarDeclaration();
Type t = cs.exp.type.toBasetype();
if (v && (t.isintegral() || t.ty == Tclass))
{ {
VarExp ve = cast(VarExp)e; /* Flag that we need to do special code generation
VarDeclaration v = ve.var.isVarDeclaration(); * for this, i.e. generate a sequence of if-then-else
Type t = cs.exp.type.toBasetype(); */
if (v && (t.isintegral() || t.ty == Tclass)) sw.hasVars = 1;
/* TODO check if v can be uninitialized at that point.
*/
if (!v.isConst() && !v.isImmutable())
{ {
/* Flag that we need to do special code generation cs.error("`case` variables have to be `const` or `immutable`");
* for this, i.e. generate a sequence of if-then-else }
*/
sw.hasVars = 1;
/* TODO check if v can be uninitialized at that point. if (sw.isFinal)
*/ {
if (!v.isConst() && !v.isImmutable()) cs.error("`case` variables not allowed in `final switch` statements");
{ errors = true;
cs.error("`case` variables have to be `const` or `immutable`"); }
}
if (sw.isFinal) /* Find the outermost scope `scx` that set `sw`.
* Then search scope `scx` for a declaration of `v`.
*/
for (Scope* scx = sc; scx; scx = scx.enclosing)
{
if (scx.enclosing && scx.enclosing.sw == sw)
continue;
assert(scx.sw == sw);
if (!scx.search(cs.exp.loc, v.ident, null))
{ {
cs.error("`case` variables not allowed in `final switch` statements"); cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
v.toChars(), v.loc.toChars());
errors = true; errors = true;
} }
break;
/* Find the outermost scope `scx` that set `sw`.
* Then search scope `scx` for a declaration of `v`.
*/
for (Scope* scx = sc; scx; scx = scx.enclosing)
{
if (scx.enclosing && scx.enclosing.sw == sw)
continue;
assert(scx.sw == sw);
if (!scx.search(cs.exp.loc, v.ident, null))
{
cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
v.toChars(), v.loc.toChars());
errors = true;
}
break;
}
goto L1;
} }
goto L1;
} }
else
cs.exp = cs.exp.ctfeInterpret();
} }
else
cs.exp = cs.exp.ctfeInterpret();
if (StringExp se = cs.exp.toStringExp()) if (StringExp se = cs.exp.toStringExp())
cs.exp = se; cs.exp = se;

View File

@ -124,7 +124,6 @@ enum TOK : ubyte
// Leaf operators // Leaf operators
identifier, identifier,
string_, string_,
hexadecimalString,
this_, this_,
super_, super_,
error, error,
@ -854,8 +853,6 @@ extern (C++) struct Token
TOK.wchar_tLiteral: "wchar_tv", TOK.wchar_tLiteral: "wchar_tv",
TOK.whitespace: "whitespace", TOK.whitespace: "whitespace",
TOK.hexadecimalString: "xstring",
// C only keywords // C only keywords
TOK.inline : "inline", TOK.inline : "inline",
TOK.register : "register", TOK.register : "register",
@ -1008,24 +1005,6 @@ nothrow:
p = buf.extractSlice().ptr; p = buf.extractSlice().ptr;
} }
break; break;
case TOK.hexadecimalString:
{
OutBuffer buf;
buf.writeByte('x');
buf.writeByte('"');
foreach (size_t i; 0 .. len)
{
if (i)
buf.writeByte(' ');
buf.printf("%02x", ustring[i]);
}
buf.writeByte('"');
if (postfix)
buf.writeByte(postfix);
buf.writeByte(0);
p = buf.extractSlice().ptr;
break;
}
case TOK.identifier: case TOK.identifier:
case TOK.enum_: case TOK.enum_:
case TOK.struct_: case TOK.struct_:

View File

@ -133,7 +133,6 @@ enum class TOK : unsigned char
// Leaf operators // Leaf operators
identifier, identifier,
string_, string_,
hexadecimalString,
this_, this_,
super_, super_,
error, error,

View File

@ -666,9 +666,13 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
Type visitType(Type t) Type visitType(Type t)
{ {
// @@@DEPRECATED_2.110@@@
// Use of `cent` and `ucent` has always been an error.
// Starting from 2.100, recommend core.int128 as a replace for the
// lack of compiler support.
if (t.ty == Tint128 || t.ty == Tuns128) if (t.ty == Tint128 || t.ty == Tuns128)
{ {
.error(loc, "`cent` and `ucent` types not implemented"); .error(loc, "`cent` and `ucent` types are obsolete, use `core.int128.Cent` instead");
return error(); return error();
} }
@ -1188,6 +1192,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
tf.isref = true; tf.isref = true;
if (sc.stc & STC.return_) if (sc.stc & STC.return_)
tf.isreturn = true; tf.isreturn = true;
if (sc.stc & STC.returnScope)
tf.isreturnscope = true;
if (sc.stc & STC.returninferred) if (sc.stc & STC.returninferred)
tf.isreturninferred = true; tf.isreturninferred = true;
if (sc.stc & STC.scope_) if (sc.stc & STC.scope_)
@ -3828,10 +3834,10 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
* e.opDot().ident * e.opDot().ident
*/ */
e = build_overload(e.loc, sc, e, null, fd); e = build_overload(e.loc, sc, e, null, fd);
// @@@DEPRECATED_2.092@@@. // @@@DEPRECATED_2.110@@@.
e.deprecation("`opDot` is deprecated. Use `alias this`"); // Deprecated in 2.082, made an error in 2.100.
e = new DotIdExp(e.loc, e, ident); e.error("`opDot` is obsolete. Use `alias this`");
return returnExp(e.expressionSemantic(sc)); return ErrorExp.get();
} }
/* Look for overloaded opDispatch to see if we should forward request /* Look for overloaded opDispatch to see if we should forward request

View File

@ -106,20 +106,20 @@ public:
tree type = build_ctype (d->type); tree type = build_ctype (d->type);
/* Not all kinds of D enums create a TYPE_DECL. */ /* Not all kinds of D enums create a TYPE_DECL. */
if (TREE_CODE (type) == ENUMERAL_TYPE) if (TREE_CODE (type) == ENUMERAL_TYPE)
d->isym = this->make_import (TYPE_STUB_DECL (type)); this->result_ = this->make_import (TYPE_STUB_DECL (type));
} }
void visit (AggregateDeclaration *d) void visit (AggregateDeclaration *d)
{ {
tree type = build_ctype (d->type); tree type = build_ctype (d->type);
d->isym = this->make_import (TYPE_STUB_DECL (type)); this->result_ = this->make_import (TYPE_STUB_DECL (type));
} }
void visit (ClassDeclaration *d) void visit (ClassDeclaration *d)
{ {
/* Want the RECORD_TYPE, not POINTER_TYPE. */ /* Want the RECORD_TYPE, not POINTER_TYPE. */
tree type = TREE_TYPE (build_ctype (d->type)); tree type = TREE_TYPE (build_ctype (d->type));
d->isym = this->make_import (TYPE_STUB_DECL (type)); this->result_ = this->make_import (TYPE_STUB_DECL (type));
} }
/* For now, ignore importing other kinds of dsymbols. */ /* For now, ignore importing other kinds of dsymbols. */

View File

@ -196,8 +196,7 @@ static assert(is( X!( C***, B*** ) == const(B**)* )); // `B***`
static assert(is( X!( C*, I* ) == I* )); static assert(is( X!( C*, I* ) == I* ));
static assert(is( X!( I*, C* ) == I* )); static assert(is( X!( I*, C* ) == I* ));
//static assert(Error!( C**, I** )); static assert(Error!( C**, I** ));
static assert(is( X!( C**, I** ) == const(I*)* ));
static assert(Error!( C*, D* )); // should work static assert(Error!( C*, D* )); // should work
@ -304,15 +303,13 @@ static assert(is( X!(C[4], B[4]) ));
static assert(Error!( C[4], I[4] )); static assert(Error!( C[4], I[4] ));
static assert(Error!( C[4], D[4] )); static assert(Error!( C[4], D[4] ));
static assert(is( X!( C[4], const(B)[4] ) == const(B)[4] )); static assert(is( X!( C[4], const(B)[4] ) == const(B)[4] ));
//static assert(Error!( C[4], const(I)[4] )); static assert(Error!( C[4], const(I)[4] ));
static assert(is( X!( C[4], const(I)[4] ) == const(I)[] ));
static assert(Error!( C[4], const(D)[4] )); static assert(Error!( C[4], const(D)[4] ));
static assert(Error!( C*[4], B*[4] )); static assert(Error!( C*[4], B*[4] ));
static assert(Error!( C*[4], I*[4] )); static assert(Error!( C*[4], I*[4] ));
static assert(Error!( C*[4], D*[4] )); static assert(Error!( C*[4], D*[4] ));
static assert(is( X!( C*[4], const(B*)[4] ) == const(B*)[] )); // !? static assert(is( X!( C*[4], const(B*)[4] ) == const(B*)[] )); // !?
//static assert(Error!( C*[4], const(I*)[4] )); static assert(Error!( C*[4], const(I*)[4] ));
static assert(is( X!( C*[4], const(I*)[4] ) == const(I*)[] ));
static assert(Error!( C*[4], const(D*)[4] )); static assert(Error!( C*[4], const(D*)[4] ));
static assert(Error!( C*[4], B**[4] )); static assert(Error!( C*[4], B**[4] ));
static assert(Error!( C*[4], const(B*)*[4] )); static assert(Error!( C*[4], const(B*)*[4] ));

View File

@ -1,3 +1,8 @@
/* TEST_OUTPUT:
---
compilable/test7172.d(14): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
---
*/
void main() void main()
{ {
abstract class AbstractC{} abstract class AbstractC{}

View File

@ -2,47 +2,47 @@
REQUIRED_ARGS: -de REQUIRED_ARGS: -de
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/dep_d1_ops.d(105): Deprecation: `opAdd` is deprecated. Use `opBinary(string op)(...) if (op == "+")` instead. fail_compilation/dep_d1_ops.d(105): Error: `opAdd` is obsolete. Use `opBinary(string op)(...) if (op == "+")` instead.
fail_compilation/dep_d1_ops.d(106): Deprecation: `opAdd_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "+")` instead. fail_compilation/dep_d1_ops.d(106): Error: `opAdd_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "+")` instead.
fail_compilation/dep_d1_ops.d(107): Deprecation: `opSub` is deprecated. Use `opBinary(string op)(...) if (op == "-")` instead. fail_compilation/dep_d1_ops.d(107): Error: `opSub` is obsolete. Use `opBinary(string op)(...) if (op == "-")` instead.
fail_compilation/dep_d1_ops.d(108): Deprecation: `opSub_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "-")` instead. fail_compilation/dep_d1_ops.d(108): Error: `opSub_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "-")` instead.
fail_compilation/dep_d1_ops.d(109): Deprecation: `opMul` is deprecated. Use `opBinary(string op)(...) if (op == "*")` instead. fail_compilation/dep_d1_ops.d(109): Error: `opMul` is obsolete. Use `opBinary(string op)(...) if (op == "*")` instead.
fail_compilation/dep_d1_ops.d(110): Deprecation: `opMul_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "*")` instead. fail_compilation/dep_d1_ops.d(110): Error: `opMul_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "*")` instead.
fail_compilation/dep_d1_ops.d(111): Deprecation: `opDiv` is deprecated. Use `opBinary(string op)(...) if (op == "/")` instead. fail_compilation/dep_d1_ops.d(111): Error: `opDiv` is obsolete. Use `opBinary(string op)(...) if (op == "/")` instead.
fail_compilation/dep_d1_ops.d(112): Deprecation: `opDiv_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "/")` instead. fail_compilation/dep_d1_ops.d(112): Error: `opDiv_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "/")` instead.
fail_compilation/dep_d1_ops.d(113): Deprecation: `opMod` is deprecated. Use `opBinary(string op)(...) if (op == "%")` instead. fail_compilation/dep_d1_ops.d(113): Error: `opMod` is obsolete. Use `opBinary(string op)(...) if (op == "%")` instead.
fail_compilation/dep_d1_ops.d(114): Deprecation: `opMod_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "%")` instead. fail_compilation/dep_d1_ops.d(114): Error: `opMod_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "%")` instead.
fail_compilation/dep_d1_ops.d(116): Deprecation: `opAnd` is deprecated. Use `opBinary(string op)(...) if (op == "&")` instead. fail_compilation/dep_d1_ops.d(116): Error: `opAnd` is obsolete. Use `opBinary(string op)(...) if (op == "&")` instead.
fail_compilation/dep_d1_ops.d(117): Deprecation: `opOr` is deprecated. Use `opBinary(string op)(...) if (op == "|")` instead. fail_compilation/dep_d1_ops.d(117): Error: `opOr` is obsolete. Use `opBinary(string op)(...) if (op == "|")` instead.
fail_compilation/dep_d1_ops.d(118): Deprecation: `opXor` is deprecated. Use `opBinary(string op)(...) if (op == "^")` instead. fail_compilation/dep_d1_ops.d(118): Error: `opXor` is obsolete. Use `opBinary(string op)(...) if (op == "^")` instead.
fail_compilation/dep_d1_ops.d(120): Deprecation: `opShl` is deprecated. Use `opBinary(string op)(...) if (op == "<<")` instead. fail_compilation/dep_d1_ops.d(120): Error: `opShl` is obsolete. Use `opBinary(string op)(...) if (op == "<<")` instead.
fail_compilation/dep_d1_ops.d(121): Deprecation: `opShl_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "<<")` instead. fail_compilation/dep_d1_ops.d(121): Error: `opShl_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "<<")` instead.
fail_compilation/dep_d1_ops.d(122): Deprecation: `opShr` is deprecated. Use `opBinary(string op)(...) if (op == ">>")` instead. fail_compilation/dep_d1_ops.d(122): Error: `opShr` is obsolete. Use `opBinary(string op)(...) if (op == ">>")` instead.
fail_compilation/dep_d1_ops.d(123): Deprecation: `opShr_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == ">>")` instead. fail_compilation/dep_d1_ops.d(123): Error: `opShr_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == ">>")` instead.
fail_compilation/dep_d1_ops.d(124): Deprecation: `opUShr` is deprecated. Use `opBinary(string op)(...) if (op == ">>>")` instead. fail_compilation/dep_d1_ops.d(124): Error: `opUShr` is obsolete. Use `opBinary(string op)(...) if (op == ">>>")` instead.
fail_compilation/dep_d1_ops.d(125): Deprecation: `opUShr_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == ">>>")` instead. fail_compilation/dep_d1_ops.d(125): Error: `opUShr_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == ">>>")` instead.
fail_compilation/dep_d1_ops.d(127): Deprecation: `opCat` is deprecated. Use `opBinary(string op)(...) if (op == "~")` instead. fail_compilation/dep_d1_ops.d(127): Error: `opCat` is obsolete. Use `opBinary(string op)(...) if (op == "~")` instead.
fail_compilation/dep_d1_ops.d(128): Deprecation: `opCat_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "~")` instead. fail_compilation/dep_d1_ops.d(128): Error: `opCat_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "~")` instead.
fail_compilation/dep_d1_ops.d(130): Deprecation: `opNeg` is deprecated. Use `opUnary(string op)() if (op == "-")` instead. fail_compilation/dep_d1_ops.d(130): Error: `opNeg` is obsolete. Use `opUnary(string op)() if (op == "-")` instead.
fail_compilation/dep_d1_ops.d(131): Deprecation: `opCom` is deprecated. Use `opUnary(string op)() if (op == "~")` instead. fail_compilation/dep_d1_ops.d(131): Error: `opCom` is obsolete. Use `opUnary(string op)() if (op == "~")` instead.
fail_compilation/dep_d1_ops.d(132): Deprecation: `opPostInc` is deprecated. Use `opUnary(string op)() if (op == "++")` instead. fail_compilation/dep_d1_ops.d(132): Error: `opPostInc` is obsolete. Use `opUnary(string op)() if (op == "++")` instead.
fail_compilation/dep_d1_ops.d(133): Deprecation: `opPostDec` is deprecated. Use `opUnary(string op)() if (op == "--")` instead. fail_compilation/dep_d1_ops.d(133): Error: `opPostDec` is obsolete. Use `opUnary(string op)() if (op == "--")` instead.
fail_compilation/dep_d1_ops.d(134): Deprecation: `opStar` is deprecated. Use `opUnary(string op)() if (op == "*")` instead. fail_compilation/dep_d1_ops.d(134): Error: `opStar` is obsolete. Use `opUnary(string op)() if (op == "*")` instead.
fail_compilation/dep_d1_ops.d(136): Deprecation: `opIn` is deprecated. Use `opBinary(string op)(...) if (op == "in")` instead. fail_compilation/dep_d1_ops.d(136): Error: `opIn` is obsolete. Use `opBinary(string op)(...) if (op == "in")` instead.
fail_compilation/dep_d1_ops.d(137): Deprecation: `opIn_r` is deprecated. Use `opBinaryRight(string op)(...) if (op == "in")` instead. fail_compilation/dep_d1_ops.d(137): Error: `opIn_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "in")` instead.
fail_compilation/dep_d1_ops.d(139): Deprecation: `opAddAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "+")` instead. fail_compilation/dep_d1_ops.d(139): Error: `opAddAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "+")` instead.
fail_compilation/dep_d1_ops.d(140): Deprecation: `opSubAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "-")` instead. fail_compilation/dep_d1_ops.d(140): Error: `opSubAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "-")` instead.
fail_compilation/dep_d1_ops.d(141): Deprecation: `opMulAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "*")` instead. fail_compilation/dep_d1_ops.d(141): Error: `opMulAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "*")` instead.
fail_compilation/dep_d1_ops.d(142): Deprecation: `opDivAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "/")` instead. fail_compilation/dep_d1_ops.d(142): Error: `opDivAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "/")` instead.
fail_compilation/dep_d1_ops.d(143): Deprecation: `opModAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "%")` instead. fail_compilation/dep_d1_ops.d(143): Error: `opModAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "%")` instead.
fail_compilation/dep_d1_ops.d(144): Deprecation: `opAndAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "&")` instead. fail_compilation/dep_d1_ops.d(144): Error: `opAndAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "&")` instead.
fail_compilation/dep_d1_ops.d(145): Deprecation: `opOrAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "|")` instead. fail_compilation/dep_d1_ops.d(145): Error: `opOrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "|")` instead.
fail_compilation/dep_d1_ops.d(146): Deprecation: `opXorAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "^")` instead. fail_compilation/dep_d1_ops.d(146): Error: `opXorAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "^")` instead.
fail_compilation/dep_d1_ops.d(147): Deprecation: `opShlAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "<<")` instead. fail_compilation/dep_d1_ops.d(147): Error: `opShlAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "<<")` instead.
fail_compilation/dep_d1_ops.d(148): Deprecation: `opShrAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == ">>")` instead. fail_compilation/dep_d1_ops.d(148): Error: `opShrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == ">>")` instead.
fail_compilation/dep_d1_ops.d(149): Deprecation: `opUShrAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == ">>>")` instead. fail_compilation/dep_d1_ops.d(149): Error: `opUShrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == ">>>")` instead.
fail_compilation/dep_d1_ops.d(150): Deprecation: `opCatAssign` is deprecated. Use `opOpAssign(string op)(...) if (op == "~")` instead. fail_compilation/dep_d1_ops.d(150): Error: `opCatAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "~")` instead.
fail_compilation/dep_d1_ops.d(158): Deprecation: `opCom` is deprecated. Use `opUnary(string op)() if (op == "~")` instead. fail_compilation/dep_d1_ops.d(158): Error: `opCom` is obsolete. Use `opUnary(string op)() if (op == "~")` instead.
--- ---
*/ */

View File

@ -2,7 +2,8 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/dephexstrings.d(8): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"60"` instead. fail_compilation/dephexstrings.d(9): Error: semicolon expected following auto declaration, not `"60"`
fail_compilation/dephexstrings.d(9): Error: declaration expected, not `"60"`
--- ---
*/ */
enum xstr = x"60"; enum xstr = x"60";

View File

@ -2,9 +2,9 @@
REQUIRED_ARGS: -de REQUIRED_ARGS: -de
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/deprecateopdot.d(27): Deprecation: `opDot` is deprecated. Use `alias this` fail_compilation/deprecateopdot.d(27): Error: `opDot` is obsolete. Use `alias this`
fail_compilation/deprecateopdot.d(28): Deprecation: `opDot` is deprecated. Use `alias this` fail_compilation/deprecateopdot.d(28): Error: `opDot` is obsolete. Use `alias this`
fail_compilation/deprecateopdot.d(29): Deprecation: `opDot` is deprecated. Use `alias this` fail_compilation/deprecateopdot.d(29): Error: `opDot` is obsolete. Use `alias this`
--- ---
*/ */
struct S6 struct S6

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail136.d(10): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"EF BB BF"` instead. fail_compilation/fail136.d(10): Error: found `"EF BB BF"` when expecting `;` following statement
--- ---
*/ */

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail18.d(14): Error: need upper and lower bound to slice pointer fail_compilation/fail18.d(14): Error: upper and lower bounds are needed to slice a pointer
--- ---
*/ */

View File

@ -1,7 +1,8 @@
// https://issues.dlang.org/show_bug.cgi?id=22780 // https://issues.dlang.org/show_bug.cgi?id=22780
/* TEST_OUTPUT: /* TEST_OUTPUT:
--- ---
fail_compilation/fail22780.d(11): Error: variable `fail22780.test10717.c` reference to `scope class` must be `scope` fail_compilation/fail22780.d(8): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/fail22780.d(12): Error: variable `fail22780.test10717.c` reference to `scope class` must be `scope`
--- ---
*/ */
scope class C10717 { } scope class C10717 { }

View File

@ -0,0 +1,9 @@
// https://issues.dlang.org/show_bug.cgi?id=22827
/* TEST_OUTPUT:
---
fail_compilation/fail22827.d(8): Error: `cent` and `ucent` types are obsolete, use `core.int128.Cent` instead
fail_compilation/fail22827.d(9): Error: `cent` and `ucent` types are obsolete, use `core.int128.Cent` instead
---
*/
cent i22827;
ucent j22827;

View File

@ -0,0 +1,68 @@
/*
TEST_OUTPUT:
---
fail_compilation/issue22820.d(138): Error: upper and lower bounds are needed to slice a pointer
fail_compilation/issue22820.d(138): pointer `s1` points to an aggregate that defines an `opIndex`, perhaps you meant `(*s1)[]`
fail_compilation/issue22820.d(139): Error: upper and lower bounds are needed to slice a pointer
fail_compilation/issue22820.d(139): pointer `s2` points to an aggregate that defines an `opSlice`, perhaps you meant `(*s2)[]`
fail_compilation/issue22820.d(140): Error: upper and lower bounds are needed to slice a pointer
fail_compilation/issue22820.d(140): pointer `s3` points to an aggregate that defines an `opIndex`, perhaps you meant `(*s3)[]`
fail_compilation/issue22820.d(141): Error: upper and lower bounds are needed to slice a pointer
fail_compilation/issue22820.d(141): pointer `cp` points to an aggregate that defines an `opIndex`, perhaps you meant `(*cp)[]`
fail_compilation/issue22820.d(142): Error: upper and lower bounds are needed to slice a pointer
fail_compilation/issue22820.d(142): pointer `e` points to an aggregate that defines an `opIndex`, perhaps you meant `(*e)[]`
---
*/
#line 100
// normal functions
struct S1 {
int[] opIndex() { return a; }
int[] a;
}
// opSlice alternative
struct S2 {
int[] opSlice() { return a; }
int[] a;
}
// templates
struct S3 {
int[] opIndex()() { return a; }
int[] a;
}
class C {
int[] opIndex()() { return a; }
int[] a;
}
enum E : S1
{
a = S1([1])
}
void main() {
S1* s1 = new S1;
S2* s2 = new S2;
S3* s3 = new S3;
C c = new C;
C* cp = &c;
E* e = new E;
int* p;
p = s1[].ptr;
p = s2[].ptr;
p = s3[].ptr;
p = cp[].ptr;
p = e[].ptr;
p = (*s1)[].ptr;
p = (*s2)[].ptr;
p = (*s3)[].ptr;
p = (*cp)[].ptr;
p = (*e)[].ptr;
}

View File

@ -1,8 +1,8 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/lexer1.d(30): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"01 02 03"w` instead. fail_compilation/lexer1.d(30): Error: no identifier for declarator `x`
fail_compilation/lexer1.d(30): Error: declaration expected, not `x"01 02 03"w` fail_compilation/lexer1.d(30): Error: declaration expected, not `"01 02 03"w`
fail_compilation/lexer1.d(31): Error: declaration expected, not `2147483649U` fail_compilation/lexer1.d(31): Error: declaration expected, not `2147483649U`
fail_compilation/lexer1.d(32): Error: declaration expected, not `0.1` fail_compilation/lexer1.d(32): Error: declaration expected, not `0.1`
fail_compilation/lexer1.d(33): Error: declaration expected, not `0.1f` fail_compilation/lexer1.d(33): Error: declaration expected, not `0.1f`

View File

@ -1,10 +1,10 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/lexer2.d(16): Error: odd number (3) of hex characters in hex string fail_compilation/lexer2.d(16): Error: semicolon expected following auto declaration, not `"123"`
fail_compilation/lexer2.d(16): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"123"` instead. fail_compilation/lexer2.d(16): Error: declaration expected, not `"123"`
fail_compilation/lexer2.d(17): Error: non-hex character 'G' in hex string fail_compilation/lexer2.d(17): Error: semicolon expected following auto declaration, not `"123G"`
fail_compilation/lexer2.d(17): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"123G"` instead. fail_compilation/lexer2.d(17): Error: declaration expected, not `"123G"`
fail_compilation/lexer2.d(18): Error: heredoc rest of line should be blank fail_compilation/lexer2.d(18): Error: heredoc rest of line should be blank
fail_compilation/lexer2.d(20): Error: unterminated delimited string constant starting at fail_compilation/lexer2.d(20) fail_compilation/lexer2.d(20): Error: unterminated delimited string constant starting at fail_compilation/lexer2.d(20)
fail_compilation/lexer2.d(22): Error: semicolon expected following auto declaration, not `End of File` fail_compilation/lexer2.d(22): Error: semicolon expected following auto declaration, not `End of File`

View File

@ -0,0 +1,27 @@
/* TEST_OUTPUT:
---
fail_compilation/opapplyscope.d(113): Error: function `opapplyscope.S.opApply(scope int delegate(scope int* ptr) @safe dg)` is not callable using argument types `(int delegate(int* x) nothrow @nogc @safe)`
fail_compilation/opapplyscope.d(113): cannot pass argument `__foreachbody3` of type `int delegate(int* x) nothrow @nogc @safe` to parameter `scope int delegate(scope int* ptr) @safe dg`
---
*/
#line 100
struct S
{
int opApply(scope int delegate (scope int* ptr) @safe dg) @safe
{
return 0;
}
}
void test() @safe
{
static int* global;
S s;
foreach (/*scope*/ int* x; s)
{
global = x;
}
}

View File

@ -1,7 +1,8 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/scope_class.d(11): Error: functions cannot return `scope scope_class.C` fail_compilation/scope_class.d(10): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/scope_class.d(12): Error: functions cannot return `scope scope_class.C`
--- ---
*/ */

View File

@ -2,11 +2,15 @@
REQUIRED_ARGS: -de REQUIRED_ARGS: -de
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/scope_type.d(11): Error: `scope` as a type constraint is obsolete. Use `scope` at the usage site. fail_compilation/scope_type.d(13): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/scope_type.d(14): Error: `scope` as a type constraint is obsolete. Use `scope` at the usage site.
fail_compilation/scope_type.d(15): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/scope_type.d(16): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
--- ---
*/ */
scope class C { } scope class C { }
scope interface I { } scope interface I { }
//scope struct S { } scope struct S { }
scope enum E { e }

View File

@ -1,15 +1,19 @@
/* TEST_OUTPUT: /* TEST_OUTPUT:
PERMUTE_ARGS: -dip1000 REQUIRED_ARGS: -preview=dip1000
--- ---
fail_compilation/test15191.d(31): Error: returning `&identity(x)` escapes a reference to local variable `x` fail_compilation/test15191.d(35): Error: returning `&identity(x)` escapes a reference to local variable `x`
fail_compilation/test15191.d(37): Error: returning `&identityPtr(x)` escapes a reference to local variable `x` fail_compilation/test15191.d(41): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
fail_compilation/test15191.d(43): Error: cannot take address of `ref return` of `identityPtr()` in `@safe` function `addrOfRefTransitive` fail_compilation/test15191.d(47): Error: cannot take address of `ref return` of `identityPtr()` in `@safe` function `addrOfRefTransitive`
fail_compilation/test15191.d(43): Error: returning `&identityPtr(x)` escapes a reference to local variable `x` fail_compilation/test15191.d(47): return type `int*` has pointers that may be `scope`
fail_compilation/test15191.d(68): Error: cannot slice static array of `ref return` of `identityArr()` in `@safe` function `sliceOfRefEscape`
fail_compilation/test15191.d(68): return type `int*[1]` has pointers that may be `scope`
--- ---
*/ */
// Test taking the address of a `ref return` using & and [] operators
// https://issues.dlang.org/show_bug.cgi?id=15191 // https://issues.dlang.org/show_bug.cgi?id=15191
// https://issues.dlang.org/show_bug.cgi?id=22519 // https://issues.dlang.org/show_bug.cgi?id=22519
// https://issues.dlang.org/show_bug.cgi?id=22539
@safe: @safe:
ref int foo(return ref int s) ref int foo(return ref int s)
@ -50,3 +54,17 @@ int* addrOfRefGlobal()
{ {
return &getGlobalInt(); return &getGlobalInt();
} }
// Slice:
ref int*[1] identityArr(ref return scope int*[1] x)
{
return x;
}
int* sliceOfRefEscape()
{
int stackVar = 0xFF;
scope int*[1] x = [&stackVar];
int*[] y = identityArr(x)[];
return y[0];
}

View File

@ -1,7 +1,9 @@
/* REQUIRED_ARGS: -preview=dip1000 /* REQUIRED_ARGS: -preview=dip1000
* TEST_OUTPUT: * TEST_OUTPUT:
--- ---
fail_compilation/test19097.d(35): Error: scope variable `s` may not be returned fail_compilation/test19097.d(37): Error: scope variable `s` may not be returned
fail_compilation/test19097.d(66): Error: scope variable `z` assigned to `refPtr` with longer lifetime
fail_compilation/test19097.d(97): Error: scope variable `s` may not be returned
--- ---
*/ */
@ -54,3 +56,43 @@ struct S2(T)
S2!int s2; S2!int s2;
/************************/
struct S3
{
int* ptr;
void assign(ref int* refPtr, return scope int* z) scope @safe
{
this.ptr = z; // allowed, first ref
refPtr = z; // should not be allowed
}
}
int* escape() @safe
{
int local;
S3 escapeThis;
int* escapeRef;
escapeThis.assign(escapeRef, &local);
return escapeRef;
}
/************************/
// https://issues.dlang.org/show_bug.cgi?id=22837
struct S4
{
int* p;
this(int dummy, return scope int* p) @safe
{
this.p = p;
}
}
int* escape2()
{
int x;
auto s = S4(0, &x);
return s.p;
}

View File

@ -0,0 +1,41 @@
/*
TEST_OUTPUT:
---
fail_compilation/test21008.d(110): Error: function `test21008.C.after` circular reference to class `C`
fail_compilation/test21008.d(117): Error: need `this` for `toString` of type `string()`
fail_compilation/test21008.d(117): Error: need `this` for `toHash` of type `nothrow @trusted $?:32=uint|64=ulong$()`
fail_compilation/test21008.d(117): Error: function `object.Object.opCmp(Object o)` is not callable using argument types `()`
fail_compilation/test21008.d(117): missing argument for parameter #1: `Object o`
fail_compilation/test21008.d(117): Error: function `object.Object.opEquals(Object o)` is not callable using argument types `()`
fail_compilation/test21008.d(117): missing argument for parameter #1: `Object o`
fail_compilation/test21008.d(117): Error: `Monitor` has no effect
fail_compilation/test21008.d(117): Error: function `object.Object.factory(string classname)` is not callable using argument types `()`
fail_compilation/test21008.d(117): missing argument for parameter #1: `string classname`
fail_compilation/test21008.d(105): called from here: `handleMiddlewareAnnotation()`
fail_compilation/test21008.d(108): Error: class `test21008.C` no size because of forward reference
---
*/
// https://issues.dlang.org/show_bug.cgi?id=21008
#line 100
class Base
{
bool after();
mixin(handleMiddlewareAnnotation);
}
class C : Base
{
override bool after();
}
string handleMiddlewareAnnotation()
{
foreach (member; __traits(allMembers, C))
{
__traits(getMember, C, member);
}
}

View File

@ -99,3 +99,81 @@ void test5(int i)
} }
} }
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(513): Error: undefined identifier `undefinedFunc`
fail_compilation/test_switch_error.d(517): Error: `case` must be a `string` or an integral constant, not `Strukt(1)`
fail_compilation/test_switch_error.d(518): Error: `case` variables have to be `const` or `immutable`
fail_compilation/test_switch_error.d(518): Error: `case` variables not allowed in `final switch` statements
fail_compilation/test_switch_error.d(519): Error: `case` variables not allowed in `final switch` statements
fail_compilation/test_switch_error.d(522): Error: undefined identifier `undefinedFunc2`
---
++/
#line 500
enum Foo
{
one, two
}
struct Strukt
{
int i;
}
void errorsWithErrors(int param, immutable int constant)
{
final switch(undefinedFunc())
{
case Foo.one: break;
case Foo.two: break;
case Strukt(1): break;
case param: break;
case constant: break;
}
switch (undefinedFunc2())
{
case constant: break;
}
}
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(622): Error: undefined identifier `undefinedFunc`
fail_compilation/test_switch_error.d(624): Error: `case` must be a `string` or an integral constant, not `SubtypeOfInt(2)`
fail_compilation/test_switch_error.d(625): Error: `case` must be a `string` or an integral constant, not `SubtypeOfIntMethod()`
---
++/
#line 600
struct SubtypeOfInt
{
int i;
alias i this;
}
struct SubtypeOfIntMethod
{
int getI() { return 0; }
alias getI this;
}
void errorsWithErrors2(int param)
{
final switch(param)
{
case SubtypeOfInt(1): break;
case SubtypeOfIntMethod(): break;
}
// This snippet causes somewhat misleading error messages
final switch(undefinedFunc())
{
case SubtypeOfInt(2): break;
case SubtypeOfIntMethod(): break;
}
}

View File

@ -1,22 +1,23 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/typeerrors.d(36): Error: tuple index 4 exceeds 4 fail_compilation/typeerrors.d(32): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/typeerrors.d(38): Error: variable `x` cannot be read at compile time fail_compilation/typeerrors.d(37): Error: tuple index 4 exceeds 4
fail_compilation/typeerrors.d(39): Error: cannot have array of `void()` fail_compilation/typeerrors.d(39): Error: variable `x` cannot be read at compile time
fail_compilation/typeerrors.d(40): Error: cannot have array of scope `typeerrors.C` fail_compilation/typeerrors.d(40): Error: cannot have array of `void()`
fail_compilation/typeerrors.d(41): Error: cannot have array of scope `typeerrors.C` fail_compilation/typeerrors.d(41): Error: cannot have array of scope `typeerrors.C`
fail_compilation/typeerrors.d(44): Error: `int[5]` is not an expression fail_compilation/typeerrors.d(42): Error: cannot have array of scope `typeerrors.C`
fail_compilation/typeerrors.d(46): Error: variable `x` is used as a type fail_compilation/typeerrors.d(45): Error: `int[5]` is not an expression
fail_compilation/typeerrors.d(37): variable `x` is declared here fail_compilation/typeerrors.d(47): Error: variable `x` is used as a type
fail_compilation/typeerrors.d(47): Error: cannot have associative array key of `void()` fail_compilation/typeerrors.d(38): variable `x` is declared here
fail_compilation/typeerrors.d(48): Error: cannot have associative array key of `void` fail_compilation/typeerrors.d(48): Error: cannot have associative array key of `void()`
fail_compilation/typeerrors.d(49): Error: cannot have array of scope `typeerrors.C` fail_compilation/typeerrors.d(49): Error: cannot have associative array key of `void`
fail_compilation/typeerrors.d(50): Error: cannot have associative array of `void` fail_compilation/typeerrors.d(50): Error: cannot have array of scope `typeerrors.C`
fail_compilation/typeerrors.d(51): Error: cannot have associative array of `void()` fail_compilation/typeerrors.d(51): Error: cannot have associative array of `void`
fail_compilation/typeerrors.d(53): Error: cannot have parameter of type `void` fail_compilation/typeerrors.d(52): Error: cannot have associative array of `void()`
fail_compilation/typeerrors.d(55): Error: slice `[1..5]` is out of range of [0..4] fail_compilation/typeerrors.d(54): Error: cannot have parameter of type `void`
fail_compilation/typeerrors.d(56): Error: slice `[2..1]` is out of range of [0..4] fail_compilation/typeerrors.d(56): Error: slice `[1..5]` is out of range of [0..4]
fail_compilation/typeerrors.d(57): Error: slice `[2..1]` is out of range of [0..4]
--- ---
*/ */

View File

@ -16,7 +16,7 @@ import core.stdc.stdio;
/******************************************/ /******************************************/
scope class Foo class Foo
{ {
static int x; static int x;
@ -65,7 +65,7 @@ void test1()
int ax; int ax;
scope class A2 class A2
{ {
this() this()
{ {
@ -96,11 +96,11 @@ void test2()
int status3; int status3;
scope class Parent3 class Parent3
{ {
} }
scope class Child3 : Parent3 class Child3 : Parent3
{ {
this(){ this(){
assert(status3==0); assert(status3==0);

View File

@ -3246,7 +3246,7 @@ int test6907()
} }
{ {
S1* p = new S1(); S1* p = new S1();
if (__ctfe) if (__ctfe)
{ {
(*p).__dtor(); (*p).__dtor();
destroy(p); destroy(p);

View File

@ -31,7 +31,8 @@ import core.stdc.stdio;
class A1 class A1
{ {
int opAdd(int i) { return 7 + i; } int opBinary(string op)(int i) if (op == "+") { return 7 + i; }
alias opBinaryRight = opBinary;
} }
void test1() void test1()
@ -50,8 +51,8 @@ void test1()
class A2 class A2
{ {
int opDiv(int i) { return 9 + i; } int opBinary(string op)(int i) if (op == "/") { return 9 + i; }
int opDiv_r(int i) { return 17 + i; } int opBinaryRight(string op)(int i) if (op == "/") { return 17 + i; }
} }
void test2() void test2()
@ -74,31 +75,31 @@ class C1
class C2 class C2
{ {
int opAdd(D1 d) { return 1; } int opBinary(string op)(D1 d) if (op == "+") { return 1; }
int opAdd(D2 d) { return 2; } int opBinary(string op)(D2 d) if (op == "+") { return 2; }
int opAdd(D3 d) { return 3; } int opBinary(string op)(D3 d) if (op == "+") { return 3; }
int opAdd(D4 d) { return 4; } int opBinary(string op)(D4 d) if (op == "+") { return 4; }
} }
class C3 class C3
{ {
int opAdd_r(D1 d) { return 5; } int opBinaryRight(string op)(D1 d) if (op == "+") { return 5; }
int opAdd_r(D2 d) { return 6; } int opBinaryRight(string op)(D2 d) if (op == "+") { return 6; }
int opAdd_r(D3 d) { return 7; } int opBinaryRight(string op)(D3 d) if (op == "+") { return 7; }
int opAdd_r(D4 d) { return 8; } int opBinaryRight(string op)(D4 d) if (op == "+") { return 8; }
} }
class C4 class C4
{ {
int opAdd(D1 d) { return 9; } int opBinary(string op)(D1 d) if (op == "+") { return 9; }
int opAdd(D2 d) { return 10; } int opBinary(string op)(D2 d) if (op == "+") { return 10; }
int opAdd(D3 d) { return 11; } int opBinary(string op)(D3 d) if (op == "+") { return 11; }
int opAdd(D4 d) { return 12; } int opBinary(string op)(D4 d) if (op == "+") { return 12; }
int opAdd_r(D1 d) { return 13; } int opBinaryRight(string op)(D1 d) if (op == "+") { return 13; }
int opAdd_r(D2 d) { return 14; } int opBinaryRight(string op)(D2 d) if (op == "+") { return 14; }
int opAdd_r(D3 d) { return 15; } int opBinaryRight(string op)(D3 d) if (op == "+") { return 15; }
int opAdd_r(D4 d) { return 16; } int opBinaryRight(string op)(D4 d) if (op == "+") { return 16; }
} }
class D1 class D1
@ -107,31 +108,31 @@ class D1
class D2 class D2
{ {
int opAdd(C1 c) { return 17; } int opBinary(string op)(C1 d) if (op == "+") { return 17; }
int opAdd(C2 d) { return 18; } int opBinary(string op)(C2 d) if (op == "+") { return 18; }
int opAdd(C3 d) { return 19; } int opBinary(string op)(C3 d) if (op == "+") { return 19; }
int opAdd(C4 d) { return 20; } int opBinary(string op)(C4 d) if (op == "+") { return 20; }
} }
class D3 class D3
{ {
int opAdd_r(C1 d) { return 21; } int opBinaryRight(string op)(C1 d) if (op == "+") { return 21; }
int opAdd_r(C2 d) { return 22; } int opBinaryRight(string op)(C2 d) if (op == "+") { return 22; }
int opAdd_r(C3 d) { return 23; } int opBinaryRight(string op)(C3 d) if (op == "+") { return 23; }
int opAdd_r(C4 d) { return 24; } int opBinaryRight(string op)(C4 d) if (op == "+") { return 24; }
} }
class D4 class D4
{ {
int opAdd(C1 d) { return 25; } int opBinary(string op)(C1 d) if (op == "+") { return 25; }
int opAdd(C2 d) { return 26; } int opBinary(string op)(C2 d) if (op == "+") { return 26; }
int opAdd(C3 d) { return 27; } int opBinary(string op)(C3 d) if (op == "+") { return 27; }
int opAdd(C4 d) { return 28; } int opBinary(string op)(C4 d) if (op == "+") { return 28; }
int opAdd_r(C1 d) { return 29; } int opBinaryRight(string op)(C1 d) if (op == "+") { return 29; }
int opAdd_r(C2 d) { return 30; } int opBinaryRight(string op)(C2 d) if (op == "+") { return 30; }
int opAdd_r(C3 d) { return 31; } int opBinaryRight(string op)(C3 d) if (op == "+") { return 31; }
int opAdd_r(C4 d) { return 32; } int opBinaryRight(string op)(C4 d) if (op == "+") { return 32; }
} }
@ -149,90 +150,45 @@ void test3()
int i; int i;
version (ADD_R)
{
//i = c1 + d1; assert(i == ); //i = c1 + d1; assert(i == );
i = c1 + d2; assert(i == 17); //i = c1 + d2; assert(i == );
i = c1 + d3; assert(i == 21); i = c1 + d3; assert(i == 21);
i = c1 + d4; assert(i == 29); i = c1 + d4; assert(i == 29);
i = c2 + d1; assert(i == 1); i = c2 + d1; assert(i == 1);
i = c2 + d2; assert(i == 2); i = c2 + d2; assert(i == 2);
i = c2 + d3; assert(i == 3); i = c2 + d3; assert(i == 22);
i = c2 + d4; assert(i == 4); i = c2 + d4; assert(i == 30);
//i = c3 + d1; assert(i == ); //i = c3 + d1; assert(i == );
i = c3 + d2; assert(i == 19); //i = c3 + d2; assert(i == );
i = c3 + d3; assert(i == 23); i = c3 + d3; assert(i == 23);
i = c3 + d4; assert(i == 31); i = c3 + d4; assert(i == 31);
i = c4 + d1; assert(i == 9); i = c4 + d1; assert(i == 9);
i = c4 + d2; assert(i == 10); i = c4 + d2; assert(i == 10);
i = c4 + d3; assert(i == 11); i = c4 + d3; assert(i == 24);
i = c4 + d4; assert(i == 12); i = c4 + d4; assert(i == 32);
//i = d1 + c1; assert(i == ); //i = d1 + c1; assert(i == );
i = d1 + c2; assert(i == 1); //i = d1 + c2; assert(i == );
i = d1 + c3; assert(i == 5); i = d1 + c3; assert(i == 5);
i = d1 + c4; assert(i == 13); i = d1 + c4; assert(i == 13);
i = d2 + c1; assert(i == 17); i = d2 + c1; assert(i == 17);
i = d2 + c2; assert(i == 18); i = d2 + c2; assert(i == 18);
i = d2 + c3; assert(i == 19); i = d2 + c3; assert(i == 6);
i = d2 + c4; assert(i == 20); i = d2 + c4; assert(i == 14);
//i = d3 + c1; assert(i == ); //i = d3 + c1; assert(i == );
i = d3 + c2; assert(i == 3); //i = d3 + c2; assert(i == );
i = d3 + c3; assert(i == 7); i = d3 + c3; assert(i == 7);
i = d3 + c4; assert(i == 15); i = d3 + c4; assert(i == 15);
i = d4 + c1; assert(i == 25); i = d4 + c1; assert(i == 25);
i = d4 + c2; assert(i == 26); i = d4 + c2; assert(i == 26);
i = d4 + c3; assert(i == 27); i = d4 + c3; assert(i == 8);
i = d4 + c4; assert(i == 28); i = d4 + c4; assert(i == 16);
}
else
{
//i = c1 + d1; assert(i == );
i = c1 + d2; assert(i == 17);
// i = c1 + d3; assert(i == 21);
i = c1 + d4; assert(i == 29);
i = c2 + d1; assert(i == 1);
i = c2 + d2; assert(i == 2);
// i = c2 + d3; assert(i == 3);
// i = c2 + d4; assert(i == 4);
//i = c3 + d1; assert(i == );
// i = c3 + d2; printf("i = %d\n", i); assert(i == 19);
// i = c3 + d3; assert(i == 23);
i = c3 + d4; assert(i == 31);
i = c4 + d1; assert(i == 9);
i = c4 + d2; assert(i == 10);
// i = c4 + d3; assert(i == 11);
// i = c4 + d4; assert(i == 12);
//i = d1 + c1; assert(i == );
i = d1 + c2; assert(i == 1);
// i = d1 + c3; assert(i == 5);
i = d1 + c4; assert(i == 13);
i = d2 + c1; assert(i == 17);
i = d2 + c2; assert(i == 18);
// i = d2 + c3; assert(i == 19);
// i = d2 + c4; assert(i == 20);
//i = d3 + c1; assert(i == );
// i = d3 + c2; assert(i == 3);
// i = d3 + c3; assert(i == 7);
i = d3 + c4; assert(i == 15);
i = d4 + c1; assert(i == 25);
i = d4 + c2; assert(i == 26);
// i = d4 + c3; assert(i == 27);
// i = d4 + c4; assert(i == 28);
}
} }
/**************************************/ /**************************************/
@ -258,44 +214,45 @@ void test4()
class A5 class A5
{ {
int opNeg() { return 10; } int opUnary(string op)() if (op == "-") { return 10; }
int opCom() { return 11; } int opUnary(string op)() if (op == "~") { return 11; }
int opPostInc() { return 12; } int opUnary(string op)() if (op == "++") { return 12; }
int opPostDec() { return 13; } int opUnary(string op)() if (op == "--") { return 13; }
int opAdd(int j) { return 14; }
int opSub(int j) { return 15; } int opBinary(string op)(int j) if (op == "+") { return 14; }
int opSub_r(int j) { return 16; } int opBinary(string op)(int j) if (op == "-") { return 15; }
int opMul(int j) { return 17; } int opBinaryRight(string op)(int j) if (op == "-") { return 16; }
int opDiv(int j) { return 18; } int opBinary(string op)(int j) if (op == "*") { return 17; }
int opDiv_r(int j) { return 19; } int opBinary(string op)(int j) if (op == "/") { return 18; }
int opMod(int j) { return 20; } int opBinaryRight(string op)(int j) if (op == "/") { return 19; }
int opMod_r(int j) { return 21; } int opBinary(string op)(int j) if (op == "%") { return 20; }
int opAnd(int j) { return 22; } int opBinaryRight(string op)(int j) if (op == "%") { return 21; }
int opOr(int j) { return 23; } int opBinary(string op)(int j) if (op == "&") { return 22; }
int opXor(int j) { return 24; } int opBinary(string op)(int j) if (op == "|") { return 23; }
int opShl(int j) { return 25; } int opBinary(string op)(int j) if (op == "^") { return 24; }
int opShl_r(int j) { return 26; } int opBinary(string op)(int j) if (op == "<<") { return 25; }
int opShr(int j) { return 27; } int opBinaryRight(string op)(int j) if (op == "<<") { return 26; }
int opShr_r(int j) { return 28; } int opBinary(string op)(int j) if (op == ">>") { return 27; }
int opUShr(int j) { return 29; } int opBinaryRight(string op)(int j) if (op == ">>") { return 28; }
int opUShr_r(int j) { return 30; } int opBinary(string op)(int j) if (op == ">>>") { return 29; }
int opCat(int j) { return 31; } int opBinaryRight(string op)(int j) if (op == ">>>") { return 30; }
int opCat_r(int j) { return 32; } int opBinary(string op)(int j) if (op == "~") { return 31; }
int opBinaryRight(string op)(int j) if (op == "~") { return 32; }
int opEquals(int j) { return 33; } int opEquals(int j) { return 33; }
int opCmp(int j) { return 34; } int opCmp(int j) { return 34; }
int opAddAssign(int j) { return 35; } int opOpAssign(string op)(int j) if (op == "+") { return 35; }
int opSubAssign(int j) { return 36; } int opOpAssign(string op)(int j) if (op == "-") { return 36; }
int opMulAssign(int j) { return 37; } int opOpAssign(string op)(int j) if (op == "*") { return 37; }
int opDivAssign(int j) { return 38; } int opOpAssign(string op)(int j) if (op == "/") { return 38; }
int opModAssign(int j) { return 39; } int opOpAssign(string op)(int j) if (op == "%") { return 39; }
int opAndAssign(int j) { return 40; } int opOpAssign(string op)(int j) if (op == "&") { return 40; }
int opOrAssign(int j) { return 41; } int opOpAssign(string op)(int j) if (op == "|") { return 41; }
int opXorAssign(int j) { return 42; } int opOpAssign(string op)(int j) if (op == "^") { return 42; }
int opShlAssign(int j) { return 43; } int opOpAssign(string op)(int j) if (op == "<<") { return 43; }
int opShrAssign(int j) { return 44; } int opOpAssign(string op)(int j) if (op == ">>") { return 44; }
int opUShrAssign(int j) { return 45; } int opOpAssign(string op)(int j) if (op == ">>>") { return 45; }
int opCatAssign(int j) { return 46; } int opOpAssign(string op)(int j) if (op == "~") { return 46; }
} }
void test5() void test5()
@ -309,10 +266,10 @@ void test5()
i = ~a; i = ~a;
assert(i == 11); assert(i == 11);
i = a++; i = ++a;
assert(i == 12); assert(i == 12);
i = a--; i = --a;
assert(i == 13); assert(i == 13);
i = a + 1; i = a + 1;
@ -402,13 +359,9 @@ printf("i = %d\n", i);
i = (a += 1); i = (a += 1);
assert(i == 35); assert(i == 35);
i = ++a;
assert(i == 35);
i = (a -= 1); i = (a -= 1);
assert(i == 36); assert(i == 36);
i = --a;
assert(i == 36);
i = (a *= 1); i = (a *= 1);
assert(i == 37); assert(i == 37);
@ -445,45 +398,45 @@ printf("i = %d\n", i);
struct A6 struct A6
{ {
int opNeg() { return 10; } int opUnary(string op)() if (op == "-") { return 10; }
int opCom() { return 11; } int opUnary(string op)() if (op == "~") { return 11; }
int opPostInc() { return 12; } int opUnary(string op)() if (op == "++") { return 12; }
int opPostDec() { return 13; } int opUnary(string op)() if (op == "--") { return 13; }
int opAdd(int j) { return 14; } int opBinary(string op)(int j) if (op == "+") { return 14; }
int opSub(int j) { return 15; } int opBinary(string op)(int j) if (op == "-") { return 15; }
int opSub_r(int j) { return 16; } int opBinaryRight(string op)(int j) if (op == "-") { return 16; }
int opMul(int j) { return 17; } int opBinary(string op)(int j) if (op == "*") { return 17; }
int opDiv(int j) { return 18; } int opBinary(string op)(int j) if (op == "/") { return 18; }
int opDiv_r(int j) { return 19; } int opBinaryRight(string op)(int j) if (op == "/") { return 19; }
int opMod(int j) { return 20; } int opBinary(string op)(int j) if (op == "%") { return 20; }
int opMod_r(int j) { return 21; } int opBinaryRight(string op)(int j) if (op == "%") { return 21; }
int opAnd(int j) { return 22; } int opBinary(string op)(int j) if (op == "&") { return 22; }
int opOr(int j) { return 23; } int opBinary(string op)(int j) if (op == "|") { return 23; }
int opXor(int j) { return 24; } int opBinary(string op)(int j) if (op == "^") { return 24; }
int opShl(int j) { return 25; } int opBinary(string op)(int j) if (op == "<<") { return 25; }
int opShl_r(int j) { return 26; } int opBinaryRight(string op)(int j) if (op == "<<") { return 26; }
int opShr(int j) { return 27; } int opBinary(string op)(int j) if (op == ">>") { return 27; }
int opShr_r(int j) { return 28; } int opBinaryRight(string op)(int j) if (op == ">>") { return 28; }
int opUShr(int j) { return 29; } int opBinary(string op)(int j) if (op == ">>>") { return 29; }
int opUShr_r(int j) { return 30; } int opBinaryRight(string op)(int j) if (op == ">>>") { return 30; }
int opCat(int j) { return 31; } int opBinary(string op)(int j) if (op == "~") { return 31; }
int opCat_r(int j) { return 32; } int opBinaryRight(string op)(int j) if (op == "~") { return 32; }
int opEquals(int j) { return 33; } int opEquals(int j) { return 33; }
const bool opEquals(const ref A6) { return false; } const bool opEquals(const ref A6) { return false; }
int opCmp(int j) { return 34; } int opCmp(int j) { return 34; }
int opAddAssign(int j) { return 35; } int opOpAssign(string op)(int j) if (op == "+") { return 35; }
int opSubAssign(int j) { return 36; } int opOpAssign(string op)(int j) if (op == "-") { return 36; }
int opMulAssign(int j) { return 37; } int opOpAssign(string op)(int j) if (op == "*") { return 37; }
int opDivAssign(int j) { return 38; } int opOpAssign(string op)(int j) if (op == "/") { return 38; }
int opModAssign(int j) { return 39; } int opOpAssign(string op)(int j) if (op == "%") { return 39; }
int opAndAssign(int j) { return 40; } int opOpAssign(string op)(int j) if (op == "&") { return 40; }
int opOrAssign(int j) { return 41; } int opOpAssign(string op)(int j) if (op == "|") { return 41; }
int opXorAssign(int j) { return 42; } int opOpAssign(string op)(int j) if (op == "^") { return 42; }
int opShlAssign(int j) { return 43; } int opOpAssign(string op)(int j) if (op == "<<") { return 43; }
int opShrAssign(int j) { return 44; } int opOpAssign(string op)(int j) if (op == ">>") { return 44; }
int opUShrAssign(int j) { return 45; } int opOpAssign(string op)(int j) if (op == ">>>") { return 45; }
int opCatAssign(int j) { return 46; } int opOpAssign(string op)(int j) if (op == "~") { return 46; }
} }
void test6() void test6()
@ -497,10 +450,10 @@ void test6()
i = ~a; i = ~a;
assert(i == 11); assert(i == 11);
i = a++; i = ++a;
assert(i == 12); assert(i == 12);
i = a--; i = --a;
assert(i == 13); assert(i == 13);
i = a + 1; i = a + 1;
@ -589,13 +542,9 @@ void test6()
i = (a += 1); i = (a += 1);
assert(i == 35); assert(i == 35);
i = ++a;
assert(i == 35);
i = (a -= 1); i = (a -= 1);
assert(i == 36); assert(i == 36);
i = --a;
assert(i == 36);
i = (a *= 1); i = (a *= 1);
assert(i == 37); assert(i == 37);
@ -652,19 +601,19 @@ void test7()
interface IWriter interface IWriter
{ {
int opShl (string i); int opBinary(string op)(string i) if (op == "<<");
int opShl (int i); int opBinary(string op)(int i) if (op == "<<");
} }
class Writer : IWriter class Writer : IWriter
{ {
int opShl (string i) int opBinary(string op)(string i) if (op == "<<")
{ {
printf("Writer.opShl(char[])\n"); printf("Writer.opShl(char[])\n");
return 1; return 1;
} }
int opShl (int i) int opBinary(string op)(int i) if (op == "<<")
{ {
printf("Writer.opShl(int)\n"); printf("Writer.opShl(int)\n");
return 2; return 2;
@ -673,9 +622,13 @@ class Writer : IWriter
class BinaryWriter : Writer class BinaryWriter : Writer
{ {
alias Writer.opShl opShl; int opBinary(string op)(string i) if (op == "<<")
{
printf("Writer.opShl(char[])\n");
return 1;
}
override int opShl (int i) int opBinary(string op)(int i) if (op == "<<")
{ {
printf("BinaryWriter.opShl(int)\n"); printf("BinaryWriter.opShl(int)\n");
return 3; return 3;
@ -712,12 +665,14 @@ void test9()
class A10 class A10
{ {
int opAdd(int i) { return i + 1; } int opBinary(string op)(int i) if (op == "+") { return i + 1; }
alias opBinaryRight = opBinary;
} }
class B10 class B10
{ {
int opAdd_r(A10 a) { return 3; } int opBinaryRight(string op)(A10 a) if (op == "+") { return 3; }
alias opBinary = opBinaryRight;
} }
void test10() void test10()
@ -791,13 +746,13 @@ void test12()
class A13 class A13
{ {
A13 opShl(int x) A13 opBinary(string op)(int x) if (op == "<<")
{ {
printf("A::opShl(int %d)\n", x); printf("A::opShl(int %d)\n", x);
printf("%d",x); printf("%d",x);
return this; return this;
} }
A13 opShl(string x) A13 opBinary(string op)(string x) if (op == "<<")
{ {
printf("A::opShl(char[])\n"); printf("A::opShl(char[])\n");
printf("%.*s", cast(int)x.length, x.ptr); printf("%.*s", cast(int)x.length, x.ptr);
@ -807,7 +762,7 @@ class A13
class B13 class B13
{ {
A13 opShl_r(A13 a) A13 opBinaryRight(string op)(A13 a) if (op == "<<")
{ {
printf("B::opShl_r(A)\n"); printf("B::opShl_r(A)\n");
return a; return a;
@ -829,7 +784,7 @@ void test13()
class Foo14 class Foo14
{ int a; { int a;
int opIn(int x) int opBinary(string op)(int x) if (op == "in")
{ {
return a + x; return a + x;
} }
@ -999,18 +954,6 @@ struct Vec12778X
float x = 0, y = 0; float x = 0, y = 0;
} }
struct Vec12778Y
{
Vec12778Y opAdd()(Vec12778Y b) const
{
enum op = "+";
mixin("return Vec12778Y(this.x " ~ op ~ " b.x, this.y " ~ op ~ " b.y);");
}
alias opAdd_r = opAdd;
float x = 0, y = 0;
}
void test12778() void test12778()
{ {
struct S struct S
@ -1018,17 +961,14 @@ void test12778()
void test1() void test1()
{ {
Vec12778X vx = vx1 + vx2; // ok Vec12778X vx = vx1 + vx2; // ok
Vec12778Y vy = vy1 + vy2; // ok
} }
void test2() const void test2() const
{ {
Vec12778X vx = vx1 + vx2; // ok <- error Vec12778X vx = vx1 + vx2; // ok <- error
Vec12778Y vy = vy1 + vy2; // ok <- error
} }
Vec12778X vx1, vx2; Vec12778X vx1, vx2;
Vec12778Y vy1, vy2;
} }
} }
@ -1049,8 +989,8 @@ struct S14343b
int i; int i;
immutable(Object) o; immutable(Object) o;
void opAddAssign(int j) { i += j; } void opOpAssign(string op)(int j) if (op == "+") { i += j; }
S14343b opPostInc() { ++i; return this; } S14343b opUnary(string op)() if (op == "++") { ++i; return this; }
void opAssign(S14343b other) {} void opAssign(S14343b other) {}
} }

View File

@ -1,5 +1,10 @@
// REQUIRED_ARGS: -w -de // REQUIRED_ARGS: -w -dw
// PERMUTE_ARGS: // PERMUTE_ARGS:
/* TEST_OUTPUT:
---
runnable/sctor2.d(12): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
---
*/
/***************************************************/ /***************************************************/
// 15665 // 15665

View File

@ -1,25 +0,0 @@
interface IObject
{
size_t toHash() @trusted nothrow;
}
interface Dummy {}
interface Bug(E) : Dummy, IObject {}
interface OK(E) : IObject, Dummy {}
void main()
{
{
Bug!string s;
size_t t = hashOf(s);
}
{
OK!string s;
size_t t = hashOf(s);
}
static assert(is(immutable Bug!string* : immutable IObject*));
static assert(is(immutable OK!string* : immutable IObject*));
}

View File

@ -2175,13 +2175,13 @@ void test4251b()
// derived class to const(base interface) in tail // derived class to const(base interface) in tail
interface I {} interface I {}
class X : I {} class X : I {}
static assert(is( X[] : const(I)[] )); static assert(!is( X[] : const(I)[] ));
// interface to const(base interface) in tail // interface to const(base interface) in tail
interface J {} interface J {}
interface K : I, J {} interface K : I, J {}
static assert( is( K[] : const(I)[] )); // OK, runtime offset is same static assert( is( K[] : const(I)[] )); // OK, runtime offset is same
static assert(is( K[] : const(J)[] )); // !? NG, runtime offset is different static assert(!is( K[] : const(J)[] )); // NG, runtime offset is different
} }
/************************************/ /************************************/

View File

@ -14,14 +14,6 @@ tuple(height)
tuple(get, get) tuple(get, get)
tuple(clear) tuple(clear)
tuple(draw, draw) tuple(draw, draw)
runnable/xtest46.d(149): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(151): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(152): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(154): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(181): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(183): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(184): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46.d(186): Deprecation: `opDot` is deprecated. Use `alias this`
const(int) const(int)
string[] string[]
double[] double[]
@ -137,10 +129,7 @@ struct T6
S6 s; S6 s;
int b = 7; int b = 7;
S6* opDot() return alias s this;
{
return &s;
}
} }
void test6() void test6()
@ -169,10 +158,7 @@ class C7
S7 s; S7 s;
int b = 7; int b = 7;
S7* opDot() alias s this;
{
return &s;
}
} }
void test7() void test7()

View File

@ -15,14 +15,6 @@ tuple(height)
tuple(get, get) tuple(get, get)
tuple(clear) tuple(clear)
tuple(draw, draw) tuple(draw, draw)
runnable/xtest46_gc.d-mixin-$n$(185): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(187): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(188): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(190): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(217): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(219): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(220): Deprecation: `opDot` is deprecated. Use `alias this`
runnable/xtest46_gc.d-mixin-$n$(222): Deprecation: `opDot` is deprecated. Use `alias this`
const(int) const(int)
string[] string[]
double[] double[]

View File

@ -1,4 +1,4 @@
0316b981e5f2fa1525e893c5d94c59c847a8c386 26b581670ef6e2643d74078f200d1cd21fa40e90
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository. merge done from the dlang/druntime repository.

View File

@ -239,7 +239,9 @@ struct GCBits
size_t cntWords = lastWord - firstWord; size_t cntWords = lastWord - firstWord;
copyWordsShifted(firstWord, cntWords, firstOff, source); copyWordsShifted(firstWord, cntWords, firstOff, source);
wordtype src = (source[cntWords - 1] >> (BITS_PER_WORD - firstOff)) | (source[cntWords] << firstOff); wordtype src = (source[cntWords - 1] >> (BITS_PER_WORD - firstOff));
if (lastOff >= firstOff) // prevent buffer overread
src |= (source[cntWords] << firstOff);
wordtype mask = (BITS_2 << lastOff) - 1; wordtype mask = (BITS_2 << lastOff) - 1;
data[lastWord] = (data[lastWord] & ~mask) | (src & mask); data[lastWord] = (data[lastWord] & ~mask) | (src & mask);
} }

View File

@ -34,7 +34,7 @@ version (StdDdoc)
alias ddoc_long = int; alias ddoc_long = int;
alias ddoc_ulong = uint; alias ddoc_ulong = uint;
} }
struct ddoc_complex(T) { T re; T im; }; struct ddoc_complex(T) { T re; T im; }
} }
/*** /***

View File

@ -151,6 +151,8 @@ version (GNUFP)
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/sparc/fpu/bits/fenv.h // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/sparc/fpu/bits/fenv.h
else version (SPARC_Any) else version (SPARC_Any)
{ {
import core.stdc.config : c_ulong;
alias fenv_t = c_ulong; alias fenv_t = c_ulong;
alias fexcept_t = c_ulong; alias fexcept_t = c_ulong;
} }

View File

@ -36,20 +36,7 @@ extern (C):
nothrow: nothrow:
@nogc: @nogc:
// These are defined the same way as D basic types, so the definition is
// platform-independant
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
// 32 bit types and need to be defined on-platform basis, because
// they might have C++ binary mangling of `int` or `long`.
// 64-bit types respectively might be mangled as `long` or `long long`
// It would seem correct to define intmax_t and uintmax_t here, but C and C++
// compilers don't in practice always set them to the maximum supported value.
// See https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/
static if (is(ucent)) static if (is(ucent))
{ {
alias int128_t = cent; /// alias int128_t = cent; ///
@ -58,6 +45,10 @@ static if (is(ucent))
version (Windows) version (Windows)
{ {
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
version (CRuntime_DigitalMars) version (CRuntime_DigitalMars)
{ {
alias int32_t = cpp_long; /// alias int32_t = cpp_long; ///
@ -71,23 +62,31 @@ version (Windows)
alias int64_t = long; /// alias int64_t = long; ///
alias uint64_t = ulong; /// alias uint64_t = ulong; ///
alias int_least8_t = byte; /// alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; /// alias uint_least8_t = ubyte; ///
alias int_least16_t = short; /// alias int_least16_t = short; ///
alias uint_least16_t = ushort; /// alias uint_least16_t = ushort; ///
alias int_least32_t = int32_t; /// alias int_least32_t = int32_t; ///
alias uint_least32_t = uint32_t; /// alias uint_least32_t = uint32_t; ///
alias int_least64_t = long; /// alias int_least64_t = long; ///
alias uint_least64_t = ulong; /// alias uint_least64_t = ulong; ///
alias int_fast8_t = byte; /// alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; /// alias uint_fast8_t = ubyte; ///
alias int_fast16_t = int; /// version (MinGW)
alias uint_fast16_t = uint; /// {
alias int_fast32_t = int32_t; /// alias int_fast16_t = short; ///
alias uint_fast16_t = ushort; ///
}
else
{
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
}
alias int_fast32_t = int32_t; ///
alias uint_fast32_t = uint32_t; /// alias uint_fast32_t = uint32_t; ///
alias int_fast64_t = long; /// alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; /// alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; /// alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; /// alias uintptr_t = size_t; ///
@ -96,6 +95,10 @@ version (Windows)
} }
else version (Darwin) else version (Darwin)
{ {
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; /// alias int32_t = int; ///
alias uint32_t = uint; /// alias uint32_t = uint; ///
alias int64_t = cpp_longlong; /// alias int64_t = cpp_longlong; ///
@ -124,32 +127,27 @@ else version (Darwin)
alias intmax_t = long; /// alias intmax_t = long; ///
alias uintmax_t = ulong; /// alias uintmax_t = ulong; ///
} }
else version (Posix) else version (linux)
{ {
alias int32_t = int; /// alias int8_t = byte; ///
alias uint32_t = uint; /// alias int16_t = short; ///
alias int64_t = long; /// alias uint8_t = ubyte; ///
alias uint64_t = ulong; /// alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = byte; /// alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; /// alias uint_least8_t = ubyte; ///
alias int_least16_t = short; /// alias int_least16_t = short; ///
alias uint_least16_t = ushort; /// alias uint_least16_t = ushort; ///
alias int_least32_t = int; /// alias int_least32_t = int; ///
alias uint_least32_t = uint; /// alias uint_least32_t = uint; ///
alias int_least64_t = long; /// alias int_least64_t = long; ///
alias uint_least64_t = ulong;/// alias uint_least64_t = ulong; ///
version (FreeBSD) version (CRuntime_Musl)
{
alias int_fast8_t = int; ///
alias uint_fast8_t = uint; ///
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
alias int_fast32_t = int; ///
alias uint_fast32_t = uint; ///
}
else version (CRuntime_Musl)
{ {
alias int_fast8_t = byte; /// alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; /// alias uint_fast8_t = ubyte; ///
@ -167,17 +165,221 @@ else version (Posix)
alias int_fast32_t = ptrdiff_t; /// alias int_fast32_t = ptrdiff_t; ///
alias uint_fast32_t = size_t; /// alias uint_fast32_t = size_t; ///
} }
alias int_fast64_t = long; /// alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
}
else version (CRuntime_Glibc)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; ///
alias int_least16_t = short; ///
alias uint_least16_t = ushort; ///
alias int_least32_t = int; ///
alias uint_least32_t = uint; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; ///
alias int_fast16_t = ptrdiff_t; ///
alias uint_fast16_t = size_t; ///
alias int_fast32_t = ptrdiff_t; ///
alias uint_fast32_t = size_t; ///
alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
}
else version (DragonFlyBSD)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = int8_t; ///
alias uint_least8_t = uint8_t; ///
alias int_least16_t = int16_t; ///
alias uint_least16_t = uint16_t; ///
alias int_least32_t = int32_t; ///
alias uint_least32_t = uint32_t; ///
alias int_least64_t = int64_t; ///
alias uint_least64_t = uint64_t; ///
alias int_fast8_t = int32_t; ///
alias uint_fast8_t = uint32_t; ///
alias int_fast16_t = int32_t; ///
alias uint_fast16_t = uint32_t; ///
alias int_fast32_t = int32_t; ///
alias uint_fast32_t = uint32_t; ///
alias int_fast64_t = int64_t; ///
alias uint_fast64_t = uint64_t; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
}
else version (FreeBSD)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; ///
alias int_least16_t = short; ///
alias uint_least16_t = ushort; ///
alias int_least32_t = int; ///
alias uint_least32_t = uint; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
alias int_fast8_t = int; ///
alias uint_fast8_t = uint; ///
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
alias int_fast32_t = int; ///
alias uint_fast32_t = uint; ///
alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; /// alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; /// alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; /// alias uintptr_t = size_t; ///
alias intmax_t = long; /// alias intmax_t = long; ///
alias uintmax_t = ulong; /// alias uintmax_t = ulong; ///
}
else version (NetBSD)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = int8_t; ///
alias uint_least8_t = uint8_t; ///
alias int_least16_t = int16_t; ///
alias uint_least16_t = uint16_t; ///
alias int_least32_t = int32_t; ///
alias uint_least32_t = uint32_t; ///
alias int_least64_t = int64_t; ///
alias uint_least64_t = uint64_t; ///
alias int_fast8_t = int32_t; ///
alias uint_fast8_t = uint32_t; ///
alias int_fast16_t = int32_t; ///
alias uint_fast16_t = uint32_t; ///
alias int_fast32_t = int32_t; ///
alias uint_fast32_t = uint32_t; ///
alias int_fast64_t = int64_t; ///
alias uint_fast64_t = uint64_t; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
}
else version (OpenBSD)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = cpp_longlong; ///
alias uint64_t = cpp_ulonglong; ///
alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; ///
alias int_least16_t = short; ///
alias uint_least16_t = ushort; ///
alias int_least32_t = int; ///
alias uint_least32_t = uint; ///
alias int_least64_t = cpp_longlong; ///
alias uint_least64_t = cpp_ulonglong; ///
alias int_fast8_t = int; ///
alias uint_fast8_t = uint; ///
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
alias int_fast32_t = int; ///
alias uint_fast32_t = uint; ///
alias int_fast64_t = cpp_longlong; ///
alias uint_fast64_t = cpp_ulonglong; ///
alias intptr_t = cpp_long; ///
alias uintptr_t = cpp_ulong; ///
alias intmax_t = cpp_longlong; ///
alias uintmax_t = cpp_ulonglong; ///
}
else version (Solaris)
{
alias int8_t = char; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
alias int_least8_t = char; ///
alias uint_least8_t = ubyte; ///
alias int_least16_t = short; ///
alias uint_least16_t = ushort; ///
alias int_least32_t = int; ///
alias uint_least32_t = uint; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
alias int_fast8_t = char; ///
alias uint_fast8_t = ubyte; ///
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
alias int_fast32_t = int; ///
alias uint_fast32_t = uint; ///
alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
} }
else else
{ {
static assert(0); static assert(false, "Unsupported architecture.");
} }

View File

@ -26,7 +26,7 @@ extern (C++, "std")
struct nothrow_t {} struct nothrow_t {}
/// ///
enum align_val_t : size_t { defaultAlignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__ }; enum align_val_t : size_t { defaultAlignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__ }
/// ///
class bad_alloc : exception class bad_alloc : exception

View File

@ -8,6 +8,8 @@ version (Windows):
extern (C) nothrow @nogc: extern (C) nothrow @nogc:
@system: @system:
import core.sys.windows.stdc.time;
// Posix version is in core.sys.posix.sys.stat // Posix version is in core.sys.posix.sys.stat
enum S_IFMT = 0xF000; enum S_IFMT = 0xF000;
@ -30,22 +32,49 @@ int S_ISDIR(int m) { return (m & S_IFMT) == S_IFDIR; }
int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; } int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; }
} }
struct struct_stat version (CRuntime_DigitalMars)
{ {
short st_dev; struct struct_stat
ushort st_ino; {
ushort st_mode; short st_dev;
short st_nlink; ushort st_ino;
ushort st_uid; ushort st_mode;
ushort st_gid; short st_nlink;
short st_rdev; ushort st_uid;
short dummy; ushort st_gid;
int st_size; short st_rdev;
int st_atime; short dummy;
int st_mtime; int st_size;
int st_ctime; time_t st_atime;
} time_t st_mtime;
time_t st_ctime;
}
int stat(const(char)*, struct_stat *); int stat(const(char)*, struct_stat *);
int fstat(int, struct_stat *) @trusted; int fstat(int, struct_stat *) @trusted;
int _wstat(const(wchar)*, struct_stat *); int _wstat(const(wchar)*, struct_stat *);
}
else version (CRuntime_Microsoft)
{
struct struct_stat
{
uint st_dev;
ushort st_ino;
ushort st_mode;
short st_nlink;
short st_uid;
short st_gid;
uint st_rdev;
int st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
}
// These assume time_t is 32 bits (which druntime's definition currently is)
// Add pragma(mangle) to use _stat64 etc. when time_t is made 64-bit
// See also: https://issues.dlang.org/show_bug.cgi?id=21134
int stat(const(char)*, struct_stat *);
int fstat(int, struct_stat *) @trusted;
int _wstat(const(wchar)*, struct_stat *);
}

View File

@ -1011,8 +1011,12 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @
foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
{ {
case T.sizeof: case T.sizeof:
(cast(T*)result.ptr)[0 .. size * length / T.sizeof] = *cast(T*)init.ptr; if (tinext.talign % T.alignof == 0)
return result; {
(cast(T*)result.ptr)[0 .. size * length / T.sizeof] = *cast(T*)init.ptr;
return result;
}
goto default;
} }
default: default:
@ -1118,7 +1122,8 @@ extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
if (tiSize) if (tiSize)
{ {
*cast(TypeInfo*)(p + itemSize) = null; // the GC might not have cleared this area // the GC might not have cleared the padding area in the block
*cast(TypeInfo*)(p + (itemSize & ~(size_t.sizeof - 1))) = null;
*cast(TypeInfo*)(p + blkInf.size - tiSize) = cast() ti; *cast(TypeInfo*)(p + blkInf.size - tiSize) = cast() ti;
} }

View File

@ -1,4 +1,4 @@
a1f8c4c0700ce4e256f4130ad7883c6ea3890901 16cb085b584f100fa677e2e64ff6b6dbb4921ad1
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository. merge done from the dlang/phobos repository.

View File

@ -404,7 +404,7 @@ if (ranges.length >= 2 &&
r = ranges[i].save; // rollover r = ranges[i].save; // rollover
} }
} }
@property Result save() scope return @property Result save() return scope
{ {
Result copy = this; Result copy = this;
foreach (i, r; ranges) foreach (i, r; ranges)

View File

@ -1447,7 +1447,8 @@ public:
size_t bitCount; size_t bitCount;
foreach (i; 0 .. fullWords) foreach (i; 0 .. fullWords)
bitCount += countBitsSet(_ptr[i]); bitCount += countBitsSet(_ptr[i]);
bitCount += countBitsSet(_ptr[fullWords] & endMask); if (endBits)
bitCount += countBitsSet(_ptr[fullWords] & endMask);
return bitCount; return bitCount;
} }
else else

View File

@ -7848,12 +7848,12 @@ if (isTimePoint!TP &&
duration = The duration which separates each successive time point in duration = The duration which separates each successive time point in
the range. the range.
+/ +/
TP delegate(scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow TP delegate(return scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow
if (isTimePoint!TP && if (isTimePoint!TP &&
__traits(compiles, TP.init + duration) && __traits(compiles, TP.init + duration) &&
(dir == Direction.fwd || dir == Direction.bwd)) (dir == Direction.fwd || dir == Direction.bwd))
{ {
TP func(scope const TP tp) TP func(return scope const TP tp)
{ {
static if (dir == Direction.fwd) static if (dir == Direction.fwd)
return tp + duration; return tp + duration;

View File

@ -6269,7 +6269,7 @@ public:
duration = The $(REF Duration, core,time) to add to or subtract from duration = The $(REF Duration, core,time) to add to or subtract from
this $(LREF SysTime). this $(LREF SysTime).
+/ +/
SysTime opBinary(string op)(Duration duration) @safe const pure nothrow scope SysTime opBinary(string op)(Duration duration) @safe const pure nothrow return scope
if (op == "+" || op == "-") if (op == "+" || op == "-")
{ {
SysTime retval = SysTime(this._stdTime, this._timezone); SysTime retval = SysTime(this._stdTime, this._timezone);
@ -7668,7 +7668,7 @@ public:
$(LREF SysTime) for the last day in the month that this Date is in. $(LREF SysTime) for the last day in the month that this Date is in.
The time portion of endOfMonth is always 23:59:59.9999999. The time portion of endOfMonth is always 23:59:59.9999999.
+/ +/
@property SysTime endOfMonth() @safe const nothrow scope @property SysTime endOfMonth() @safe const nothrow return scope
{ {
immutable hnsecs = adjTime; immutable hnsecs = adjTime;
immutable days = getUnitsFromHNSecs!"days"(hnsecs); immutable days = getUnitsFromHNSecs!"days"(hnsecs);

View File

@ -392,6 +392,7 @@ version (Posix)
AlignedMallocator.instance.alignedReallocate(c, 32, 32); AlignedMallocator.instance.alignedReallocate(c, 32, 32);
assert(c.ptr); assert(c.ptr);
version (LDC_AddressSanitizer) {} else // AddressSanitizer does not support such large memory allocations (0x10000000000 max)
version (DragonFlyBSD) {} else /* FIXME: Malloc on DragonFly does not return NULL when allocating more than UINTPTR_MAX version (DragonFlyBSD) {} else /* FIXME: Malloc on DragonFly does not return NULL when allocating more than UINTPTR_MAX
* $(LINK: https://bugs.dragonflybsd.org/issues/3114, dragonfly bug report) * $(LINK: https://bugs.dragonflybsd.org/issues/3114, dragonfly bug report)
* $(LINK: https://github.com/dlang/druntime/pull/1999#discussion_r157536030, PR Discussion) */ * $(LINK: https://github.com/dlang/druntime/pull/1999#discussion_r157536030, PR Discussion) */

View File

@ -1847,3 +1847,168 @@ if (isCallable!(F))
static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD)));
} }
} }
// Converts an unsigned integer to a compile-time string constant.
private enum toCtString(ulong n) = n.stringof[0 .. $ - "LU".length];
// Check that .stringof does what we expect, since it's not guaranteed by the
// language spec.
@safe unittest
{
assert(toCtString!0 == "0");
assert(toCtString!123456 == "123456");
}
/**
* Passes the fields of a struct as arguments to a function.
*
* Can be used with a $(LINK2 https://dlang.org/spec/expression.html#function_literals,
* function literal) to give temporary names to the fields of a struct or
* tuple.
*
* Params:
* fun = Callable that the struct's fields will be passed to.
*
* Returns:
* A function that accepts a single struct as an argument and passes its
* fields to `fun` when called.
*/
template bind(alias fun)
{
/**
* Params:
* args = The struct or tuple whose fields will be used as arguments.
*
* Returns: `fun(args.tupleof)`
*/
auto ref bind(T)(auto ref T args)
if (is(T == struct))
{
import std.meta : Map = staticMap;
import core.lifetime : move;
// Forwards the i'th member of `args`
// Needed because core.lifetime.forward doesn't work on struct members
template forwardArg(size_t i)
{
static if (__traits(isRef, args) || !is(typeof(move(args.tupleof[i]))))
enum forwardArg = "args.tupleof[" ~ toCtString!i ~ "], ";
else
enum forwardArg = "move(args.tupleof[" ~ toCtString!i ~ "]), ";
}
static if (args.tupleof.length == 0)
enum argList = "";
else
alias argList = Map!(forwardArg, Iota!(args.tupleof.length));
return mixin("fun(", argList, ")");
}
}
/// Giving names to tuple elements
@safe unittest
{
import std.typecons : tuple;
auto name = tuple("John", "Doe");
string full = name.bind!((first, last) => first ~ " " ~ last);
assert(full == "John Doe");
}
/// Passing struct fields to a function
@safe unittest
{
import std.algorithm.comparison : min, max;
struct Pair
{
int a;
int b;
}
auto p = Pair(123, 456);
assert(p.bind!min == 123); // min(p.a, p.b)
assert(p.bind!max == 456); // max(p.a, p.b)
}
/// In a range pipeline
@safe unittest
{
import std.algorithm.iteration : map, filter;
import std.algorithm.comparison : equal;
import std.typecons : tuple;
auto ages = [
tuple("Alice", 35),
tuple("Bob", 64),
tuple("Carol", 21),
tuple("David", 39),
tuple("Eve", 50)
];
auto overForty = ages
.filter!(bind!((name, age) => age > 40))
.map!(bind!((name, age) => name));
assert(overForty.equal(["Bob", "Eve"]));
}
// Zero arguments
@safe unittest
{
struct Empty {}
assert(Empty().bind!(() => 123) == 123);
}
// Non-copyable arguments
@safe unittest
{
import std.typecons : tuple;
static struct NoCopy
{
int n;
@disable this(this);
}
static struct Pair
{
NoCopy a, b;
}
static auto fun(NoCopy a, NoCopy b)
{
return tuple(a.n, b.n);
}
auto expected = fun(NoCopy(1), NoCopy(2));
assert(Pair(NoCopy(1), NoCopy(2)).bind!fun == expected);
}
// ref arguments
@safe unittest
{
import std.typecons : tuple;
auto t = tuple(123, 456);
t.bind!((ref int a, int b) { a = 789; b = 1011; });
assert(t[0] == 789);
assert(t[1] == 456);
}
// auto ref arguments
@safe unittest
{
import std.typecons : tuple;
auto t = tuple(123);
t.bind!((auto ref x) {
static assert(__traits(isRef, x));
});
tuple(123).bind!((auto ref x) {
static assert(!__traits(isRef, x));
});
}

View File

@ -13,6 +13,7 @@ include:
License: Boost License 1.0 License: Boost License 1.0
Authors: Paul Backus Authors: Paul Backus
Source: $(PHOBOSSRC std/sumtype.d)
+/ +/
module std.sumtype; module std.sumtype;

View File

@ -1209,6 +1209,15 @@ do
assert("ë"w.decode(i) == 'ë' && i == 1); assert("ë"w.decode(i) == 'ë' && i == 1);
} }
@safe pure unittest // https://issues.dlang.org/show_bug.cgi?id=22867
{
import std.conv : hexString;
string data = hexString!"f787a598";
size_t offset = 0;
try data.decode(offset);
catch (UTFException ex) assert(offset == 0);
}
/++ /++
`decodeFront` is a variant of $(LREF decode) which specifically decodes `decodeFront` is a variant of $(LREF decode) which specifically decodes
the first code point. Unlike $(LREF decode), `decodeFront` accepts any the first code point. Unlike $(LREF decode), `decodeFront` accepts any
@ -1671,7 +1680,6 @@ if (
} }
} }
index += i + 1;
static if (i == 3) static if (i == 3)
{ {
if (d > dchar.max) if (d > dchar.max)
@ -1682,6 +1690,8 @@ if (
throw invalidUTF(); throw invalidUTF();
} }
} }
index += i + 1;
return d; return d;
} }
} }