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:
parent
da332ce109
commit
87b9a01ea7
34 changed files with 1624 additions and 1539 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
module dmd.compiler;
|
||||
|
||||
import dmd.arraytypes;
|
||||
import dmd.ctfeexpr;
|
||||
import dmd.dmodule;
|
||||
import dmd.expression;
|
||||
import dmd.mtype;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -54,6 +54,7 @@ $(UL
|
|||
$(LI `trace`)
|
||||
$(LI `info`)
|
||||
$(LI `warning`)
|
||||
#(LI `error`)
|
||||
$(LI `critical`)
|
||||
$(LI `fatal`)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue