mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 19:03:59 +08:00
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:
parent
1b85638aff
commit
7e28750395
@ -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.
|
||||
|
@ -1 +1 @@
|
||||
v2.099.0-rc.1
|
||||
v2.099.0
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
//}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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());
|
||||
|
@ -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`)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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_:
|
||||
|
@ -133,7 +133,6 @@ enum class TOK : unsigned char
|
||||
// Leaf operators
|
||||
identifier,
|
||||
string_,
|
||||
hexadecimalString,
|
||||
this_,
|
||||
super_,
|
||||
error,
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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] ));
|
||||
|
@ -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{}
|
||||
|
@ -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.
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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 { }
|
||||
|
9
gcc/testsuite/gdc.test/fail_compilation/fail22827.d
Normal file
9
gcc/testsuite/gdc.test/fail_compilation/fail22827.d
Normal 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;
|
68
gcc/testsuite/gdc.test/fail_compilation/issue22820.d
Normal file
68
gcc/testsuite/gdc.test/fail_compilation/issue22820.d
Normal 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;
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -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`
|
||||
|
27
gcc/testsuite/gdc.test/fail_compilation/opapplyscope.d
Normal file
27
gcc/testsuite/gdc.test/fail_compilation/opapplyscope.d
Normal 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;
|
||||
}
|
||||
}
|
||||
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
41
gcc/testsuite/gdc.test/fail_compilation/test21008.d
Normal file
41
gcc/testsuite/gdc.test/fail_compilation/test21008.d
Normal 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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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);
|
||||
|
@ -3246,7 +3246,7 @@ int test6907()
|
||||
}
|
||||
{
|
||||
S1* p = new S1();
|
||||
if (__ctfe)
|
||||
if (__ctfe)
|
||||
{
|
||||
(*p).__dtor();
|
||||
destroy(p);
|
||||
|
@ -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) {}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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*));
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
/************************************/
|
||||
|
@ -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()
|
||||
|
@ -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[]
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 *);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) */
|
||||
|
@ -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));
|
||||
});
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ include:
|
||||
|
||||
License: Boost License 1.0
|
||||
Authors: Paul Backus
|
||||
Source: $(PHOBOSSRC std/sumtype.d)
|
||||
+/
|
||||
module std.sumtype;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user