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
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];
}
alias opDollar = length;
/***********************************
* Extract the data as a slice and take ownership of it.
*
@ -879,3 +881,36 @@ unittest
s = unsignedToTempString(29, buf[], 16);
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
*/
UnionExp Index(Type type, Expression e1, Expression e2)
UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
{
UnionExp ue = void;
Loc loc = e1.loc;
@ -1255,8 +1255,9 @@ UnionExp Index(Type type, Expression e1, Expression e2)
TypeSArray tsa = cast(TypeSArray)e1.type.toBasetype();
uinteger_t length = tsa.dim.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);
emplaceExp!(ErrorExp)(&ue);
}

View File

@ -22,6 +22,7 @@ import dmd.identifier;
import dmd.lexer;
import dmd.parse;
import dmd.errors;
import dmd.root.array;
import dmd.root.filename;
import dmd.common.outbuffer;
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 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,
const ref TARGET target)
{
@ -47,6 +66,7 @@ final class CParser(AST) : Parser!AST
mod = _module;
linkage = LINK.c;
Ccompile = true;
this.packalign.setDefault();
// Configure sizes for C `long`, `long double`, `wchar_t`, ...
this.boolsize = target.boolsize;
@ -130,6 +150,7 @@ final class CParser(AST) : Parser!AST
//printf("cparseStatement()\n");
const funcTypeIdsLengthSave = funcTypeIds.length;
auto symbolsSave = symbols;
if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)))
symbols = new AST.Dsymbols();
@ -572,6 +593,7 @@ final class CParser(AST) : Parser!AST
if (pEndloc)
*pEndloc = prevloc;
symbols = symbolsSave;
funcTypeIds.setDim(funcTypeIdsLengthSave);
return s;
}
@ -1551,6 +1573,7 @@ final class CParser(AST) : Parser!AST
return;
}
const funcTypeIdsLengthSave = funcTypeIds.length;
auto symbolsSave = symbols;
Specifier specifier;
specifier.packalign = this.packalign;
@ -1660,11 +1683,13 @@ final class CParser(AST) : Parser!AST
t.value == TOK.leftCurly) // start of compound-statement
{
auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
funcTypeIds.setDim(funcTypeIdsLengthSave);
symbols = symbolsSave;
symbols.push(s);
return;
}
AST.Dsymbol s = null;
funcTypeIds.setDim(funcTypeIdsLengthSave);
symbols = symbolsSave;
if (!symbols)
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)
s = new AST.AliasDeclaration(token.loc, id, dt);
}
@ -1743,7 +1772,8 @@ final class CParser(AST) : Parser!AST
}
// declare the symbol
assert(id);
if (dt.isTypeFunction())
if (isFunctionTypedef(dt))
{
if (hasInitializer)
error("no initializer for function declaration");
@ -4546,5 +4576,238 @@ final class CParser(AST) : Parser!AST
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());
}
__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 typeb = e.type.toBasetype();
@ -2453,7 +2453,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
int offset;
e.func.tookAddressOf++;
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();
result.type = t;
return result;
@ -2469,7 +2469,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
int 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
f.tookAddressOf++;
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;
}
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);
__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)
{
@ -232,37 +232,37 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.TypeInfo)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.dtypeinfo = this;
}
if (id == Id.TypeInfo_Class)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoclass = this;
}
if (id == Id.TypeInfo_Interface)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfointerface = this;
}
if (id == Id.TypeInfo_Struct)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfostruct = this;
}
if (id == Id.TypeInfo_Pointer)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfopointer = this;
}
if (id == Id.TypeInfo_Array)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoarray = this;
}
if (id == Id.TypeInfo_StaticArray)
@ -274,61 +274,61 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.TypeInfo_AssociativeArray)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoassociativearray = this;
}
if (id == Id.TypeInfo_Enum)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoenum = this;
}
if (id == Id.TypeInfo_Function)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfofunction = this;
}
if (id == Id.TypeInfo_Delegate)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfodelegate = this;
}
if (id == Id.TypeInfo_Tuple)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfotypelist = this;
}
if (id == Id.TypeInfo_Const)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoconst = this;
}
if (id == Id.TypeInfo_Invariant)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoinvariant = this;
}
if (id == Id.TypeInfo_Shared)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfoshared = this;
}
if (id == Id.TypeInfo_Wild)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfowild = this;
}
if (id == Id.TypeInfo_Vector)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
Type.typeinfovector = this;
}
}
@ -336,32 +336,32 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (id == Id.Object)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
object = this;
}
if (id == Id.Throwable)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
throwable = this;
}
if (id == Id.Exception)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
exception = this;
}
if (id == Id.Error)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
errorException = this;
}
if (id == Id.cpp_type_info_ptr)
{
if (!inObject)
error("%s", msg);
error("%s", msg.ptr);
cpp_type_info_ptr = this;
}

View File

@ -29,6 +29,7 @@ import dmd.errors;
import dmd.expression;
import dmd.func;
import dmd.globals;
import dmd.gluelayer;
import dmd.id;
import dmd.identifier;
import dmd.init;
@ -227,6 +228,8 @@ extern (C++) abstract class Declaration : Dsymbol
enum wasRead = 1; // set if AliasDeclaration was read
enum ignoreRead = 2; // ignore any reads of AliasDeclaration
Symbol* isym; // import version of csym
// overridden symbol with pragma(mangle, "...")
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
{
Dsymbol aliassym;
Dsymbol aliassym; // alias ident = aliassym;
Dsymbol overnext; // next in overload list
Dsymbol _import; // !=null if unresolved internal alias for selective import

View File

@ -119,6 +119,7 @@ public:
LINK linkage;
short inuse; // used to detect cycles
uint8_t adFlags;
Symbol* isym; // import version of csym
DString mangleOverride; // overridden symbol with pragma(mangle, "...")
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());
if (global.params.emitMakeDeps)
{
global.params.makeDeps.push(srcfile.toChars());
}
bool success;
if (auto readResult = FileManager.fileManager.lookup(srcfile))
{
srcBuffer = readResult;
return true;
success = true;
}
auto readResult = File.read(srcfile.toChars());
if (loadSourceBuffer(loc, readResult))
else
{
FileManager.fileManager.add(srcfile, srcBuffer);
return true;
auto readResult = File.read(srcfile.toChars());
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

View File

@ -245,8 +245,6 @@ extern (C++) class Dsymbol : ASTNode
/// C++ namespace this symbol belongs to
CPPNamespaceDeclaration cppnamespace;
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
Scope* _scope; // !=null means context to use for semantic()
const(char)* prettystring; // cached value of toPrettyChars()
@ -257,10 +255,6 @@ extern (C++) class Dsymbol : ASTNode
DeprecatedDeclaration depdecl; // customized deprecation message
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()
{
//printf("Dsymbol::Dsymbol(%p)\n", this);
@ -811,7 +805,7 @@ extern (C++) class Dsymbol : ASTNode
Dsymbol s2 = sds.symtabLookup(this,ident);
// 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))
return;
@ -1214,17 +1208,65 @@ extern (C++) class Dsymbol : ASTNode
*/
void addComment(const(char)* comment)
{
//if (comment)
// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
if (!this.comment)
this.comment = comment;
else if (comment && strcmp(cast(char*)comment, cast(char*)this.comment) != 0)
if (!comment || !*comment)
return;
//printf("addComment '%s' to Dsymbol %p '%s'\n", comment, this, toChars());
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
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.
*/
@ -1247,6 +1289,18 @@ extern (C++) class Dsymbol : ASTNode
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)

View File

@ -175,8 +175,6 @@ public:
/// C++ namespace this symbol belongs to
CPPNamespaceDeclaration *namespace_;
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
Scope *_scope; // !=NULL means context to use for semantic()
const utf8_t *prettystring;
@ -185,7 +183,6 @@ public:
unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
DeprecatedDeclaration *depdecl; // customized deprecation message
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 *);
const char *toChars() const;
@ -252,6 +249,10 @@ public:
virtual void checkCtorConstInit() { }
virtual void addComment(const utf8_t *comment);
const utf8_t *comment(); // current value of comment
UnitTestDeclaration *ddocUnittest();
void ddocUnittest(UnitTestDeclaration *);
bool inNonRoot();

View File

@ -2140,6 +2140,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
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;
if (ed.isAnonymous())
sce = sc;
@ -3085,6 +3091,25 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
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))
return;
@ -3550,6 +3575,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
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 fdc = cd.vtbl[vi].isFuncDeclaration();
// This function is covariant with fdv
@ -4625,6 +4659,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sd.deferred.semantic2(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)
@ -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);
// @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.087
// Make an error in 2.091
// @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.100
// 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
if (0 && // deprecation disabled for now to accommodate existing extensive use
cldec.storage_class & STC.scope_)
if (cldec.storage_class & STC.scope_)
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
* an existing instance.
*/
static if (__VERSION__ >= 2099)
res = (cast()ti).equalsx(cast()s.ti);
else // https://issues.dlang.org/show_bug.cgi?id=22717
static if (__VERSION__ < 2099) // https://issues.dlang.org/show_bug.cgi?id=22717
res = (cast()s.ti).equalsx(cast()ti);
else
res = (cast()ti).equalsx(cast()s.ti);
}
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)
{
// 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];
if (!arg.type.hasPointers())
return false;
continue;
//printf("\targ[%d]: %s\n", i, arg.toChars());
@ -620,7 +620,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
return false;
if (va == fd.vthis) // `this` of a non-static member function is considered to be the first parameter
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 false;
@ -1029,7 +1029,6 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
*/
!(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
&& 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;
// https://dlang.org/spec/function.html#return-ref-parameters
// Only look for errors if in module listed on command line
if (p == sc.func)
{
//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)
)
{
// Only look for errors if in module listed on command line
// https://issues.dlang.org/show_bug.cgi?id=17029
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)
{
printf("byref `%s`\n", v.toChars());
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");
printf("byref `%s` %s\n", v.toChars(), toChars(buildScopeRef(v.storage_class)));
}
// '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];
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);
else if ((stc & (STC.ref_)) && (stc & STC.return_))
else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
{
if (tf.isref)
{
@ -1974,9 +1968,10 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
{
Parameter p = tf.parameterList[i - j];
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);
else if ((stc & STC.scope_) && (stc & STC.return_))
else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
{
if (auto de = arg.isDelegateExp())
{

View File

@ -72,10 +72,15 @@ import dmd.typesem;
import dmd.visitor;
enum LOGSEMANTIC = false;
void emplaceExp(T : Expression, Args...)(void* p, Args args)
{
scope tmp = new T(args);
memcpy(p, cast(void*)tmp, __traits(classInstanceSize, T));
static if (__VERSION__ < 2099)
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)
@ -5831,6 +5836,13 @@ extern (C++) final class IndexExp : BinExp
//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()
{
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
}
if (!(sc.flags & SCOPE.Cfile))
{
/* https://issues.dlang.org/show_bug.cgi?id=21272
* 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();
}
}
else if (exp.e1.op == EXP.call)
else if (auto ce = exp.e1.isCallExp())
{
CallExp ce = cast(CallExp)exp.e1;
if (ce.e1.type.ty == Tfunction)
{
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());
}
}
if (!checkAddressCall(sc, ce, "take address of"))
return setError();
}
else if (exp.e1.op == EXP.index)
{
@ -7800,7 +7792,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
Type t1b = exp.e1.type.toBasetype();
if (t1b.ty == Tpointer)
if (auto tp = t1b.isTypePointer())
{
if (t1b.isPtrToFunction())
{
@ -7809,7 +7801,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
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();
}
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))
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)
@ -8446,7 +8464,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (length)
{
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;
}
/****************************************************
* 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.
* 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())
{
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
@ -167,7 +168,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
auto t2 = e2.type.toBasetype();
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);

View File

@ -68,8 +68,6 @@ class Lexer
ubyte long_doublesize; /// size of C long double, 8 or D real.sizeof
ubyte wchar_tsize; /// size of C wchar_t, 2 or 4
structalign_t packalign; /// current state of #pragma pack alignment (ImportC)
private
{
const(char)* base; // pointer to start of buffer
@ -89,10 +87,6 @@ class Lexer
int lastDocLine; // last line of previous doc comment
Token* tokenFreelist;
// ImportC #pragma pack stack
Array!Identifier* records; // identifers (or null)
Array!structalign_t* packs; // parallel alignment values
}
nothrow:
@ -124,7 +118,6 @@ class Lexer
this.commentToken = commentToken;
this.inTokenStringConstant = 0;
this.lastDocLine = 0;
this.packalign.setDefault();
//initKeywords();
/* If first line starts with '#!', ignore the line
*/
@ -381,24 +374,18 @@ class Lexer
goto case_ident;
case 'r':
if (p[1] != '"')
if (Ccompile || p[1] != '"')
goto case_ident;
p++;
goto case '`';
case '`':
if (Ccompile)
goto default;
wysiwygStringConstant(t);
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':
if (Ccompile)
goto case_ident;
if (p[1] == '"')
{
p++;
@ -438,7 +425,7 @@ class Lexer
//case 'u':
case 'v':
case 'w':
/*case 'x':*/
case 'x':
case 'y':
case 'z':
case 'A':
@ -676,6 +663,7 @@ class Lexer
endOfLine();
continue;
case '+':
if (!Ccompile)
{
int nest;
startLoc = loc();
@ -745,6 +733,7 @@ class Lexer
}
continue;
}
break;
default:
break;
}
@ -1051,35 +1040,8 @@ class Lexer
case '#':
{
p++;
Token n;
scan(&n);
if (Ccompile && n.value == TOK.int32Literal)
{
poundLine(n, true);
if (parseSpecialTokenSequence())
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;
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:
---
@ -2666,6 +2550,37 @@ class Lexer
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:
* #line linnum [filespec]
@ -2680,7 +2595,7 @@ class Lexer
* References:
* 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;
const(char)* filespec = null;
@ -2806,183 +2721,10 @@ class Lexer
error(loc, "#line integer [\"filespec\"]\\n expected");
}
/*********************************************
* C11 6.10.6 Pragma directive
* # pragma pp-tokens(opt) new-line
* The C preprocessor sometimes leaves pragma directives in
* the preprocessed output. Ignore them.
* Upon return, p is at start of next line.
*/
private void pragmaDirective(const ref Loc loc)
{
Token n;
scan(&n);
if (n.value == TOK.identifier && n.ident == Id.pack)
return pragmaPack(loc);
skipToNextLine();
}
/*********
* ImportC
* # pragma pack
* https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
* https://docs.microsoft.com/en-us/cpp/preprocessor/pack
* Scanner is on the `pack`
* Params:
* startloc = location to use for error messages
*/
private void pragmaPack(const ref Loc startloc)
{
const loc = startloc;
Token n;
scan(&n);
if (n.value != TOK.leftParenthesis)
{
error(loc, "left parenthesis expected to follow `#pragma pack`");
skipToNextLine();
return;
}
void closingParen()
{
if (n.value != TOK.rightParenthesis)
{
error(loc, "right parenthesis expected to close `#pragma pack(`");
}
skipToNextLine();
}
void setPackAlign(ref const Token t)
{
const n = t.unsvalue;
if (n < 1 || n & (n - 1) || ushort.max < n)
error(loc, "pack must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
packalign.set(cast(uint)n);
packalign.setPack(true);
}
scan(&n);
if (!records)
{
records = new Array!Identifier;
packs = new Array!structalign_t;
}
/* # pragma pack ( show )
*/
if (n.value == TOK.identifier && n.ident == Id.show)
{
if (packalign.isDefault())
warning(startloc, "current pack attribute is default");
else
warning(startloc, "current pack attribute is %d", packalign.get());
scan(&n);
return closingParen();
}
/* # pragma pack ( push )
* # pragma pack ( push , identifier )
* # pragma pack ( push , integer )
* # pragma pack ( push , identifier , integer )
*/
if (n.value == TOK.identifier && n.ident == Id.push)
{
scan(&n);
Identifier record = null;
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
record = n.ident;
scan(&n);
if (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
}
else
error(loc, "alignment value expected, not `%s`", n.toChars());
}
this.records.push(record);
this.packs.push(packalign);
return closingParen();
}
/* # pragma pack ( pop )
* # pragma pack ( pop PopList )
* PopList :
* , IdentifierOrInteger
* , IdentifierOrInteger PopList
* IdentifierOrInteger:
* identifier
* integer
*/
if (n.value == TOK.identifier && n.ident == Id.pop)
{
scan(&n);
while (n.value == TOK.comma)
{
scan(&n);
if (n.value == TOK.identifier)
{
for (size_t len = this.records.length; len; --len)
{
if ((*this.records)[len - 1] == n.ident)
{
packalign = (*this.packs)[len - 1];
this.records.setDim(len - 1);
this.packs.setDim(len - 1);
break;
}
}
scan(&n);
}
else if (n.value == TOK.int32Literal)
{
setPackAlign(n);
this.records.push(null);
this.packs.push(packalign);
scan(&n);
}
}
return closingParen();
}
/* # pragma pack ( integer )
*/
if (n.value == TOK.int32Literal)
{
setPackAlign(n);
scan(&n);
return closingParen();
}
/* # pragma pack ( )
*/
if (n.value == TOK.rightParenthesis)
{
packalign.setDefault();
return closingParen();
}
error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
skipToNextLine();
}
/***************************************
* Scan forward to start of next line.
*/
private void skipToNextLine()
final void skipToNextLine()
{
while (1)
{
@ -3557,5 +3299,3 @@ unittest
assert(tok == TOK.endOfFile);
}
}

View File

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

View File

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

View File

@ -396,13 +396,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
fd = search_function(ad, id);
if (fd)
{
// @@@DEPRECATED_2.098@@@.
// Deprecated in 2.088
// Make an error in 2.098
e.deprecation("`%s` is deprecated. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
// Rewrite +e1 as e1.add()
result = build_overload(e.loc, sc, e.e1, null, fd);
return result;
// @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088, made an error in 2.100
e.error("`%s` is obsolete. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
return ErrorExp.get();
}
}
// 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);
if (s && id != Id.assign)
{
// @@@DEPRECATED_2.098@@@.
// Deprecated in 2.088
// Make an error in 2.098
// @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088, made an error in 2.100
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
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)
@ -689,10 +686,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
s_r = null;
if (s_r)
{
// @@@DEPRECATED_2.098@@@.
// Deprecated in 2.088
// Make an error in 2.098
e.deprecation("`%s` is deprecated. Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr);
// @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088, made an error in 2.100
e.error("`%s` is obsolete. 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);
if (s)
{
// @@@DEPRECATED_2.098@@@.
// Deprecated in 2.088
// Make an error in 2.098
// @@@DEPRECATED_2.110@@@.
// Deprecated in 2.088, made an error in 2.100
scope char[] op = EXPtoString(e.op).dup;
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:
* fes = the foreach statement
* 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:
* false for errors
*/
@ -1588,8 +1586,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
*/
if (FuncDeclaration fd = sapply.isFuncDeclaration())
{
auto fdapply = findBestOpApplyMatch(ethis, fd, fes.parameters);
if (fdapply)
if (auto fdapply = findBestOpApplyMatch(ethis, fd, fes.parameters))
{
// Fill in any missing types on foreach parameters[]
matchParamsToOpApply(fdapply.type.isTypeFunction(), fes.parameters, true);
@ -1598,7 +1595,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
}
return false;
}
return sapply !is null;
return true; // shouldn't this be false?
}
Parameter p = (*fes.parameters)[0];

View File

@ -338,9 +338,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
void visitTuple(TupleExp e)
{
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)
{
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)
{
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);
}
}
@ -374,9 +374,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
e.stageflags |= stageOptimize;
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;
@ -647,9 +647,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// Optimize parameters
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)
{
Type t1 = e.e1.type.toBasetype();
if (t1.ty == Tdelegate)
t1 = t1.nextOf();
if (auto td = t1.isTypeDelegate())
t1 = td.next;
// t1 can apparently be void for __ArrayDtor(T) calls
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];
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)
{
//printf(" returning2 %s\n", e.e1.toChars());
L1:
// Returning e1 with changing its type
ret = (e1old == e.e1 ? e.e1.copy() : e.e1);
ret.type = e.type;
return;
return returnE_e1();
}
/* 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))
{
//printf(" returning3 %s\n", e.e1.toChars());
goto L1;
return returnE_e1();
}
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)
return error();
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.
// https://issues.dlang.org/show_bug.cgi?id=16980
cdfrom.size(e.loc);
@ -760,13 +763,13 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (cdto.isBaseOf(cdfrom, &offset) && offset == 0)
{
//printf(" returning4 %s\n", e.e1.toChars());
goto L1;
return returnE_e1();
}
}
if (e.e1.type.mutableOf().unSharedOf().equals(e.to.mutableOf().unSharedOf()))
{
//printf(" returning5 %s\n", e.e1.toChars());
goto L1;
return returnE_e1();
}
if (e.e1.isConst())
{
@ -781,7 +784,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return error();
if (esz == e1sz)
goto L1;
return returnE_e1();
}
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
if (keepLvalue && ex.op == EXP.arrayLiteral)
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()))
ret = e;
}

View File

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

View File

@ -866,7 +866,6 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
assert(t.ty == Tdelegate);
tfld = cast(TypeFunction)t.nextOf();
}
//printf("tfld = %s\n", tfld.toChars());
}
}
}
@ -1442,12 +1441,12 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
/* Call:
* _aApply(aggr, flde)
*/
__gshared const(char)** fntab =
static immutable fntab =
[
"cc", "cw", "cd",
"wc", "cc", "wd",
"dc", "dw", "dd"
];
];
const(size_t) BUFFER_LEN = 7 + 1 + 2 + dim.sizeof * 3 + 1;
char[BUFFER_LEN] fdname;
@ -1470,7 +1469,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
assert(0);
}
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);
FuncDeclaration fdapply;
@ -2475,68 +2474,66 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
Expression initialExp = cs.exp;
// 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())
{
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;
// Remove all the casts the user and/or implicitCastTo may introduce
// otherwise we'd sometimes fail the check below.
while (e.op == EXP.cast_)
e = (cast(CastExp)e).e1;
Expression e = cs.exp;
// Remove all the casts the user and/or implicitCastTo may introduce
// otherwise we'd sometimes fail the check below.
while (e.op == EXP.cast_)
e = (cast(CastExp)e).e1;
/* This is where variables are allowed as case expressions.
*/
if (e.op == EXP.variable)
/* This is where variables are allowed as case expressions.
*/
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;
VarDeclaration v = ve.var.isVarDeclaration();
Type t = cs.exp.type.toBasetype();
if (v && (t.isintegral() || t.ty == Tclass))
/* Flag that we need to do special code generation
* 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 (!v.isConst() && !v.isImmutable())
{
/* Flag that we need to do special code generation
* for this, i.e. generate a sequence of if-then-else
*/
sw.hasVars = 1;
cs.error("`case` variables have to be `const` or `immutable`");
}
/* TODO check if v can be uninitialized at that point.
*/
if (!v.isConst() && !v.isImmutable())
{
cs.error("`case` variables have to be `const` or `immutable`");
}
if (sw.isFinal)
{
cs.error("`case` variables not allowed in `final switch` statements");
errors = true;
}
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;
}
/* 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;
break;
}
goto L1;
}
else
cs.exp = cs.exp.ctfeInterpret();
}
else
cs.exp = cs.exp.ctfeInterpret();
if (StringExp se = cs.exp.toStringExp())
cs.exp = se;

View File

@ -124,7 +124,6 @@ enum TOK : ubyte
// Leaf operators
identifier,
string_,
hexadecimalString,
this_,
super_,
error,
@ -854,8 +853,6 @@ extern (C++) struct Token
TOK.wchar_tLiteral: "wchar_tv",
TOK.whitespace: "whitespace",
TOK.hexadecimalString: "xstring",
// C only keywords
TOK.inline : "inline",
TOK.register : "register",
@ -1008,24 +1005,6 @@ nothrow:
p = buf.extractSlice().ptr;
}
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.enum_:
case TOK.struct_:

View File

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

View File

@ -666,9 +666,13 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
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)
{
.error(loc, "`cent` and `ucent` types not implemented");
.error(loc, "`cent` and `ucent` types are obsolete, use `core.int128.Cent` instead");
return error();
}
@ -1188,6 +1192,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
tf.isref = true;
if (sc.stc & STC.return_)
tf.isreturn = true;
if (sc.stc & STC.returnScope)
tf.isreturnscope = true;
if (sc.stc & STC.returninferred)
tf.isreturninferred = true;
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 = build_overload(e.loc, sc, e, null, fd);
// @@@DEPRECATED_2.092@@@.
e.deprecation("`opDot` is deprecated. Use `alias this`");
e = new DotIdExp(e.loc, e, ident);
return returnExp(e.expressionSemantic(sc));
// @@@DEPRECATED_2.110@@@.
// Deprecated in 2.082, made an error in 2.100.
e.error("`opDot` is obsolete. Use `alias this`");
return ErrorExp.get();
}
/* Look for overloaded opDispatch to see if we should forward request

View File

@ -106,20 +106,20 @@ public:
tree type = build_ctype (d->type);
/* Not all kinds of D enums create a TYPE_DECL. */
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)
{
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)
{
/* Want the RECORD_TYPE, not POINTER_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. */

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!( I*, C* ) == I* ));
//static assert(Error!( C**, I** ));
static assert(is( X!( C**, I** ) == const(I*)* ));
static assert(Error!( C**, I** ));
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], D[4] ));
static assert(is( X!( C[4], const(B)[4] ) == const(B)[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(I)[4] ));
static assert(Error!( C[4], const(D)[4] ));
static assert(Error!( C*[4], B*[4] ));
static assert(Error!( C*[4], I*[4] ));
static assert(Error!( C*[4], D*[4] ));
static assert(is( X!( C*[4], const(B*)[4] ) == const(B*)[] )); // !?
//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(I*)[4] ));
static assert(Error!( C*[4], const(D*)[4] ));
static assert(Error!( C*[4], 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()
{
abstract class AbstractC{}

View File

@ -2,47 +2,47 @@
REQUIRED_ARGS: -de
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(106): Deprecation: `opAdd_r` is deprecated. 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(108): Deprecation: `opSub_r` is deprecated. 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(110): Deprecation: `opMul_r` is deprecated. 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(112): Deprecation: `opDiv_r` is deprecated. 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(114): Deprecation: `opMod_r` is deprecated. 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(117): Deprecation: `opOr` is deprecated. 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(120): Deprecation: `opShl` is deprecated. 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(122): Deprecation: `opShr` is deprecated. 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(124): Deprecation: `opUShr` is deprecated. 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(127): Deprecation: `opCat` is deprecated. 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(130): Deprecation: `opNeg` is deprecated. 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(132): Deprecation: `opPostInc` is deprecated. 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(134): Deprecation: `opStar` is deprecated. 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(137): Deprecation: `opIn_r` is deprecated. 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(140): Deprecation: `opSubAssign` is deprecated. 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(142): Deprecation: `opDivAssign` is deprecated. 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(144): Deprecation: `opAndAssign` is deprecated. 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(146): Deprecation: `opXorAssign` is deprecated. 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(148): Deprecation: `opShrAssign` is deprecated. 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(150): Deprecation: `opCatAssign` is deprecated. 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(105): Error: `opAdd` is obsolete. Use `opBinary(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): Error: `opSub` is obsolete. Use `opBinary(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): Error: `opMul` is obsolete. Use `opBinary(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): Error: `opDiv` is obsolete. Use `opBinary(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): Error: `opMod` is obsolete. Use `opBinary(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): Error: `opAnd` is obsolete. 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): Error: `opXor` is obsolete. 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): Error: `opShl_r` is obsolete. Use `opBinaryRight(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): Error: `opShr_r` is obsolete. Use `opBinaryRight(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): Error: `opUShr_r` is obsolete. Use `opBinaryRight(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): Error: `opCat_r` is obsolete. Use `opBinaryRight(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): Error: `opCom` is obsolete. 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): Error: `opPostDec` is obsolete. 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): Error: `opIn` is obsolete. Use `opBinary(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): Error: `opAddAssign` is obsolete. 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): Error: `opMulAssign` is obsolete. 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): Error: `opModAssign` is obsolete. 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): Error: `opOrAssign` is obsolete. 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): Error: `opShlAssign` is obsolete. 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): Error: `opUShrAssign` is obsolete. 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): Error: `opCom` is obsolete. Use `opUnary(string op)() if (op == "~")` instead.
---
*/

View File

@ -2,7 +2,8 @@
/*
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";

View File

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

View File

@ -1,7 +1,7 @@
/*
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:
---
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
/* 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 { }

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:
---
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: declaration expected, not `x"01 02 03"w`
fail_compilation/lexer1.d(30): Error: no identifier for declarator `x`
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(32): Error: declaration expected, not `0.1`
fail_compilation/lexer1.d(33): Error: declaration expected, not `0.1f`

View File

@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/lexer2.d(16): Error: odd number (3) of hex characters in hex string
fail_compilation/lexer2.d(16): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"123"` instead.
fail_compilation/lexer2.d(17): Error: non-hex character 'G' in hex string
fail_compilation/lexer2.d(17): Error: Built-in hex string literals are obsolete, use `std.conv.hexString!"123G"` instead.
fail_compilation/lexer2.d(16): Error: semicolon expected following auto declaration, not `"123"`
fail_compilation/lexer2.d(16): Error: declaration expected, not `"123"`
fail_compilation/lexer2.d(17): Error: semicolon expected following auto declaration, not `"123G"`
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(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`

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:
---
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
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 interface I { }
//scope struct S { }
scope struct S { }
scope enum E { e }

View File

@ -1,15 +1,19 @@
/* 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(37): 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(43): Error: returning `&identityPtr(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(41): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
fail_compilation/test15191.d(47): Error: cannot take address of `ref return` of `identityPtr()` in `@safe` function `addrOfRefTransitive`
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=22519
// https://issues.dlang.org/show_bug.cgi?id=22539
@safe:
ref int foo(return ref int s)
@ -50,3 +54,17 @@ int* addrOfRefGlobal()
{
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
* 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;
/************************/
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:
---
fail_compilation/typeerrors.d(36): Error: tuple index 4 exceeds 4
fail_compilation/typeerrors.d(38): Error: variable `x` cannot be read at compile time
fail_compilation/typeerrors.d(39): Error: cannot have array of `void()`
fail_compilation/typeerrors.d(40): Error: cannot have array of scope `typeerrors.C`
fail_compilation/typeerrors.d(32): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
fail_compilation/typeerrors.d(37): Error: tuple index 4 exceeds 4
fail_compilation/typeerrors.d(39): Error: variable `x` cannot be read at compile time
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(44): Error: `int[5]` is not an expression
fail_compilation/typeerrors.d(46): Error: variable `x` is used as a type
fail_compilation/typeerrors.d(37): variable `x` is declared here
fail_compilation/typeerrors.d(47): 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(50): 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(55): Error: slice `[1..5]` is out of range of [0..4]
fail_compilation/typeerrors.d(56): Error: slice `[2..1]` is out of range of [0..4]
fail_compilation/typeerrors.d(42): Error: cannot have array of scope `typeerrors.C`
fail_compilation/typeerrors.d(45): Error: `int[5]` is not an expression
fail_compilation/typeerrors.d(47): Error: variable `x` is used as a type
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(49): Error: cannot have associative array key 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(52): Error: cannot have associative array of `void()`
fail_compilation/typeerrors.d(54): Error: cannot have parameter of type `void`
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;
@ -65,7 +65,7 @@ void test1()
int ax;
scope class A2
class A2
{
this()
{
@ -96,11 +96,11 @@ void test2()
int status3;
scope class Parent3
class Parent3
{
}
scope class Child3 : Parent3
class Child3 : Parent3
{
this(){
assert(status3==0);

View File

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

View File

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

View File

@ -1,5 +1,10 @@
// REQUIRED_ARGS: -w -de
// REQUIRED_ARGS: -w -dw
// PERMUTE_ARGS:
/* TEST_OUTPUT:
---
runnable/sctor2.d(12): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
---
*/
/***************************************************/
// 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
interface I {}
class X : I {}
static assert(is( X[] : const(I)[] ));
static assert(!is( X[] : const(I)[] ));
// interface to const(base interface) in tail
interface J {}
interface K : I, J {}
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(clear)
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)
string[]
double[]
@ -137,10 +129,7 @@ struct T6
S6 s;
int b = 7;
S6* opDot() return
{
return &s;
}
alias s this;
}
void test6()
@ -169,10 +158,7 @@ class C7
S7 s;
int b = 7;
S7* opDot()
{
return &s;
}
alias s this;
}
void test7()

View File

@ -15,14 +15,6 @@ tuple(height)
tuple(get, get)
tuple(clear)
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)
string[]
double[]

View File

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

View File

@ -239,7 +239,9 @@ struct GCBits
size_t cntWords = lastWord - firstWord;
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;
data[lastWord] = (data[lastWord] & ~mask) | (src & mask);
}

View File

@ -34,7 +34,7 @@ version (StdDdoc)
alias ddoc_long = int;
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
else version (SPARC_Any)
{
import core.stdc.config : c_ulong;
alias fenv_t = c_ulong;
alias fexcept_t = c_ulong;
}

View File

@ -36,20 +36,7 @@ extern (C):
nothrow:
@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))
{
alias int128_t = cent; ///
@ -58,6 +45,10 @@ static if (is(ucent))
version (Windows)
{
alias int8_t = byte; ///
alias int16_t = short; ///
alias uint8_t = ubyte; ///
alias uint16_t = ushort; ///
version (CRuntime_DigitalMars)
{
alias int32_t = cpp_long; ///
@ -71,23 +62,31 @@ version (Windows)
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 = int32_t; ///
alias int_least8_t = byte; ///
alias uint_least8_t = ubyte; ///
alias int_least16_t = short; ///
alias uint_least16_t = ushort; ///
alias int_least32_t = int32_t; ///
alias uint_least32_t = uint32_t; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; ///
alias int_fast16_t = int; ///
alias uint_fast16_t = uint; ///
alias int_fast32_t = int32_t; ///
alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; ///
version (MinGW)
{
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 int_fast64_t = long; ///
alias uint_fast64_t = ulong; ///
alias int_fast64_t = long; ///
alias uint_fast64_t = ulong; ///
alias intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
@ -96,6 +95,10 @@ version (Windows)
}
else version (Darwin)
{
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; ///
@ -124,32 +127,27 @@ else version (Darwin)
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
}
else version (Posix)
else version (linux)
{
alias int32_t = int; ///
alias uint32_t = uint; ///
alias int64_t = long; ///
alias uint64_t = ulong; ///
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 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_least32_t = int; ///
alias uint_least32_t = uint; ///
alias int_least64_t = long; ///
alias uint_least64_t = ulong; ///
version (FreeBSD)
{
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)
version (CRuntime_Musl)
{
alias int_fast8_t = byte; ///
alias uint_fast8_t = ubyte; ///
@ -167,17 +165,221 @@ else version (Posix)
alias int_fast32_t = ptrdiff_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 intptr_t = ptrdiff_t; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
alias uintmax_t = ulong; ///
alias uintptr_t = size_t; ///
alias intmax_t = long; ///
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
{
static assert(0);
static assert(false, "Unsupported architecture.");
}

View File

@ -26,7 +26,7 @@ extern (C++, "std")
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

View File

@ -8,6 +8,8 @@ version (Windows):
extern (C) nothrow @nogc:
@system:
import core.sys.windows.stdc.time;
// Posix version is in core.sys.posix.sys.stat
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; }
}
struct struct_stat
version (CRuntime_DigitalMars)
{
short st_dev;
ushort st_ino;
ushort st_mode;
short st_nlink;
ushort st_uid;
ushort st_gid;
short st_rdev;
short dummy;
int st_size;
int st_atime;
int st_mtime;
int st_ctime;
}
struct struct_stat
{
short st_dev;
ushort st_ino;
ushort st_mode;
short st_nlink;
ushort st_uid;
ushort st_gid;
short st_rdev;
short dummy;
int st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
}
int stat(const(char)*, struct_stat *);
int fstat(int, struct_stat *) @trusted;
int _wstat(const(wchar)*, struct_stat *);
int stat(const(char)*, struct_stat *);
int fstat(int, struct_stat *) @trusted;
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))
{
case T.sizeof:
(cast(T*)result.ptr)[0 .. size * length / T.sizeof] = *cast(T*)init.ptr;
return result;
if (tinext.talign % T.alignof == 0)
{
(cast(T*)result.ptr)[0 .. size * length / T.sizeof] = *cast(T*)init.ptr;
return result;
}
goto default;
}
default:
@ -1118,7 +1122,8 @@ extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
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;
}

View File

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

View File

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

View File

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

View File

@ -7848,12 +7848,12 @@ if (isTimePoint!TP &&
duration = The duration which separates each successive time point in
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 &&
__traits(compiles, TP.init + duration) &&
(dir == Direction.fwd || dir == Direction.bwd))
{
TP func(scope const TP tp)
TP func(return scope const TP tp)
{
static if (dir == Direction.fwd)
return tp + duration;

View File

@ -6269,7 +6269,7 @@ public:
duration = The $(REF Duration, core,time) to add to or subtract from
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 == "-")
{
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.
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 days = getUnitsFromHNSecs!"days"(hnsecs);

View File

@ -392,6 +392,7 @@ version (Posix)
AlignedMallocator.instance.alignedReallocate(c, 32, 32);
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
* $(LINK: https://bugs.dragonflybsd.org/issues/3114, dragonfly bug report)
* $(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)));
}
}
// 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
Authors: Paul Backus
Source: $(PHOBOSSRC std/sumtype.d)
+/
module std.sumtype;

View File

@ -1209,6 +1209,15 @@ do
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
the first code point. Unlike $(LREF decode), `decodeFront` accepts any
@ -1671,7 +1680,6 @@ if (
}
}
index += i + 1;
static if (i == 3)
{
if (d > dchar.max)
@ -1682,6 +1690,8 @@ if (
throw invalidUTF();
}
}
index += i + 1;
return d;
}
}