d: Merge upstream dmd 65a3da148c, phobos fc06c514a.

D front-end changes:

    - Import latest bug fixes from dmd v2.106.0-beta.1.

Phobos changes:

    - Import latest bug fixes from phobos v2.106.0-beta.1.
    - `std.range.primitives.isForwardRange' now takes an optional
      element type.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 65a3da148c.

libphobos/ChangeLog:

	* src/MERGE: Merge upstream phobos fc06c514a.
This commit is contained in:
Iain Buclaw 2023-11-12 14:21:43 +01:00
parent da332ce109
commit 87b9a01ea7
34 changed files with 1624 additions and 1539 deletions

View file

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

View file

@ -172,7 +172,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
}
if (e.e1.op == EXP.arrayLiteral)
{
return e.e1.modifiableLvalue(sc, e.e1);
return e.e1.modifiableLvalue(sc);
}
return arrayOp(e.isBinExp(), sc);

View file

@ -22,6 +22,7 @@ import dmd.declaration;
import dmd.dsymbol;
import dmd.errorsink;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.init;
@ -80,7 +81,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
if (!f.isDtorDeclaration())
errorSupplementalInferredAttr(f, 10, false, STC.nothrow_);
e.checkOverriddenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
}
else if (func)
{

View file

@ -12,6 +12,7 @@
module dmd.compiler;
import dmd.arraytypes;
import dmd.ctfeexpr;
import dmd.dmodule;
import dmd.expression;
import dmd.mtype;

View file

@ -29,6 +29,7 @@ import dmd.globals;
import dmd.identifier;
import dmd.location;
import dmd.mtype;
import dmd.optimize;
import dmd.typesem;
import dmd.common.outbuffer;
import dmd.rootobject;

View file

@ -2023,6 +2023,9 @@ final class CParser(AST) : Parser!AST
}
symbols.push(s);
}
if (level == LVL.global && !id)
error("expected identifier for declaration");
first = false;
switch (token.value)
@ -2736,7 +2739,7 @@ final class CParser(AST) : Parser!AST
private AST.Type cparseDeclarator(DTR declarator, AST.Type tbase,
out Identifier pident, ref Specifier specifier)
{
//printf("cparseDeclarator(%d, %p)\n", declarator, t);
//printf("cparseDeclarator(%d, %s)\n", declarator, tbase.toChars());
AST.Types constTypes; // all the Types that will need `const` applied to them
/* Insert tx -> t into
@ -2755,6 +2758,7 @@ final class CParser(AST) : Parser!AST
AST.Type parseDecl(AST.Type t)
{
//printf("parseDecl() t: %s\n", t.toChars());
AST.Type ts;
while (1)
{
@ -2770,9 +2774,18 @@ final class CParser(AST) : Parser!AST
break;
case TOK.leftParenthesis: // ( declarator )
//printf("leftParen\n");
/* like: T (*fp)();
* T ((*fp))();
*/
auto tk = &token;
if (!isCDeclarator(tk, declarator))
{
/* Not ( declarator ), might be parameter-list
*/
ts = t;
break;
}
nextToken();
if (token.value == TOK.__stdcall) // T (__stdcall*fp)();
@ -2786,6 +2799,7 @@ final class CParser(AST) : Parser!AST
break;
case TOK.mul: // pointer
//printf("star\n");
t = new AST.TypePointer(t);
nextToken();
// add post fixes const/volatile/restrict/_Atomic
@ -2797,6 +2811,7 @@ final class CParser(AST) : Parser!AST
continue;
default:
//printf("default %s\n", token.toChars());
if (declarator == DTR.xdirect)
{
if (!t || t.isTypeIdentifier())
@ -2914,7 +2929,7 @@ final class CParser(AST) : Parser!AST
if (specifier._pure)
stc |= STC.pure_;
AST.Type tf = new AST.TypeFunction(parameterList, t, lkg, stc);
// tf = tf.addSTC(storageClass); // TODO
//tf = tf.addSTC(storageClass); // TODO
insertTx(ts, tf, t); // ts -> ... -> tf -> t
if (ts != tf)
@ -2927,6 +2942,8 @@ final class CParser(AST) : Parser!AST
}
break;
}
if (declarator == DTR.xdirect && !pident)
error("expected identifier for declarator");
return ts;
}
@ -4556,6 +4573,7 @@ final class CParser(AST) : Parser!AST
*/
private bool isCDeclarator(ref Token* pt, DTR declarator)
{
//printf("isCDeclarator()\n");
auto t = pt;
while (1)
{
@ -4578,6 +4596,8 @@ final class CParser(AST) : Parser!AST
else if (t.value == TOK.leftParenthesis)
{
t = peek(t);
if (t.value == TOK.__stdcall)
t = peek(t);
if (!isCDeclarator(t, declarator))
return false;
if (t.value != TOK.rightParenthesis)

View file

@ -35,75 +35,98 @@ import dmd.root.rmem;
import dmd.tokens;
import dmd.visitor;
/***********************************************************
* A reference to a class, or an interface. We need this when we
* point to a base class (we must record what the type is).
/****************************************************************/
/* A type meant as a union of all the Expression types,
* to serve essentially as a Variant that will sit on the stack
* during CTFE to reduce memory consumption.
*/
extern (C++) final class ClassReferenceExp : Expression
extern (D) struct UnionExp
{
StructLiteralExp value;
extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe
// yes, default constructor does nothing
extern (D) this(Expression e)
{
super(loc, EXP.classReference);
assert(lit && lit.sd && lit.sd.isClassDeclaration());
this.value = lit;
this.type = type;
memcpy(&this, cast(void*)e, e.size);
}
ClassDeclaration originalClass()
/* Extract pointer to Expression
*/
extern (D) Expression exp() return
{
return value.sd.isClassDeclaration();
return cast(Expression)&u;
}
// Return index of the field, or -1 if not found
private int getFieldIndex(Type fieldtype, uint fieldoffset)
/* Convert to an allocated Expression
*/
extern (D) Expression copy()
{
ClassDeclaration cd = originalClass();
uint fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
Expression e = exp();
//if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
assert(e.size <= u.sizeof);
switch (e.op)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size())
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
case EXP.cantExpression: return CTFEExp.cantexp;
case EXP.voidExpression: return CTFEExp.voidexp;
case EXP.break_: return CTFEExp.breakexp;
case EXP.continue_: return CTFEExp.continueexp;
case EXP.goto_: return CTFEExp.gotoexp;
default: return e.copy();
}
return -1;
}
// Return index of the field, or -1 if not found
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(VarDeclaration v)
private:
// Ensure that the union is suitably aligned.
align(8) union _AnonStruct_u
{
ClassDeclaration cd = originalClass();
size_t fieldsSoFar = 0;
for (size_t j = 0; j < value.elements.length; j++)
{
while (j - fieldsSoFar >= cd.fields.length)
{
fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (v == v2)
{
return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
char[__traits(classInstanceSize, Expression)] exp;
char[__traits(classInstanceSize, IntegerExp)] integerexp;
char[__traits(classInstanceSize, ErrorExp)] errorexp;
char[__traits(classInstanceSize, RealExp)] realexp;
char[__traits(classInstanceSize, ComplexExp)] complexexp;
char[__traits(classInstanceSize, SymOffExp)] symoffexp;
char[__traits(classInstanceSize, StringExp)] stringexp;
char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp;
char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp;
char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp;
char[__traits(classInstanceSize, CompoundLiteralExp)] compoundliteralexp;
char[__traits(classInstanceSize, NullExp)] nullexp;
char[__traits(classInstanceSize, DotVarExp)] dotvarexp;
char[__traits(classInstanceSize, AddrExp)] addrexp;
char[__traits(classInstanceSize, IndexExp)] indexexp;
char[__traits(classInstanceSize, SliceExp)] sliceexp;
char[__traits(classInstanceSize, VectorExp)] vectorexp;
}
override void accept(Visitor v)
{
v.visit(this);
}
_AnonStruct_u u;
}
void emplaceExp(T : Expression, Args...)(void* p, Args args)
{
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)
{
memcpy(p, cast(void*)e, e.size);
}
// Generate an error message when this exception is not caught
void generateUncaughtError(ThrownExceptionExp tee)
{
UnionExp ue = void;
Expression e = resolveSlice((*tee.thrown.value.elements)[0], &ue);
StringExp se = e.toStringExp();
error(tee.thrown.loc, "uncaught CTFE exception `%s(%s)`", tee.thrown.type.toChars(), se ? se.toChars() : e.toChars());
/* Also give the line where the throw statement was. We won't have it
* in the case where the ThrowStatement is generated internally
* (eg, in ScopeStatement)
*/
if (tee.loc.isValid() && !tee.loc.equals(tee.thrown.loc))
.errorSupplemental(tee.loc, "thrown from here");
}
/*************************
@ -121,100 +144,6 @@ int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pur
return -1;
}
/***********************************************************
* Fake class which holds the thrown exception.
* Used for implementing exception handling.
*/
extern (C++) final class ThrownExceptionExp : Expression
{
ClassReferenceExp thrown; // the thing being tossed
extern (D) this(const ref Loc loc, ClassReferenceExp victim) @safe
{
super(loc, EXP.thrownException);
this.thrown = victim;
this.type = victim.type;
}
override const(char)* toChars() const
{
return "CTFE ThrownException";
}
// Generate an error message when this exception is not caught
extern (D) void generateUncaughtError()
{
UnionExp ue = void;
Expression e = resolveSlice((*thrown.value.elements)[0], &ue);
StringExp se = e.toStringExp();
error(thrown.loc, "uncaught CTFE exception `%s(%s)`", thrown.type.toChars(), se ? se.toChars() : e.toChars());
/* Also give the line where the throw statement was. We won't have it
* in the case where the ThrowStatement is generated internally
* (eg, in ScopeStatement)
*/
if (loc.isValid() && !loc.equals(thrown.loc))
.errorSupplemental(loc, "thrown from here");
}
override void accept(Visitor v)
{
v.visit(this);
}
}
/***********************************************************
* This type is only used by the interpreter.
*/
extern (C++) final class CTFEExp : Expression
{
extern (D) this(EXP tok)
{
super(Loc.initial, tok);
type = Type.tvoid;
}
override const(char)* toChars() const
{
switch (op)
{
case EXP.cantExpression:
return "<cant>";
case EXP.voidExpression:
return "cast(void)0";
case EXP.showCtfeContext:
return "<error>";
case EXP.break_:
return "<break>";
case EXP.continue_:
return "<continue>";
case EXP.goto_:
return "<goto>";
default:
assert(0);
}
}
extern (D) __gshared CTFEExp cantexp;
extern (D) __gshared CTFEExp voidexp;
extern (D) __gshared CTFEExp breakexp;
extern (D) __gshared CTFEExp continueexp;
extern (D) __gshared CTFEExp gotoexp;
/* Used when additional information is needed regarding
* a ctfe error.
*/
extern (D) __gshared CTFEExp showcontext;
extern (D) static bool isCantExp(const Expression e) @safe
{
return e && e.op == EXP.cantExpression;
}
extern (D) static bool isGotoExp(const Expression e) @safe
{
return e && e.op == EXP.goto_;
}
}
// True if 'e' is CTFEExp::cantexp, or an exception
bool exceptionOrCantInterpret(const Expression e) @safe
{

View file

@ -38,6 +38,7 @@ import dmd.init;
import dmd.intrange;
import dmd.mtype;
import dmd.opover;
import dmd.optimize;
import dmd.root.ctfloat;
import dmd.common.outbuffer;
import dmd.root.rmem;

View file

@ -152,6 +152,7 @@ import dmd.identifier;
import dmd.mtype;
import dmd.root.ctfloat;
import dmd.common.outbuffer;
import dmd.optimize;
import dmd.root.aav;
import dmd.root.string;
import dmd.root.stringtable;

View file

@ -793,7 +793,7 @@ extern (C++) final class Module : Package
}
else
{
const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
const bool doUnittests = global.params.parsingUnittestsRequired();
scope p = new Parser!AST(this, buf, cast(bool) docfile, global.errorSink, &global.compileEnv, doUnittests);
p.transitionIn = global.params.v.vin;
p.nextToken();

View file

@ -57,6 +57,7 @@ import dmd.nogc;
import dmd.nspace;
import dmd.objc;
import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.root.array;
import dmd.root.filename;
@ -1951,7 +1952,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
const len = buf.length;
buf.writeByte(0);
const str = buf.extractSlice()[0 .. len];
const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
const bool doUnittests = global.params.parsingUnittestsRequired();
auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut);
scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
p.transitionIn = global.params.v.vin;
@ -3384,9 +3385,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
{
OutBuffer buf;
MODtoBuffer(buf, tf.mod);
.error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, buf.peekChars());
import core.bitop;
auto mods = MODtoChars(tf.mod);
.error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods);
if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1)
.errorSupplemental(funcdecl.loc,
"did you mean to use `%s(%s)` as the return type?", mods, tf.next.toChars());
tf.mod = 0; // remove qualifiers
}

View file

@ -69,6 +69,7 @@ import dmd.initsem;
import dmd.location;
import dmd.mtype;
import dmd.opover;
import dmd.optimize;
import dmd.root.array;
import dmd.common.outbuffer;
import dmd.rootobject;

File diff suppressed because it is too large Load diff

View file

@ -50,7 +50,10 @@ struct Symbol; // back end symbol
Expression *ctfeInterpret(Expression *e);
void expandTuples(Expressions *exps, Identifiers *names = nullptr);
StringExp *toUTF8(StringExp *se, Scope *sc);
Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc);
MATCH implicitConvTo(Expression *e, Type *t);
Expression *toLvalue(Expression *_this, Scope *sc);
Expression *modifiableLvalue(Expression* exp, Scope *sc);
typedef unsigned char OwnedBy;
enum
@ -99,9 +102,6 @@ public:
virtual complex_t toComplex();
virtual StringExp *toStringExp();
virtual bool isLvalue();
virtual Expression *toLvalue(Scope *sc, Expression *e);
virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
virtual Expression *resolveLoc(const Loc &loc, Scope *sc);
virtual bool checkType();
virtual bool checkValue();
Expression *addressOf();
@ -244,7 +244,6 @@ public:
real_t toImaginary() override;
complex_t toComplex() override;
Optional<bool> toBool() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
dinteger_t getInteger() { return value; }
template<int v>
@ -254,7 +253,6 @@ public:
class ErrorExp final : public Expression
{
public:
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
static ErrorExp *errorexp; // handy shared value
@ -302,7 +300,6 @@ public:
static IdentifierExp *create(const Loc &loc, Identifier *ident);
bool isLvalue() override final;
Expression *toLvalue(Scope *sc, Expression *e) override final;
void accept(Visitor *v) override { v->visit(this); }
};
@ -320,7 +317,6 @@ public:
DsymbolExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -331,8 +327,7 @@ public:
ThisExp *syntaxCopy() override;
Optional<bool> toBool() override;
bool isLvalue() override final;
Expression *toLvalue(Scope *sc, Expression *e) override final;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -370,8 +365,6 @@ public:
StringExp *toStringExp() override;
Optional<bool> toBool() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
size_t numberOfCodeUnits(int tynto = 0) const;
void writeTo(void* dest, bool zero, int tyto = 0) const;
@ -469,7 +462,6 @@ public:
static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -501,7 +493,6 @@ public:
FuncDeclaration *fd;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
@ -575,8 +566,6 @@ public:
static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true);
bool equals(const RootObject * const o) const override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -589,7 +578,6 @@ public:
OverloadSet *vars;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -678,7 +666,6 @@ public:
Expression *e1;
UnaExp *syntaxCopy() override;
Expression *resolveLoc(const Loc &loc, Scope *sc) override final;
void accept(Visitor *v) override { v->visit(this); }
};
@ -701,8 +688,6 @@ class BinAssignExp : public BinExp
{
public:
bool isLvalue() override final;
Expression *toLvalue(Scope *sc, Expression *ex) override final;
Expression *modifiableLvalue(Scope *sc, Expression *e) override final;
void accept(Visitor *v) override { v->visit(this); }
};
@ -767,8 +752,6 @@ public:
d_bool hasOverloads;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -821,7 +804,6 @@ public:
CallExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -836,8 +818,6 @@ class PtrExp final : public UnaExp
{
public:
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -882,7 +862,6 @@ public:
CastExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -903,7 +882,6 @@ class VectorArrayExp final : public UnaExp
{
public:
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -926,8 +904,6 @@ private:
public:
SliceExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
@ -953,8 +929,6 @@ class DelegatePtrExp final : public UnaExp
{
public:
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -962,8 +936,6 @@ class DelegateFuncptrExp final : public UnaExp
{
public:
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -978,7 +950,6 @@ public:
ArrayExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -997,8 +968,6 @@ public:
d_bool isGenerated;
d_bool allowCommaExp;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -1012,8 +981,6 @@ public:
IndexExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -1047,7 +1014,6 @@ public:
MemorySet memset;
bool isLvalue() override final;
Expression *toLvalue(Scope *sc, Expression *ex) override final;
void accept(Visitor *v) override { v->visit(this); }
};
@ -1292,8 +1258,6 @@ public:
CondExp *syntaxCopy() override;
bool isLvalue() override;
Expression *toLvalue(Scope *sc, Expression *e) override;
Expression *modifiableLvalue(Scope *sc, Expression *e) override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -1320,35 +1284,30 @@ public:
class FileInitExp final : public DefaultInitExp
{
public:
Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class LineInitExp final : public DefaultInitExp
{
public:
Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class ModuleInitExp final : public DefaultInitExp
{
public:
Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class FuncInitExp final : public DefaultInitExp
{
public:
Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
class PrettyFuncInitExp final : public DefaultInitExp
{
public:
Expression *resolveLoc(const Loc &loc, Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};

File diff suppressed because it is too large Load diff

View file

@ -250,6 +250,12 @@ extern (C++) struct Param
const(char)[] resfile;
const(char)[] exefile;
const(char)[] mapfile;
///
bool parsingUnittestsRequired()
{
return useUnitTests || ddoc.doOutput || dihdr.doOutput;
}
}
enum mars_ext = "d"; // for D source files

View file

@ -41,6 +41,7 @@ import dmd.identifier;
import dmd.init;
import dmd.mtype;
import dmd.nspace;
import dmd.optimize;
import dmd.parse;
import dmd.root.complex;
import dmd.root.ctfloat;

View file

@ -302,7 +302,7 @@ Ldone:
extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
{
//printf("GccAsmStatement.semantic()\n");
const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
const bool doUnittests = global.params.parsingUnittestsRequired();
scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink, &global.compileEnv, doUnittests);
// Make a safe copy of the token list before parsing.
@ -341,7 +341,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
e = e.expressionSemantic(sc);
// Check argument is a valid lvalue/rvalue.
if (i < s.outputargs)
e = e.modifiableLvalue(sc, null);
e = e.modifiableLvalue(sc);
else if (e.checkValue())
e = ErrorExp.get();
(*s.args)[i] = e;

View file

@ -38,6 +38,7 @@ import dmd.init;
import dmd.location;
import dmd.mtype;
import dmd.opover;
import dmd.optimize;
import dmd.statement;
import dmd.target;
import dmd.tokens;

View file

@ -3258,6 +3258,24 @@ class Lexer
scanloc.linnum = scanloc.linnum + 1;
line = p;
}
/****************************
* Print the tokens from the current `token` to the end,
* while not advancing the parser forward.
* Useful for debugging.
*/
void printRestOfTokens()
{
auto tk = &token;
while (1)
{
printf("%s ", (*tk).toChars());
if (tk.value == TOK.endOfFile)
break;
tk = peek(tk);
}
printf("\n");
}
}

View file

@ -34,6 +34,7 @@ import dmd.id;
import dmd.identifier;
import dmd.location;
import dmd.mtype;
import dmd.optimize;
import dmd.statement;
import dmd.tokens;
import dmd.typesem;

View file

@ -272,9 +272,9 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
* Returns:
* Constant folded version of `e`
*/
Expression Expression_optimize(Expression e, int result, bool keepLvalue)
Expression optimize(Expression e, int result, bool keepLvalue = false)
{
//printf("Expression_optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
//printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
Expression ret = e;
void errorReturn()
@ -288,7 +288,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
if (!e)
return false;
Expression ex = Expression_optimize(e, flags, keepLvalue);
Expression ex = optimize(e, flags, keepLvalue);
if (ex.op == EXP.error)
{
ret = ex; // store error result
@ -591,7 +591,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
Expression add = new AddExp(ae.loc, ex, new IntegerExp(ae.e2.loc, offset, ae.e2.type));
add.type = e.type;
ret = Expression_optimize(add, result, keepLvalue);
ret = optimize(add, result, keepLvalue);
return;
}
}
@ -1239,7 +1239,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
ret = new CastExp(e.loc, ret, Type.tvoid);
ret.type = e.type;
}
ret = Expression_optimize(ret, result, false);
ret = optimize(ret, result, false);
return;
}
expOptimize(e.e2, WANTvalue);
@ -1294,7 +1294,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// `["c"] ~ "a" ~ "b"` becoming `["c"] ~ "ab"`
scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2);
cex.type = e.type;
Expression ex = Expression_optimize(cex, result, false);
Expression ex = optimize(cex, result, false);
if (ex != cex)
{
e.e1 = ce1.e1;
@ -1323,9 +1323,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
const opt = e.econd.toBool();
if (opt.hasValue(true))
ret = Expression_optimize(e.e1, result, keepLvalue);
ret = optimize(e.e1, result, keepLvalue);
else if (opt.hasValue(false))
ret = Expression_optimize(e.e2, result, keepLvalue);
ret = optimize(e.e2, result, keepLvalue);
else
{
expOptimize(e.e1, result, keepLvalue);

View file

@ -54,6 +54,7 @@ import dmd.nspace;
import dmd.ob;
import dmd.objc;
import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.root.filename;
import dmd.common.outbuffer;
@ -917,7 +918,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (f.isref)
{
// Function returns a reference
exp = exp.toLvalue(sc2, exp);
exp = exp.toLvalue(sc2);
checkReturnEscapeRef(sc2, exp, false);
exp = exp.optimize(WANTvalue, /*keepLvalue*/ true);
}

View file

@ -55,6 +55,7 @@ import dmd.location;
import dmd.mtype;
import dmd.mustuse;
import dmd.nogc;
import dmd.optimize;
import dmd.opover;
import dmd.parse;
import dmd.common.outbuffer;
@ -4887,7 +4888,7 @@ private Statements* flatten(Statement statement, Scope* sc)
const len = buf.length;
buf.writeByte(0);
const str = buf.extractSlice()[0 .. len];
const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
const bool doUnittests = global.params.parsingUnittestsRequired();
auto loc = adjustLocForMixin(str, cs.loc, global.params.mixinOut);
scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
p.transitionIn = global.params.v.vin;

View file

@ -22,6 +22,7 @@ import dmd.expressionsem;
import dmd.globals;
import dmd.identifier;
import dmd.mtype;
import dmd.optimize;
import dmd.root.array;
import dmd.common.outbuffer;
import dmd.tokens;

View file

@ -42,6 +42,7 @@ import dmd.identifier;
import dmd.location;
import dmd.mtype;
import dmd.nogc;
import dmd.optimize;
import dmd.parse;
import dmd.root.array;
import dmd.root.speller;
@ -1875,16 +1876,24 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);
auto o = (*e.args)[0];
Type t = isType(o);
AggregateDeclaration ad = t ? isAggregate(t) : null;
// Interfaces don't have an init symbol and hence cause linker errors
if (!ad || ad.isInterfaceDeclaration())
ErrorExp badArgument()
{
error(e.loc, "struct / class type expected as argument to __traits(initSymbol) instead of `%s`", o.toChars());
return ErrorExp.get();
}
Type t = isType(o);
if (!t || t.isTypeEnum())
return badArgument();
AggregateDeclaration ad = isAggregate(t);
// Interfaces don't have an init symbol and hence cause linker errors
if (!ad || ad.isInterfaceDeclaration())
return badArgument();
Declaration d = new SymbolDeclaration(ad.loc, ad);
d.type = Type.tvoid.arrayOf().constOf();
d.storage_class |= STC.rvalue;

View file

@ -53,6 +53,7 @@ import dmd.visitor;
import dmd.mtype;
import dmd.objc;
import dmd.opover;
import dmd.optimize;
import dmd.parse;
import dmd.root.complex;
import dmd.root.ctfloat;
@ -1098,7 +1099,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (isRefOrOut && !isAuto &&
!(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
global.params.rvalueRefParam != FeatureState.enabled)
e = e.toLvalue(sc, e);
e = e.toLvalue(sc);
fparam.defaultArg = e;
return (e.op != EXP.error);
@ -3748,7 +3749,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
}
// check before alias resolution; the alias itself might be deprecated!
if (s.isAliasDeclaration)
e.checkDeprecated(sc, s);
s.checkDeprecated(e.loc, sc);
s = s.toAlias();
if (auto em = s.isEnumMember())
@ -5009,7 +5010,7 @@ RootObject compileTypeMixin(TypeMixin tm, ref const Loc loc, Scope* sc)
const len = buf.length;
buf.writeByte(0);
const str = buf.extractSlice()[0 .. len];
const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
const bool doUnittests = global.params.parsingUnittestsRequired();
auto locm = adjustLocForMixin(str, loc, global.params.mixinOut);
scope p = new Parser!ASTCodegen(locm, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
p.transitionIn = global.params.v.vin;

View file

@ -79,14 +79,11 @@ version (Win64)
{
void checkReal(in real p)
{
// ref for x87 real, value for double-precision real
static assert(__traits(isRef, p) == (real.sizeof > 8));
}
struct RGB { ubyte r, g, b; }
void checkNonPowerOf2(in RGB p)
{
static assert(__traits(isRef, p));
}
}
else version (X86_64) // Posix x86_64
@ -94,7 +91,6 @@ else version (X86_64) // Posix x86_64
struct Empty {} // 1 dummy byte passed on the stack
void checkEmptyStruct(in Empty p)
{
static assert(!__traits(isRef, p));
}
static if (is(__vector(double[4])))
@ -102,7 +98,6 @@ else version (X86_64) // Posix x86_64
struct AvxVectorWrapper { __vector(double[4]) a; } // 256 bits
void checkAvxVector(in AvxVectorWrapper p)
{
static assert(!__traits(isRef, p));
}
}
}
@ -111,6 +106,5 @@ else version (AArch64)
alias HVA = __vector(float[4])[4]; // can be passed in 4 vector registers
void checkHVA(in HVA p)
{
static assert(!__traits(isRef, p));
}
}

View file

@ -1,10 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail212.d(14): Error: function `fail212.S.bar` without `this` cannot be `const`
fail_compilation/fail212.d(10): Error: function `fail212.baz` without `this` cannot be `const`
fail_compilation/fail212.d(10): did you mean to use `const(int)` as the return type?
fail_compilation/fail212.d(18): Error: function `fail212.S.bar` without `this` cannot be `const`
---
*/
const int baz();
struct S
{
void foo() const

View file

@ -154,27 +154,25 @@ struct WithDtor
@safe pure nothrow @nogc:
// By value
void testin1(in uint p) { static assert(!__traits(isRef, p)); }
void testin1(in uint p) { }
// By ref because of size
void testin2(in ulong[64] p) { static assert(__traits(isRef, p)); }
void testin2(in ulong[64] p) { }
// By value or ref depending on size (or structs always passed by reference)
void testin3(in ValueT p) { static assert(!__traits(isRef, p) || true); }
void testin3(in RefT p) { static assert(__traits(isRef, p)); }
void testin3(in ValueT p) { }
void testin3(in RefT p) { }
// By ref because of size (or arrays always passed by reference)
void testin4(in ValueT[64] p) { static assert(__traits(isRef, p)); }
void testin4(in RefT[4] p) { static assert(__traits(isRef, p)); }
void testin4(in ValueT[64] p) { }
void testin4(in RefT[4] p) { }
// By ref because of non-copyability
void testin5(in NonCopyable noncopy) { static assert(__traits(isRef, noncopy)); }
static assert(testin5.mangleof == "_D9previewin7testin5FNaNbNiNfIKSQBe11NonCopyableZv"); // incl. `ref`
void testin5(in NonCopyable noncopy) { }
// By ref because of postblit
void testin6(in WithPostblit withpostblit) { static assert(__traits(isRef, withpostblit)); }
void testin6(in WithPostblit withpostblit) { }
// By ref because of copy ctor
void testin7(in WithCopyCtor withcopy) { static assert(__traits(isRef, withcopy)); }
void testin7(in WithCopyCtor withcopy) { }
// By ref because of dtor
void testin8(in WithDtor withdtor, scope bool* isTestOver)
{
static assert(__traits(isRef, withdtor));
if (isTestOver)
*isTestOver = true;
}

View file

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

View file

@ -594,6 +594,10 @@ if (!is(immutable T == immutable bool))
assert(capacity == values.length); // We check that reserve has been called before the loop.
}
/// ditto
// needed when T is an array and only one argument is passed
this(T single) { __ctor!T(single); }
/**
* Constructor taking an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
*/
@ -1282,6 +1286,13 @@ if (!is(immutable T == immutable bool))
}
}
@system unittest
{
import std.algorithm.comparison : equal;
auto a = Array!string("test");
assert(a[].equal(["test"]));
}
@safe unittest
{
// https://issues.dlang.org/show_bug.cgi?id=13621

View file

@ -54,6 +54,7 @@ $(UL
$(LI `trace`)
$(LI `info`)
$(LI `warning`)
#(LI `error`)
$(LI `critical`)
$(LI `fatal`)
)

View file

@ -1015,12 +1015,27 @@ See_Also:
enum bool isForwardRange(R) = isInputRange!R
&& is(typeof((R r) { return r.save; } (R.init)) == R);
/// ditto
enum bool isForwardRange(R, E) =
.isForwardRange!R && isQualifierConvertible!(ElementType!R, E);
///
@safe unittest
{
static assert(!isForwardRange!(int));
static assert( isForwardRange!(int[]));
static assert( isForwardRange!(inout(int)[]));
static assert( isForwardRange!(int[], const int));
static assert(!isForwardRange!(int[], immutable int));
static assert(!isForwardRange!(const(int)[], int));
static assert( isForwardRange!(const(int)[], const int));
static assert(!isForwardRange!(const(int)[], immutable int));
static assert(!isForwardRange!(immutable(int)[], int));
static assert( isForwardRange!(immutable(int)[], const int));
static assert( isForwardRange!(immutable(int)[], immutable int));
}
@safe unittest